如何从 pl/pgsql 中的深层 UDT 访问数组?

How can I access arrays from deep UDTs in pl/pgsql?

我有一个正在处理的存储过程,它使用一组复合类型来 return 之前需要我 4 个不同的查询。我 运行 遇到的问题是解决某些元素未按预期工作的问题。给定如下类型结构:

CREATE TYPE mytype3 ( field1 TEXT, field2 TEXT );
CREATE TYPE mytype2 ( field1 INTEGER, field2 mytype3[] );
CREATE TYPE mytype1 ( field1 TEXT, field2 mytype2[] );

我如何处理特定的 "mytype3" 元素?我希望它是这样的:

CREATE FUNCTION get_item( IN n VARCHAR(64) )RETURNS mytype1 AS $$
DECLARE
  iid INTEGER;
  r RECORD;
  output mytype1;
BEGIN
  iid=(SELECT id FROM idlist WHERE name=n LIMIT 1);

  SELECT field1, NULL FROM table1 WHERE id=iid LIMIT 1 INTO output;
  SELECT array( SELECT (field2, NULL) FROM table2 WHERE id=iid)
    AS foo INTO output.field2;
  FOR r IN SELECT id,field1,field2 FROM table3 WHERE id=iid LOOP
    output.field2[r.id].field2 := 
       array_append(output.field2[r.id].field2, (r.field1, r.field2));
  END LOOP;
  RETURN output;
END
$$ LANGUAGE plpgsql STABLE;

但这似乎在第一个数组索引处有语法错误。我已经阅读了大量文档并进行了谷歌搜索,但似乎没有任何内容进入如此复杂的 UDT。

这是 PLpgSQL 中真正缺失的功能之一。 assign 语句不支持复杂的左半部分表达式。左侧可以是记录或复合类型的字段或数组字段。但是不支持混合。你应该使用辅助变量:

DECLARE
  var1 customtype;
  var2 customtype[];
BEGIN
  ...
  FOR r IN SELECT ...
    -- left part can be (only these simple variants are supported)
    var1.field := ..
    var2[r.id] := ..

此外,您的代码是错误的 - a) 您正在使用类型类型 (mytypex) 作为字段名称。 b) 你的类型是循环的——mytype1 使用 mytype2 而 mytype2 使用 mytype1

请参阅 https://www.postgresql.org/docs/current/static/plpgsql-statements.html - 赋值 - 如前所述,此类语句中的表达式是通过发送到主函数的 SQL SELECT 命令求值的数据库引擎。表达式必须产生单个值(如果变量是行或记录变量,则可能是行值)。目标变量可以是简单变量(可选地用块名称限定)、行或记录变量的字段,或者作为简单变量或字段的数组元素。可以使用等号 (=) 代替 PL/SQL-compliant :=。

PLpgSQL 语言是非常静态的语言,使用过多的嵌套结构是不好的做法(在 PG 9.5 之前可能会很慢)。