从 UDF 返回的匿名记录自动转换为众所周知的表类型

art*_*hur 8 postgresql type-conversion plpgsql functions composite-types

专有代码(我们无法更改)有一堆用户定义的函数类型:

create or replace function f() returns record as $$ ... $$
Run Code Online (Sandbox Code Playgroud)

我们通过以下方式调用它(例如):

SELECT status, log FROM f() as (status boolean, log text);
Run Code Online (Sandbox Code Playgroud)

(status boolean, log text)是 table 的行类型T。是否可以在不列出属性的情况下自动将record(或setof record返回类型)转换为T行类型?我正在寻找的是那种:

SELECT * FROM f() as T%rowtype
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 8

有一种方法。

给定一个表t和一个f()返回与该表类型匹配的匿名记录的函数:

CREATE TABLE t (id int, d date);
Run Code Online (Sandbox Code Playgroud)

你不能只是投匿名记录,因为是一个字段定义列表所需

SELECT * FROM f()
Run Code Online (Sandbox Code Playgroud)

引用SELECT 命令的手册

如果函数已定义为返回记录数据类型,则AS必须存在别名或关键字,后跟表单中的列定义列表...

大胆强调我的。

因此,虽然所有这些查询都有效:

SELECT '(1,2013-11-11)'::t;
SELECT ('(1,2013-11-11)'::t).*;
SELECT f();                      -- returning anonymous record
SELECT * FROM f() AS f(id int, d date);
Run Code Online (Sandbox Code Playgroud)

这些都没有:

SELECT * FROM f();
SELECT * FROM f()::t;
Run Code Online (Sandbox Code Playgroud)

后者引发异常:

错误:无法将类型记录转换为 t

您可以将SELECTwith 列定义列表包装到@a_horse@deszo建议的VIEWor 函数中。那会工作得很好:

CREATE OR REPLACE VIEW v1 AS
SELECT * FROM f() AS f(id int, d date);
Run Code Online (Sandbox Code Playgroud)

但这不会回答你的问题:

将记录(或 setof 记录返回类型)转换为Trowtype 而不列出属性?

单排解决方案

强制转换失败时,plpgsql 中赋值有效。

CREATE OR REPLACE function f1(OUT rec t) AS
$func$
BEGIN
rec := f();   -- assignment succeeds where cast failed (!)
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

称呼:

SELECT * FROM f1();
Run Code Online (Sandbox Code Playgroud)

虽然你也可以用这种模式编写一个集合返回函数,但我没有找到一种方法来SELECT从集合返回函数而不提供列定义列表......

->SQLfiddle