我是 Postgres 新手,正在尝试创建将多个表中的数据插入到单个表中的代码。
所有源表的名称都以“B3_HIST_”开头,仅年份不同(它们的命名范围为“B3_HIST_2015”到“B3_HIST_2023”)。
我使用 3 个变量,连接名称并在循环中使用它们,如下所示:
create or replace procedure dbo.SP_B3_HIST ()
language plpgsql
AS $$
declare
nametab TEXT := 'dbo.B3_HIST_';
startyr INTEGER := 2015;
lastyr INTEGER := 2023;
begin
while startyr <= lastyr loop
INSERT INTO TEMP1 SELECT * FROM (nametab || startyr )
startyr = startyr + 1
END LOOP;
END; $$
问题:
ERROR: string between dollars did not end in or near "$$
declare
nametab TEXT := 'dbo.B3_HIST_'"
LINE 3: AS$$
^
如何正确执行此操作?
您可以循环为每个源表运行单独的
INSERT
。 (就像大表和每个表后面的COMMIT
?)当然需要正确的语法,就像评论中指出的Islingre...
通常,构建单个语句(使用纯 SQL)并执行更简单、更快:
CREATE OR REPLACE PROCEDURE dbo.sp_b3_hist()
LANGUAGE plpgsql AS
$proc$
DECLARE
nametab text := 'dbo.b3_hist_'; -- lower case
startyr int := 2015;
lastyr int := 2023;
BEGIN
-- RAISE NOTICE '%', ( -- debug first?
EXECUTE (
SELECT E'INSERT INTO temp1 \n'
|| string_agg('TABLE ' || nametab || g, E'\nUNION ALL ')
FROM generate_series(startyr, lastyr) g
);
END
$proc$;
CALL dbo.sp_b3_hist();
相关:
如果是一次性操作,请使用
DO
命令而不是持久化过程。
或者在 psql 中使用
\gexec
。
参见:
避免在 Postgres 中混合大小写标识符,让您的生活更轻松。
我只是按照你的解决方案。对存储过程 INSERT 语句进行细微更改。 问题在于存储过程中表的动态名称。有不同的方法可以解决它。我使用 quote_ident() 函数来解决该问题。根据 postgresql 的文档,它是:
quote_ident(文本)→文本
返回适当引用的给定字符串,以用作 SQL 语句字符串中的标识符。仅在必要时添加引号(即,如果字符串包含非标识符字符或大小写折叠)。嵌入的引号适当加倍 quote_ident('Foo bar') → "Foo bar"
让我们开始实际工作吧。
CREATE TABLE IF NOT EXISTS public.B3_HIST_2015
(
TranDate Date,
amount numeric(12,2)
);
INSERT INTO public.B3_HIST_2015(
TranDate, Amount)
VALUES ('01-Jan-2015', 2000), ('01-Feb-2015', 3000), ('01-Mar-2015', 4000);
CREATE TABLE IF NOT EXISTS public.B3_HIST_2016
(
TranDate Date,
amount numeric(12,2)
);
INSERT INTO public.B3_HIST_2016(
TranDate, Amount)
VALUES ('02-Apr-2016', 2000), ('03-May-2016', 3000), ('04-Jun-2016', 4000);
CREATE TABLE IF NOT EXISTS public.B3_HIST_2017
(
TranDate Date,
amount numeric(12,2)
);
INSERT INTO public.B3_HIST_2017(
TranDate, Amount)
VALUES ('12-Jul-2017', 2500), ('13-Aug-2017', 3007), ('14-Sep-2017', 4060);
CREATE TABLE IF NOT EXISTS public.TEMP1
(
TranDate Date,
amount numeric(12,2)
);
create or replace procedure public.SP_B3_HIST ()
language plpgsql
AS $$
declare
nametab TEXT := 'b3_hist_';
temptab TEXT :='';
startyr INTEGER := 2015;
lastyr INTEGER := 2017;
begin
while startyr <= lastyr loop
temptab = CONCAT(nametab, startyr);
execute 'INSERT INTO TEMP1(TranDate, Amount) (SELECT TranDate, Amount FROM ' || quote_ident(temptab) || ')';
startyr = startyr + 1;
END LOOP;
END; $$;
call public.SP_B3_HIST ();
SELECT * FROM temp1;
谢谢你。