我需要将数据从源表转换为目标表。
源表具有“内容”列和“乘数”列。根据乘数(X),源的内容应该X次写入目标。
例如:如果 multilpier 为 '0',则不会写入任何内容,如果为 '1',则将内容一次写入目标表。两次,如果乘数为“2”,依此类推。我以前从未在 Postgres 中做过函数。
我的方法:嵌套 for-while 循环:对于每一行,当“计数器”小于“乘数”时,将源表中的内容插入到目标表中。
示例数据:
--create source table
create table public.source_tbl(
id serial,
multiplier int,
content varchar,
primary key (id)
);
--create destination table
create table public.dest_tbl(
id serial,
multiplier int,
content varchar,
primary key (id)
);
--some content
insert into public.source_tbl(multiplier,content)
values(1,'foo'),(1,'bar'),(1,'random'),(2, 'content'),(3,'My'),(4,'creativity'),(3,'is'),(2,'very'),(6,'limited'),(7,'!!!'), (0, 'nothing should be written');
这就是我想出的代码:
do
$$
declare f record;
begin
for f in select id, multiplier, content
from public.source_tbl;
loop
do
$$
declare counter integer counter:=0;
begin
while counter < f.multiplier
loop
insert into public.dest_tbl(multiplier,content)
select f.multiplier, f.content;
counter := counter +1;
end loop;
end;
end loop;
end;
$$
不用说它不起作用,我收到第二个“声明”的语法错误。那么我做错了什么?
答案 0 :(得分:2)
Jim 立即回答了有关语法错误的问题。但是,为此您不需要函数或 PL/pgSQL。同样可以通过使用内置函数 generate_series()
insert into dest_tbl (multiplier, content)
select st.multiplier, st.content
from source_tbl st
cross join generate_series(1, st.multiplier);
答案 1 :(得分:1)
您不能在 plpgsql
代码中间声明变量。也没有必要为第二个循环创建另一个匿名代码块。试试这个:
do
$$
declare
f record;
counter integer :=0;
begin
for f in select id, multiplier, content from public.source_tbl loop
while counter < f.multiplier loop
insert into public.dest_tbl(multiplier,content)
select f.multiplier, f.content;
counter := counter +1;
end loop;
counter := 0;
end loop;
end;
$$ language plpgsql;
演示:db<>fiddle