一般来说,您可以使用
Daniel提供的简单语法扩展已知的行类型(也称为记录类型、复杂类型、组合类型)。其中包含了
well known。
SELECT i.name, (compute_prices(i.id, current_date)).*
FROM items i
WHERE i.type = 404;
然而,如果您的描述是准确的……
compute_prices sp 返回一组记录。
...... 我们正在处理匿名记录。Postgres不知道如何展开匿名记录并绝望地抛出异常:
ERROR: a column definition list is required for functions returning "record"
PostgreSQL 9.3
在PostgreSQL 9.3中有一个解决方案。如评论中所提到的,使用LATERAL
:
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已经到达生命周期终点,从现在开始不再受支持(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
类型的函数通常很麻烦。我只会用五米长的杆子去碰这些函数。