我正在开发一个PostgreSQL 8.3版本,它不支持日期/时间序列的generate_series()
函数变体。我现在有这个丑陋的解决方法,用第三个参数调用函数,如:
select table_union('2012-12-01', '2013-02-20', 79)
我必须手动计算最后一个参数,以确定generate_series()
的天数。
修改此脚本的最佳方法是什么,以便在函数调用中只需要两个参数?
有没有办法修改下面的代码才能以相同的方式工作,只给出这个函数的两个参数?
select table_union('2012-12-01', '2013-02-20')
create or replace function table_union(date_from date, date_to date, numday int)
returns void language plpgsql as $$
declare
day_1 date;
_stop_ bigint := (date_from::date - date_to::date)::int;
begin
for day_1 in
select date_from + s.a as dates from generate_series(0, $3 ) as s(a)
loop
execute 'insert into dhcp.dhcp_map select * from dhcp.final_map_'|| trim( leading ' ' from to_char(extract(month from day_1), '09')) ||'_'||
trim( leading ' ' from to_char(extract(day from day_1), '09')); --to_char introduces a leadin space use trim to remove
end loop;
end; $$;
更新:我在下面的答案中提出了很好的建议后尝试修改我的代码,但仍有一些错误:
create or replace function
table_union(date_from date, date_to date)
returns void language plpgsql
as $func$
declare day_1 date;
begin
for day_1 in select date_from
+ s.a as dates from generate_series(0, (date_to - date_from))
as s(a)
loop
execute
'insert into dhcp.dhcp_map select * from dhcp.final_map_'||
array_to_string(ARRAY(SELECT to_char(date_from + generate_series(0, (date_to - date_from)), 'MM_DD')) ) ;
end loop;
end;
$func$;
答案 0 :(得分:3)
CREATE OR REPLACE FUNCTION table_union(date_from date, date_to date)
RETURNS void LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE '
INSERT INTO dhcp.dhcp_map
SELECT * FROM dhcp.final_map_'
|| array_to_string(ARRAY(SELECT to_char(date_from
+ generate_series(0, (date_to - date_from)), 'MM_DD')), '
UNION ALL
SELECT * FROM dhcp.final_map_'
);
END
$func$;
呼叫:
SELECT table_union('2012-12-01', '2013-01-10');
对性能最重要的是:我每天生成并执行一个单 INSERT
语句,而不是一天INSERT
语句 。用RETURNS text
和RETURN
代替EXECUTE
,您可以看到生成的语句:
INSERT INTO dhcp.dhcp_map
SELECT * FROM dhcp.final_map_12_01
UNION ALL
SELECT * FROM dhcp.final_map_12_02
UNION ALL
SELECT * FROM dhcp.final_map_12_03
...
->sqlfiddle for Postgres 8.3.
只要将数据量插入到RAM中,就会快得多。
如果您的INSERT
应该巨大,您可能希望坚持每天一INSERT
。
CREATE OR REPLACE FUNCTION table_union_huge(date_from date, date_to date)
RETURNS void LANGUAGE plpgsql AS
$func$
BEGIN
FOR i IN 0 .. (date_to - date_from)
LOOP
EXECUTE 'INSERT INTO dhcp.dhcp_map
SELECT * FROM dhcp.final_map_'|| (date_from + i)::text;
END LOOP;
END
$func$;
从函数调用中删除冗余参数$3
。替换为简单减法$2 - $1
。返回Postgres中的整数(以天为单位)。
简化generate_series()
来电。
将LOOP替换为ARRAY constructor和array_to_string()
以创建单个语句。
大大简化了字符串处理。只需使用pattern MM_DD
with to_char()
从日期中提取字符串。
Postgres 8.3手册的所有链接。