为什么允许“子查询用作表达式”返回SETOF而不是TABLE?

时间:2018-08-09 16:21:38

标签: postgresql

所以我有一个包含一些整数数组的表。

CREATE TABLE arrays (
  nums int[],
  id serial PRIMARY KEY
);

INSERT INTO arrays VALUES
  ('{1, 5, 72}', 1),
  ('{3}', 2),
  ('{32, 6}', 3);

如果我想将这些数组元素散布到单独的行中,可以使用返回SETOF INT的函数来完成,例如unnest

SELECT
  id,
  unnest(nums)
FROM arrays;

-- id   unnest
-- 1    1
-- 1    5
-- 1    72
-- 2    3
-- 3    32
-- 3    6

但是我一直认为SELECT子句中的子查询必须返回单个值! unnest返回了多个值。 Postgres只是通过为每个值复制行来处理它。但是,如果我尝试另一个返回多个值的子查询,如下所示:

SELECT
  a.id,
  (SELECT a.nums[1] UNION SELECT a.nums[2])
FROM arrays a;

-- ERROR: more than one row returned by a subquery used as an expression

出现错误。似乎应该以类似于unnest的方式来处理它。 为什么允许unnest返回多个值,但不能返回多个值?

1 个答案:

答案 0 :(得分:3)

那是PostgreSQL的疣^ H ^ H ^ H ^ Hfeature。

实际上是documented

  

返回集合的函数也可以在查询的选择列表中调用。对于查询本身生成的每一行,都会调用set-returning函数,并为函数结果集中的每个元素生成一个输出行。

     

[...]

     

PostgreSQL对查询的选择列表中的返回集合函数的行为几乎完全等同于将返回返回函数写在LATERAL FROM子句中。

请注意,{10}中的SELECT列表中有多个个集合返回函数时的行为已更改;请参阅发行说明。

我建议您不要使用此功能,并将此类功能放在它们所属的FROM列表中。