整数类型的无效输入语法:执行函数时具有复合数据类型的“(2,2)”
Invalid input syntax for type integer: "(2,2)" with composite data type while executing function
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;
尝试复制此答案中的解决方案:
- Format specifier for integer variables in format() for EXECUTE?
对于复合类型的函数:
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 = ', tbl_name)
INTO _l_tree
USING _parent_id;
END
$func$;
执行的有效查询:
select l_tree from parent_tree where parent_id = 1;
执行函数:
select get_parent_ltree(1,'parent_tree');
select get_parent_ltree(1,'public.parent_tree');
我得到这个错误:
ERROR: invalid input syntax for type integer: "(2,2)"
CONTEXT: PL/pgSQL function get_parent_ltree(integer,regclass) line 3 at EXECUTE
第 3 行的上下文:
它看起来像是一个 Postgres 错误,但 Erwin 在相邻的答案中澄清了这个问题。一种自然的解决方法是按如下方式使用辅助文本变量:
create or replace function get_parent_ltree(_parent_id int, tbl_name regclass)
returns ltree language plpgsql as
$func$
declare
rslt text;
begin
execute format('select l_tree from %s where parent_id = ', tbl_name)
into rslt
using _parent_id;
return rslt::ltree;
end
$func$;
输出参数_l_tree
是一个“行变量”。 (复合类型被视为行变量。)SELECT INTO
逐一分配行变量的字段。 The manual:
The optional target
is a record variable, a row variable, or a comma-separated list of simple variables and record/row fields, [...]
因此,目前(第 14 页),行或记录变量必须独立为 target
。或者正如相应的 Postgres 错误消息所说的那样:
ERROR: record variable cannot be part of multiple-item INTO list
这个有效:
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 = ', _tbl_name)
INTO _l_tree
USING _parent_id;
END
$func$;
或者这个:
CREATE OR REPLACE FUNCTION public.get_parent_ltree2 (IN _parent_id int
, IN _tbl_name regclass
, OUT _l_tree ltree)
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('SELECT (l_tree).a, (l_tree).b FROM %s WHERE parent_id = ', _tbl_name)
INTO _l_tree.a, _l_tree.b
USING _parent_id;
END
$func$;
db<>fiddle here
我同意这相当棘手。人们可能希望将复合字段视为单个字段(如简单类型)。但目前在 PL/pgSQL 作业中并非如此。
来自 the manual about composite types 的相关引用:
A composite type represents the structure of a row or record; it is
essentially just a list of field names and their data types.
PostgreSQL allows composite types to be used in many of the same ways that simple types can be used.
大胆强调我的。
很多。不是 全部.
相关:
- PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"
旁白:考虑 additional module ltree
而不是“自己种植”。如果您继续使用自己的复合类型,请考虑使用不同的名称以避免与该模块混淆/冲突。
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;
尝试复制此答案中的解决方案:
- Format specifier for integer variables in format() for EXECUTE?
对于复合类型的函数:
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 = ', tbl_name)
INTO _l_tree
USING _parent_id;
END
$func$;
执行的有效查询:
select l_tree from parent_tree where parent_id = 1;
执行函数:
select get_parent_ltree(1,'parent_tree');
select get_parent_ltree(1,'public.parent_tree');
我得到这个错误:
ERROR: invalid input syntax for type integer: "(2,2)"
CONTEXT: PL/pgSQL function get_parent_ltree(integer,regclass) line 3 at EXECUTE
第 3 行的上下文:
它看起来像是一个 Postgres 错误,但 Erwin 在相邻的答案中澄清了这个问题。一种自然的解决方法是按如下方式使用辅助文本变量:
create or replace function get_parent_ltree(_parent_id int, tbl_name regclass)
returns ltree language plpgsql as
$func$
declare
rslt text;
begin
execute format('select l_tree from %s where parent_id = ', tbl_name)
into rslt
using _parent_id;
return rslt::ltree;
end
$func$;
输出参数_l_tree
是一个“行变量”。 (复合类型被视为行变量。)SELECT INTO
逐一分配行变量的字段。 The manual:
The optional
target
is a record variable, a row variable, or a comma-separated list of simple variables and record/row fields, [...]
因此,目前(第 14 页),行或记录变量必须独立为 target
。或者正如相应的 Postgres 错误消息所说的那样:
ERROR: record variable cannot be part of multiple-item INTO list
这个有效:
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 = ', _tbl_name)
INTO _l_tree
USING _parent_id;
END
$func$;
或者这个:
CREATE OR REPLACE FUNCTION public.get_parent_ltree2 (IN _parent_id int
, IN _tbl_name regclass
, OUT _l_tree ltree)
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('SELECT (l_tree).a, (l_tree).b FROM %s WHERE parent_id = ', _tbl_name)
INTO _l_tree.a, _l_tree.b
USING _parent_id;
END
$func$;
db<>fiddle here
我同意这相当棘手。人们可能希望将复合字段视为单个字段(如简单类型)。但目前在 PL/pgSQL 作业中并非如此。
来自 the manual about composite types 的相关引用:
A composite type represents the structure of a row or record; it is essentially just a list of field names and their data types. PostgreSQL allows composite types to be used in many of the same ways that simple types can be used.
大胆强调我的。
很多。不是 全部.
相关:
- PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"
旁白:考虑 additional module ltree
而不是“自己种植”。如果您继续使用自己的复合类型,请考虑使用不同的名称以避免与该模块混淆/冲突。