处理错误 "record or row variable cannot be part of multiple-item INTO list"

Dealing with error "record or row variable cannot be part of multiple-item INTO list"

这个 "workaround" 有 "cleaner" 语法吗?

我要处理以下对象:

create type token as(tp varchar(20), val varchar(128));
create or replace
function p_post_token
         (      token_type varchar,
         ,inout token_new  token
         ,inout tokens_all token[]
         ,  out b1         boolean
         ,  out b2         boolean
         ,  out b3         boolean
         ) as...

该函数有一些(长)逻辑,但最终它是:

  1. 根据某些条件修改"new"记录,
  2. 将 "new" 记录添加到 "all" 数组,
  3. 清空 "new" 记录,
  4. 为输出设置一些布尔值。

当我按如下方式调用我的函数时(来自 Oracle PL/SQL 的翻译):

do $$
declare
  lb1 boolean;
  lb2 boolean;
  lb3 boolean;
  --
  lr_token  token;
  lt_tokens token[];
begin
  select * into lr_token, lt_tokens, lb1, lb2, lb3
    from p_post_token('', lr_token, lt_tokens);
end$$;

我收到错误:

ERROR:  record or row variable cannot be part of multiple-item INTO list
LINE 10:       select * into lr_token, lt_tokens, lb1, lb2, lb3

我被建议的解决方法是:

do $$
declare
  lb1 boolean;
  lb2 boolean;
  lb3 boolean;
  --
  lr_token  token;
  lt_tokens token[];
  --
  r record;
begin
  select * into r
    from p_post_token('', lr_token, lt_tokens);
  lr_token  := r.token_new;
  lt_tokens := r.tokens_all;
  lb1       := r.b1;
  lb2       := r.b2;
  lb3       := r.b3;
end$$;

这行得通,但我必须在 十几个 处调用函数 p_post_token,然后编写这样的代码,嗯, 是 "too long".

这是从具有 INOUT/OUT 记录参数 + 其他 INOUT/OUT 参数的函数读取输出的唯一方法吗?有(希望)"one-liner" 方法吗?

不可能用一个语句来完成您的要求。此限制是由于一些较旧的实现而无法更改,因为 PostgreSQL 开发人员不应该破坏兼容性。记录类型的解决方法是一种可能。

我的一位同事提出了一个(恕我直言)非常 easier/better 的解决方法。将记录参数转换为数组。函数声明将变为:

function p_post_token
     (      token_type varchar
     ,inout token_new  token[] --<< this turned from record to array
     ,inout tokens_all token[]
     ,  out b1         boolean
     ,  out b2         boolean
     ,  out b3         boolean
     ) as...

... 让代码(内部)只处理数组中的一条记录。 这在处理记录时避免了很多 "extra" 代码。

然后对函数的调用变成一行(简单直观,再次恕我直言):

do $$
declare
  lb1 boolean;
  lb2 boolean;
  lb3 boolean;
  --
  lr_token  token[];
  lt_tokens token[];
begin
  select * p_post_token('', lr_token, lt_tokens)
    into lr_token, lt_tokens, lb1, lb2, lb3;
end$$;

我希望这可以帮助其他正在为同样的事情而苦苦挣扎的人。

干杯!