“无法将非复合值分配给记录变量”将结果存储在数组中时
在 Postgres 13 上,我有一个触发器执行表的 ON UPDATE
。在此触发器中,我想将查询结果存储在数组中,因为我需要在内部迭代器中多次使用它。通过这种方式,我可以避免在每次迭代时执行相同的查询,并且可以重用该数组。
起初我尝试这样,我将变量输入为数组记录:
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results record[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select
date_start,
coalesce(date_end, 'infinity'::date) as date_end
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in array l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
但是我得到了
Errore SQL [0A000]: ERROR: variable "l_table1_results" has pseudo-type record[]
做一些研究我发现不可能用查询的结果分配内存中的变量,而是我需要使用自定义类型。好的,所以我也尝试了这个
create type apc_dates_pair as (
date_start date,
date_end date
);
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results apc_dates_pair[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select
date_start,
coalesce(date_end, 'infinity'::date) as date_end
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
-- TODO do some stuffs with array
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results apc_dates_pair[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select row(
date_start,
coalesce(date_end, 'infinity'::date)
)
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in array l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
不同的错误,但仍然是一个错误:
cannot assign non-composite value to a record variable
从中我没有发现太多。
是否有可能在记录数组中存储临时查询,然后迭代它们?
on Postgres 13 I have a trigger execute ON UPDATE
of a table. In this trigger I want to store in an array a result from a query, because I will need to use it inside an inner iterator, multiple times. In this way I avoid performing the same query at every iteration and I can reuse the array.
At first I tried like this, I typed the variable as array record:
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results record[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select
date_start,
coalesce(date_end, 'infinity'::date) as date_end
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in array l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
But I'm getting a
Errore SQL [0A000]: ERROR: variable "l_table1_results" has pseudo-type record[]
Doing some research I discovered it is not possible to assign an in-memory variable with the result of a query, but instead I need to use a custom type. Ok, so I tried also this
create type apc_dates_pair as (
date_start date,
date_end date
);
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results apc_dates_pair[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select
date_start,
coalesce(date_end, 'infinity'::date) as date_end
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
-- TODO do some stuffs with array
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
create or REPLACE FUNCTION check_companyprofile_between_records_constraints_trigger_hook()
RETURNS trigger as
$body$
declare
l_table1_results apc_dates_pair[];
l_table1_result record;
l_record record;
begin
l_table1_results := ARRAY(
select row(
date_start,
coalesce(date_end, 'infinity'::date)
)
FROM application.section_profile_company_metadata
WHERE persona_id = NEW.persona_id and id != new.id
);
for l_record in (
select foo,bar,baz
from table2
)
loop
foreach l_table1_result in array l_table1_results
loop
-- Check some stuffs
end loop;
end loop;
RETURN NEW;
end
$body$
LANGUAGE plpgsql;
Different error, but still an error:
cannot assign non-composite value to a record variable
And from this I did not find much.
Is it possible at all to store a temp query inside and array of records and then iterate them?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
解释多于答案:
您似乎将复合类型与数组混淆了,它们在 Postgres 中是不同的东西。最值得注意的是 Postgres Array 包含单一类型的值。您可以使用
int[]
所有整数,varchar[]
所有字符,依此类推,但不能在单个数组中混合类型。另一方面, 复合类型 可以做到这一点,包含的值属于不同类型。在 plpgsql 中声明一个记录基本上是声明一个匿名复合类型,该类型获取传递给它的任何实际复合类型的属性。这就是你收到第二个错误的原因; “无法将非复合值分配给记录变量”。您正在尝试将数组分配给复合类型,在本例中为记录
。鉴于您要存储的值都是date
,您可以省略create type apc_dates_pair ...
,而只需执行l_table1_results date[]
。然后使用 所示的形式迭代数组数组循环。An explanation more then an answer:
You seem to be confusing composite types with arrays, they are different things in Postgres. Most notably a Postgres Array contains values of a single type. You can have
int[]
all integers,varchar[]
all characters, and so on, but you cannot mix types in a single array. A Composite Type on the other hand can do just that, have included values that are of different types. Inplpgsql
declaring arecord
is to basically declare an anonymous composite type that acquires the properties of whatever actual composite type is passed to it. This is why you get your second error; "cannot assign non-composite value to a record variable". You are trying to assign an array to a composite type, in this case arecord
. Given that the values you want to store are bothdate
s you could dispense withcreate type apc_dates_pair ...
and just dol_table1_results date[]
. Then iterate over the array using the form shown at Array loop.