使用generate_series()修改PL/pgSQL函数

使用generate_series()修改PL/pgSQL函数,sql,plpgsql,dynamic-sql,generate-series,postgresql-8.3,Sql,Plpgsql,Dynamic Sql,Generate Series,Postgresql 8.3,我正在开发的PostgreSQL 8.3版本不支持日期/时间序列的generate_series()函数的变体。我现在有一个难看的解决方法,用第三个参数调用函数,如下所示: select table_union('2012-12-01', '2013-02-20', 79) 我必须手动计算最后一个参数,以确定generate_series()的天数 修改此脚本以便在函数调用中只需要两个参数的最佳方法是什么 是否有一种方法可以修改下面的代码,使其以相同的方式工作,只需向函数提供两个参数,如下所示

我正在开发的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) 
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$;
电话:

要点
  • 对性能最重要的是:我不是每天生成一条
    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
    ...
    

    只要将f9its插入RAM的数据量足够大,这就大大加快了速度

  • 如果你的
    INSERT
    应该很大,你可能希望每天坚持一个
    INSERT

  • 从函数调用中删除冗余参数
    $3
    。替换为简单减法
    $2-$1
    。返回Postgres中的整数(天数差)

  • 简化的
    generate_series()
    调用

  • 将循环替换为和以创建单个语句

  • 大大简化了字符串处理。只需使用从日期中提取字符串


Postgres 8.3手册的所有链接。

为避免前导空格,请在
to_char()
掩码中使用。感谢您的精彩写作。我从你的每一篇博文中都学到了很多东西。1事实证明,我正在应用的insert语句大约有几十亿行,所以在以前编写insert语句时,union的速度比insert慢。我尝试了在下面的注释中添加的代码的变体,但在使用时遇到问题。创建或替换函数表_union(date_from date,date_to date)将无效语言plpgsql返回为$func$declare day_1 date;从选择日期从+s.a中的第1天开始,作为从生成系列的日期(0,(日期从-date从))作为s(a)循环执行“插入到dhcp.dhcp映射从dhcp中选择*。最终映射到数组到字符串(数组(选择到字符(日期从+generate系列(0,(日期从-date从)),“MM\u DD”)) ; 端环;结束$func$@user7980:最好以更易于阅读的格式将更新后的版本放入问题中(而不是评论)。或者,如果它足够新,就用它打开另一个问题。我在我的答案中添加了一个简单的版本,每次插入一个。
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 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
...
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$;