PL/pgSQL: 访问自定义类型数组元素的字段

PL/pgSQL: accessing fields of an element of an array of custom type

我定义了一个自定义类型:

create type pg_temp.MYTYPE as (f1 int, f2 text);  

然后,在一个函数或块中,我声明了一个这样类型的数组:

declare ax MYTYPE[];

我可以通过熟悉的语法访问元素 ax[1].f1,但只是为了阅读。
当我使用相同的语法设置字段时,出现语法错误。

create type pg_temp.MYTYPE as (f1 int, f2 text);

do $$
declare x MYTYPE;
declare ax MYTYPE[];
declare f int;
begin

    x.f1 = 10;
    x.f2 = 'hello';

    --assigning an element: OK
    ax[1] = x;

    --reading an element's field: OK
    f = ax[1].f1;

    --writing an elememt's field: SYNTAX ERROR: 

    ax[1].f1 = f;

end; $$

错误如下:

psql:test.sql:28: ERROR:  syntax error at or near "."
LINE 20:  ax[1].f1 = f;
          ^

我也试过语法 (ax[1]).f1 得到了同样的结果。
执行此操作的正确语法是什么?

Postgres 服务器版本:9.2.2

PLpgSQL有时很简单,也许是太简单了。赋值语句的左边部分是一个例子——左边只能是变量、记录字段或数组字段。不支持任何复杂的左半部分表达式。​​

您需要一个数组元素类型的辅助变量。

DECLARE aux MTYPE;

aux := ax[1];
aux.f := 100000;
ax[1] := aux;

这对 plpgsql 来说似乎特别不合理,因为 SQL 本身 可以 很好地更新一个复合类型的字段数组。

演示:

CREATE TEMP TABLE mytype (f1 int, f2 text);

CREATE TEMP TABLE mycomp (c mytype);
INSERT INTO mycomp VALUES ('(10,hello)');

UPDATE mycomp
SET    c.f1 = 12     -- note: without parentheses
WHERE  (c).f1 = 10;  -- note: with parentheses

TABLE mycomp;
     c
------------
 (12,hello)
CREATE TEMP TABLE mycomparr (ca mytype[]);
INSERT INTO mycomparr VALUES ('{"(10,hello)"}');

UPDATE mycomparr
SET    ca[1].f1 = 12      -- works!
WHERE  (ca[1]).f1  = 10;

TABLE mycomparr;
       ca
----------------
 {"(12,hello)"}

我想知道为什么 plpgsql 没有实现相同的功能?

尽管如此,另一种可能的解决方法是在临时 table:

上使用 UPDATE
DO
$$
DECLARE
   ax mytype[] := '{"(10,hello)"}';
BEGIN
   CREATE TEMP TABLE tmp_ax ON COMMIT DROP AS SELECT ax;

   UPDATE tmp_ax SET ax[1].f1 = 12;
   -- WHERE  (ax[1]).f1  = 10;  -- not necessary while only 1 row.

   SELECT t.ax INTO ax FROM tmp_ax t;  -- table-qualify column!

   RAISE NOTICE '%', ax;
END
$$;

这比 的开销要多。我不会将它用于简单的情况。但是,如果您有很多作业,使用临时 table.

可能仍然值得