记录数组 select 中的奇怪错误

Strange error in the select of the array of records

据我了解,Postgres 支持 select 复杂类型数组 - 记录 (tables)。我发现 所以我在我的 PLPGSQL 函数中尝试这样的代码:

...
DECLARE
  deleting my_table[];
BEGIN
  deleting := ARRAY(SELECT mt.* FROM table1 t1
    INNER JOIN table2 t2 ON t2.id=t1.table1
    INNER JOIN my_table mt ON mt.id=t2.my_table
    WHERE t1.x=10);
...
END;
$$;

只是简单的例子来说明错误。错误是:

SQL Error [42601]: ERROR: subquery must return only one column
where: PL/pgSQL function xxx(...) line 6 at assignment

错误在赋值 deleting := ARRAY(SELECT mt.* ...) 中(我直接在这一行之后用调试 RAISE 验证了它)。但它有什么问题呢?我想 select ALL columns 确定,并且我的数组类型是 mt table 的类型。它看起来类似于提到的 Whosebug 的回答恕我直言。 TBH 我知道只有一种替代方法可以在不查询记录数组的情况下实现相同的效果:多条记录 - 每列一个看起来是虚拟的。

有人会提示正确的语法吗?任何帮助都会非常有用。

PS。我使用 Postgres 12.

你可以使用一个技巧(它等于@a_horse_with_no_name注意-这里只是更详细的描述)。任何 Postgres 的 table 都有一些不可见的列。一,具有与 table 名称相同的名称,以复合格式保存 table 的所有列。我不知道,这个功能是什么时候引入的——它已经很老了(可能是 SQL 之前的年龄):

postgres=# select * from foo;
┌────┬────┐
│ a  │ b  │
╞════╪════╡
│ 10 │ 20 │
│ 30 │ 40 │
└────┴────┘
(2 rows)

postgres=# select foo from foo ;
┌─────────┐
│   foo   │
╞═════════╡
│ (10,20) │
│ (30,40) │
└─────────┘
(2 rows)

有时这个功能非常有用:

postgres=# do $$             
declare a foo[];
begin
  a := array(select foo from foo);
  raise notice '%', a;
end;
$$;
NOTICE:  {"(10,20)","(30,40)"}
DO

如果你不知道这个技巧,或者如果你更喜欢精确的列规范,你可以使用行构造函数:

postgres=# do $$
declare a foo[];
begin
  a := array(select row(x.a,x.b) from foo x);
  raise notice '%', a;
end;
$$;
NOTICE:  {"(10,20)","(30,40)"}
DO

在这两种情况下,结果都是一个复合值数组。注意 - 内容仅保存在内存中,您可能会耗尽大量内存(尽管大小限制为 1GB)。另一方面,它非常实用地替换临时 tables 或 table 的变量。创建和删除临时 table 相对缓慢且昂贵,并且当内容不是太大,并且不需要 table 的全部功能(索引、统计信息、会话相关生命周期)时), 那么复合数组可以很好的替代(完美)临时 tables.