文本形式的postgresql for循环脚本无法执行
postgresql for loop script in text form can not be executed
我正在尝试在 postgresql 中编写函数,它创建 temp_table 列 table_name 文本,table_rec jsonb 并通过 for 循环填充它 table 来自我的 table 的名字,其中包含 table 的名字和 json 中的记录。我在字符串中有 for 循环,我想执行它。 但是没用。
我有可变 rec 记录,sql_query 文本和 tab_name 文本,我想这样做:
CREATE OR REPLACE FUNCTION public.test51(
)
RETURNS TABLE(tabel_name text, record_json jsonb)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
declare
rec record;
tabel_name text;
tabel_names text[];
counter integer := 1;
sql_query text;
limit_for_sending integer;
rec_count integer;
begin
select into tabel_names array(select "TABLE_NAME" from public."TABLES");
create temp table temp_tab(tab_nam text, recik jsonb);
while array_length(tabel_names, 1) >= counter loop
tabel_name := '"' || tabel_names[counter] || '"';
select into limit_for_sending "TABLE_LIMIT_FOR_SENDING_DATA" from public."TABLES" where "TABLE_NAME" = tabel_name;
sql_query := 'select count(*) from public.' || tabel_name;
execute sql_query into rec_count;
if (rec_count >= limit_for_sending and limit_for_sending is not null) then
sql_query := 'for rec in select * from public.' || tabel_name || '
loop
insert into temp_tab
select ' || tabel_name || ', to_jsonb(rec);
end loop';
execute sql_query;
end if;
counter := counter + 1;
end loop;
return query
select * from temp_tabik;
drop table temp_tabik;
end;
$BODY$;
感谢您的回复。
您似乎有一些 table 包含您想要 return 将所有行作为 JSONB 的 table 的信息。那个 meta-table 还包含一个设置阈值的列,在该阈值下不应 returned.
您不需要临时 table 或数组来存储 table 名称。您可以直接在该循环中遍历 TABLES
table 和 运行 动态 SQL 上的查询。
return query
in PL/pgSQL 不会终止函数,它只是将查询的结果附加到函数的结果。
动态 SQL 最好使用 format()
函数创建,因为它更易于阅读,并且使用 %I
占位符将正确处理带引号的标识符(这对您来说非常重要正在使用那些可怕的大写 table 名称)
据我所知,你的函数可以简化为:
CREATE OR REPLACE FUNCTION public.test51()
RETURNS TABLE(tabel_name text, record_json jsonb)
LANGUAGE plpgsql
AS
$BODY$
declare
rec record;
sql_query text;
rec_count bigint;
begin
for rec in
select "TABLE_NAME" as table_name, "TABLE_LIMIT_FOR_SENDING_DATA" as rec_limit
from public."TABLES"
loop
if rec.rec_limit is not null then
execute format('select count(*) from %I', rec.table_name)
into rec_count;
end if;
if (rec.rec_limit is not null and rec_count >= rec.rec_limit) then
sql_query := format('select %L, to_jsonb(t) from %I as t', rec.table_name, rec.table_name);
return query execute sql_query;
end if;
end loop;
end;
$BODY$;
一些笔记
- 语言名称是一个标识符,不应用单引号引起来。此语法已弃用,可能会在未来的版本中删除,因此请不要习惯它。
- 你真的应该避免那些可怕的引用标识符。他们带来的麻烦多于他们的价值。有关详细信息,请参阅 the Postgres wiki。
我正在尝试在 postgresql 中编写函数,它创建 temp_table 列 table_name 文本,table_rec jsonb 并通过 for 循环填充它 table 来自我的 table 的名字,其中包含 table 的名字和 json 中的记录。我在字符串中有 for 循环,我想执行它。 但是没用。 我有可变 rec 记录,sql_query 文本和 tab_name 文本,我想这样做:
CREATE OR REPLACE FUNCTION public.test51(
)
RETURNS TABLE(tabel_name text, record_json jsonb)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
declare
rec record;
tabel_name text;
tabel_names text[];
counter integer := 1;
sql_query text;
limit_for_sending integer;
rec_count integer;
begin
select into tabel_names array(select "TABLE_NAME" from public."TABLES");
create temp table temp_tab(tab_nam text, recik jsonb);
while array_length(tabel_names, 1) >= counter loop
tabel_name := '"' || tabel_names[counter] || '"';
select into limit_for_sending "TABLE_LIMIT_FOR_SENDING_DATA" from public."TABLES" where "TABLE_NAME" = tabel_name;
sql_query := 'select count(*) from public.' || tabel_name;
execute sql_query into rec_count;
if (rec_count >= limit_for_sending and limit_for_sending is not null) then
sql_query := 'for rec in select * from public.' || tabel_name || '
loop
insert into temp_tab
select ' || tabel_name || ', to_jsonb(rec);
end loop';
execute sql_query;
end if;
counter := counter + 1;
end loop;
return query
select * from temp_tabik;
drop table temp_tabik;
end;
$BODY$;
感谢您的回复。
您似乎有一些 table 包含您想要 return 将所有行作为 JSONB 的 table 的信息。那个 meta-table 还包含一个设置阈值的列,在该阈值下不应 returned.
您不需要临时 table 或数组来存储 table 名称。您可以直接在该循环中遍历 TABLES
table 和 运行 动态 SQL 上的查询。
return query
in PL/pgSQL 不会终止函数,它只是将查询的结果附加到函数的结果。
动态 SQL 最好使用 format()
函数创建,因为它更易于阅读,并且使用 %I
占位符将正确处理带引号的标识符(这对您来说非常重要正在使用那些可怕的大写 table 名称)
据我所知,你的函数可以简化为:
CREATE OR REPLACE FUNCTION public.test51()
RETURNS TABLE(tabel_name text, record_json jsonb)
LANGUAGE plpgsql
AS
$BODY$
declare
rec record;
sql_query text;
rec_count bigint;
begin
for rec in
select "TABLE_NAME" as table_name, "TABLE_LIMIT_FOR_SENDING_DATA" as rec_limit
from public."TABLES"
loop
if rec.rec_limit is not null then
execute format('select count(*) from %I', rec.table_name)
into rec_count;
end if;
if (rec.rec_limit is not null and rec_count >= rec.rec_limit) then
sql_query := format('select %L, to_jsonb(t) from %I as t', rec.table_name, rec.table_name);
return query execute sql_query;
end if;
end loop;
end;
$BODY$;
一些笔记
- 语言名称是一个标识符,不应用单引号引起来。此语法已弃用,可能会在未来的版本中删除,因此请不要习惯它。
- 你真的应该避免那些可怕的引用标识符。他们带来的麻烦多于他们的价值。有关详细信息,请参阅 the Postgres wiki。