tin*_*lyx 9 postgresql set-returning-functions
为什么在 SELECT 列表中使用 Set Returning Function (SRF) 与在 FROM 子句中使用 SRF 在行为上存在差异?
例如,对于返回 2 行的简单 SRF:
CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
RETURNS SETOF record AS $$
SELECT 1,1
UNION
SELECT 2,2;
$$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
SELECT gen_series();
返回两个单列行,每个行包含一条记录:
=> gen_series
------------
(1,1)
(2,2)
(2 rows)
Run Code Online (Sandbox Code Playgroud)
而SELECT * FROM gen_series();
返回扩展记录的两行:
=> column1 | column2
---------+---------
1 | 1
2 | 2
(2 rows)
Run Code Online (Sandbox Code Playgroud)
相比之下,如果 SRF 返回单个列,则在 SELECT 或 FROM 子句中调用 SRF 没有区别。例如:
=> SELECT generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
=> SELECT * FROM generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
Run Code Online (Sandbox Code Playgroud)
我的问题是:
我不太明白为什么在第二种情况下,SRF 行为与第一种情况不同,只是因为返回的表只有一列。就类型、元组和集合而言,这真的是一致的行为吗?
导致不同行为的两种情况有什么区别?
SRF可以用作如上所示的表格,但表格也可以用来代替SRF吗?例如
SELECT my_table;
Run Code Online (Sandbox Code Playgroud)显然,这是SELECT my_SRF();
不可能的,但为什么是可能的,而
SELECT my_table;
不允许(在关系和数学方面)?
Postgres 对简单情况的处理方式有所不同。多列被视为复合类型(表行),仅使用 进行分解SELECT * FROM ...
,而标量类型的单列被视为复合类型,没有添加复合类型包装器。因此产生与简单情况SELECT my_SRF()
相同的结果。关于表函数的手册:SELECT * FROM my_SRF()
表函数是生成一组行的函数,这些行由基本数据类型(标量类型)或复合数据类型(表行)组成。
我同意这很令人困惑,而且你不是第一个感到困惑的人。(不过,请考虑替代方案:在单个列周围添加复合类型包装器可能会更加令人困惑。)
但不像Postgres 10之前列表中的多个SRF 函数所发生的那样令人困惑。这个问题已被永久修复:SELECT
标准的 SQL 方式是将 SRF 函数移至FROM
子句中。使用LATERAL
联接对表列进行操作。手册建议:
LATERAL
当调用多个返回集合的函数时,该语法产生的结果并不令人意外,因此通常应该使用该语法。