了解SELECT列表中的集返回函数(SRF)


8

为什么在SELECT列表中使用Set Returning Function(SRF)与在FROM子句中使用SRF之间在行为上有区别?

例如,对于一个简单的SRF返回2行:

CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
  RETURNS SETOF record AS $$
  SELECT 1,1
  UNION
  SELECT 2,2;
$$ LANGUAGE SQL;

SELECT gen_series(); 返回两个单列行,每个行包含一条记录:

=>  gen_series 
------------
 (1,1)
 (2,2)
(2 rows)

SELECT * FROM gen_series();返回记录扩展的两行:

=>  column1 | column2 
---------+---------
       1 |       1
       2 |       2
(2 rows)

相比之下,如果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)

我的问题是:

  1. 我不太清楚为什么在第二种情况下,SRF行为与第一种情况不同,只是因为返回的表只有一个列。就类型,元组和集合而言,这真的是一致的行为吗?

  2. 导致不同行为的两种情况之间有什么区别?

  3. SRF可以用作如上所示的表格,但是表格也可以用来替代SRF吗?例如

    SELECT my_table; 

显然,这无法完成,但是为什么SELECT my_SRF();可行却 SELECT my_table;不允许这样做(在关系和数学方面)?


SELECT my_table;是不是有效的语法
姆拉登Uzelac

Answers:


3

Postgres对简单案例的处理方式有所不同。多列被视为复合类型(表行),仅用分解SELECT * FROM ...,而标量类型的单列则被视为复合类型,不添加复合类型包装器。因此SELECT my_SRF()产生与SELECT * FROM my_SRF()简单情况相同的结果。有关表功能的手册

表函数是产生一组行的函数,这些行由基本数据类型(标量类型)或复合数据类型(表行)组成。

我同意这令人困惑,并且您不是第一个被混淆的人。(不过,请考虑替代方法:在单个列周围添加复合类型包装器可能会更加令人困惑。)

但是,没有将列表中的多个 SRF功能组合在一起时会发生的混乱SELECT。不过,这将在Postgres 10中永久改变:

对于这两种情况,安全,不易混淆的方法是将SRF函数移至该FROM子句。使用LATERAL加入,如果你需要从另一个表引用列。该手册建议:

LATERAL调用多个集合返回函数时,该语法产生的结果并不令人惊讶,通常应使用它来代替。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.