通常,您可以使用@Daniel 提供的简单语法扩展众所周知的行类型(也称为记录类型、复杂类型、复合类型):
SELECT i.name, (compute_prices(i.id, current_date)).*
FROM items i
WHERE i.type = 404;
但是,如果你的描述是准确的......
compute_prices sp 返回一组记录。
...我们正在处理匿名记录。Postgres 不知道如何扩展匿名记录,绝望地抛出一个 EXCEPTION:
ERROR: a column definition list is required for functions returning "record"
PostgreSQL 9.3
Postgres 9.3 中有一个解决方案。LATERAL
,正如@a_horse 在评论中提到的那样:
SELECT i.name, sp.*
FROM items i
LEFT JOIN LATERAL compute_prices(i.id,current_date) AS sp (
price numeric(15,2)
,discount numeric(5,2)
,taxes numeric(5,2)
) ON TRUE
WHERE i.type = 404;
手册中的详细信息。
PostgreSQL 9.2 及更早版本
事情变得多毛。这是一种解决方法:编写一个包装函数,将您的匿名记录转换为众所周知的类型:
CREATE OR REPLACE FUNCTION compute_prices_wrapper(int, date)
RETURNS TABLE (
price numeric(15,2)
,discount numeric(5,2)
,taxes numeric(5,2)
) AS
$func$
SELECT * FROM compute_prices($1, $2)
AS t(price numeric(15,2)
,discount numeric(5,2)
,taxes numeric(5,2));
$func$ LANGUAGE sql;
然后您可以使用@Daniel 的简单解决方案,只需放入包装函数:
SELECT i.name, (compute_prices_wrapper(i.id, current_date)).*
FROM items i
WHERE i.type = 404;
PostgreSQL 8.3 及更早版本
PostgreSQL 8.3 刚刚达到 EOL,截至目前(2013 年 2 月)不受支持。
因此,如果可能,您最好升级。但如果你不能:
CREATE OR REPLACE FUNCTION compute_prices_wrapper(int, date
,OUT price numeric(15,2)
,OUT discount numeric(5,2)
,OUT taxes numeric(5,2))
RETURNS SETOF record AS
$func$
SELECT * FROM compute_prices($1, $2)
AS t(price numeric(15,2)
,discount numeric(5,2)
,taxes numeric(5,2));
$func$ LANGUAGE sql;
也可以在以后的版本中使用。
正确的解决方案是修复您的函数compute_prices()
以返回一个众所周知的类型。返回的函数SETOF record
通常是 PITA。我只戳那些用五米长的杆子。