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

时间:2017-04-27 16:44:13

标签: postgresql plpgsql

我有一个正在处理的存储过程,它使用一组复合类型来返回之前带有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。

1 个答案:

答案 0 :(得分:1)

这是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命令来计算的。表达式必须产生单个值(如果变量是行或记录变量,则可能是行值)。目标变量可以是简单变量(可选地使用块名称限定),行或记录变量的字段,或者是简单变量或字段的数组元素。可以使用Equal(=)代替PL / SQL兼容:=。

PLpgSQL语言是非常静态的语言,并且使用过于嵌套的结构是不好的做法(并且在旧的PG上比9.5可能非常慢)。