整数类型的输入语法无效:执行函数时具有复合数据类型的“(2,2)”

jia*_*ian 4 postgresql plpgsql variable-assignment rowtype

begin;
create type public.ltree as (a int, b int);
create  table public.parent_tree(parent_id int,l_tree ltree);
insert into public.parent_tree values(1,(2,2)),(2,(1,2)),(3, (1,28));
commit;
Run Code Online (Sandbox Code Playgroud)

尝试复制此答案中的解决方案:

对于复合类型的函数:

CREATE OR REPLACE FUNCTION public.get_parent_ltree
            (_parent_id int, tbl_name regclass , OUT _l_tree ltree)
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT l_tree FROM %s WHERE parent_id = $1', tbl_name)
   INTO  _l_tree
   USING _parent_id;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

执行的有效查询:

select l_tree from parent_tree where parent_id = 1;
Run Code Online (Sandbox Code Playgroud)

执行函数:

select get_parent_ltree(1,'parent_tree');
select get_parent_ltree(1,'public.parent_tree');
Run Code Online (Sandbox Code Playgroud)

我收到此错误

begin;
create type public.ltree as (a int, b int);
create  table public.parent_tree(parent_id int,l_tree ltree);
insert into public.parent_tree values(1,(2,2)),(2,(1,2)),(3, (1,28));
commit;
Run Code Online (Sandbox Code Playgroud)

第 3 行的上下文:

第3行图片

Erw*_*ter 5

输出参数_l_tree是“行变量”。(复合类型被视为行变量。)SELECT INTO将行变量的字段一一分配。手册:

可选的target是记录变量、行变量或逗号分隔的简单变量和记录/行字段列表,[...]

因此,当前(第 14 页),行或记录变量必须独立为target. 或者正如根据 Postgres 错误消息所说的那样:

ERROR:  record variable cannot be part of multiple-item INTO list
Run Code Online (Sandbox Code Playgroud)

这有效:

ERROR:  record variable cannot be part of multiple-item INTO list
Run Code Online (Sandbox Code Playgroud)

或这个:

CREATE OR REPLACE FUNCTION public.get_parent_ltree (IN  _parent_id int
                                                  , IN  _tbl_name  regclass
                                                  , OUT _l_tree    ltree)
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format('SELECT (l_tree).* FROM %s WHERE parent_id = $1', _tbl_name)
   INTO  _l_tree
   USING _parent_id;
END
$func$;
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

我同意这相当棘手。人们可能期望复合字段被视为单个字段(如简单类型)。但目前 PL/pgSQL 作业并非如此。

手册中有关复合类型的相关引用:

复合类型表示行或记录的结构;它本质上只是字段名称及其数据类型的列表。 PostgreSQL 允许以许多与使用简单类型相同的方式使用复合类型

大胆强调我的。
许多。不是全部

有关的:


旁白:考虑附加模块ltree而不是“开发自己的模块”。如果您继续使用自己的复合类型,请考虑使用不同的名称,以避免与该模块混淆/冲突。