db2 存储过程中的全局临时 table

global temporary table in db2 stored procedure

刚接触 DB2,并决定在我的存储过程中使用全局临时 table 来完成我的任务。

下一个任务是: 只需为每天(例如 5 天)填充一些数据,从其他行中选择随机行 table 我的约会对象是这样的:

    select id from (
    select id, rand() rnd from source_table) 
    where rnd>0
    order by rnd
    fetch first 1000 rows only 

我想将该 int 列表存储在某处以重用它们。下一个想法是 -

            create table test (id int, dt date);


    create or replace procedure proc1 ()

    begin 

    declare v_start date default '2018-05-25'; 
    declare v_end date default '2018-05-30'; 
    declare v_dml varchar(8000);

    /*                                  this part so far doesn't work
    declare global temporary table
    session.temp_tab(id int)
    not logged on commit preserve;

    insert into session.temp_tab(id)
    select id from my_table;*/

    while v_start <= v_end DO 

        set v_dml = 'insert into test (id, dt)
                with t as (
                select 1 id, '''||v_start||''' dt from sysibm.dual
                union
                select 2 id, '''||v_start||''' dt from sysibm.dual
                union
                select 3 id, '''||v_start||''' dt from sysibm.dual)
                select *
                from t 
                where id in (1,3)';                         
    /*instead of 1,3 I would like to have list of values in some temp 
    table/array..., which I'll get 
    from the other table and can just use duriing this proc     
    I don't want to use sub select, because I'll get every time some random 
    data. But also I need that list for filter in several insert/update 
    statements*/ 
        set v_start = v_start +1 day;

        execute immediate v_dml;
        commit;
    end while;
    end 

P.S。我使用 DB2 LUW v10.5.0.7

UPD_1: 我想在一个循环中进行 DDL 和 DML 操作。例如我想添加partititon,然后将数据插入到同一个table。像这样:

    create or replace procedure proc1 (
                                    in in_rep int)
    begin 
    declare v_dt date; 
    declare v_end_dt date;
    declare v_add_part varchar(1024);
    declare v_id int;
    declare v_next_id int;       

            select max(id), max(dt) 
            into v_id,  v_dt
            from test;                                                                  

            set v_end_dt  = v_dt + in_rep day; 

                        while v_dt < v_end_dt DO

                                   set v_dt = v_dt +1 day;
                                   set v_next_id = v_id+1;          
                                   set v_add_part = 'alter table TEST               
                                                      add PARTITION part_'||v_next_id||'
                                                      starting from '||v_next_id||' ending at '||v_next_id;     

                                   execute immediate v_add_part;                  

                                   insert into test (id, dt)
                                   select v_next_id, v_dt 
                                   from sysibm.dual;                   
                       end while;
    end

在这种情况下,我会得到一个错误,SQLCODE=-327,SQLSTATE=22525 无法插入该行,因为它在最后一个分区的分区范围之外。

因为我试图改变 table 并同时插入,而不是一步一步。但是除了用动态 sql 替换插入之外,无法真正了解如何逐步完成它,例如:

    set v_add_part = 'alter table TEST               
    add PARTITION part_'||v_next_id||'
    starting from '||v_next_id||' ending at '||v_next_id;     

    set v_ins = 'insert into test (id, dt)
    select '||v_next_id||','''||v_dt||'''
    from sysibm.dual'; 

    execute immediate v_add_part;
    execute immediate v_ins;

如果您使用 Data Studio,它将在本地解析您的代码并突出显示任何语法错误。一旦我在 PRESERVE

之后添加工作 ROWS ,该过程就会为我创建(无论如何在 Db2 11.1 上)
create or replace procedure proc1 ()

begin 

declare v_start date default '2018-05-25'; 
declare v_end date default '2018-05-30'; 
declare v_dml varchar(8000);

--                                  this part so far doesn't work
declare global temporary table
session.temp_tab(id int)
not logged on commit preserve rows;

insert into session.temp_tab(id)
select id from my_table;

while v_start <= v_end DO 

    set v_dml = 'insert into test (id, dt)
            with t as (
            select 1 id, '''||v_start||''' dt from sysibm.dual
            union
            select 2 id, '''||v_start||''' dt from sysibm.dual
            union
            select 3 id, '''||v_start||''' dt from sysibm.dual)
            select *
            from t 
            where id in (1,3)';                         
/*instead of 1,3 I would like to have list of values in some temp 
table/array..., which I'll get 
from the other table and can just use duriing this proc     
I don't want to use sub select, because I'll get every time some random 
data. But also I need that list for filter in several insert/update 
statements*/ 
    set v_start = v_start +1 day;

    execute immediate v_dml;
    commit;
end while;
end

顺便说一句,使用变量和静态 SQL 而不是动态构建 SQL 语句,您的代码会更好(恕我直言)。您也可以对多行​​使用 VALUES,无需从虚拟 DUAL 表中 select。

我不确定你的任务是什么,但我不确定你是否接近这里的最佳解决方案...;-)

这是使用 RAND() 函数填充会话的示例 table。

注意插入语句只编译一次,但执行次数与日期范围一样多。

对于生产使用,您应该添加相关的错误处理。

create or replace procedure proc1 ()
language sql
specific proc1
begin 
    declare v_start date default '2018-05-25'; 
    declare v_end date default '2018-05-30'; 
    declare v_dml varchar(8000);
    declare global temporary table 
        session.temp_tab(id int not null) 
        with replace not logged on commit preserve rows;
    insert into session.temp_tab(id) 
       select int(rand()*1000) as random 
       from my_table order by random fetch first 1000 rows only;
    set v_dml = 'insert into test (id, dt) 
                 select t.id ,cast(? as date)  from session.temp_tab as t ' ;
    prepare s1 from v_dml;
    while v_start <= v_end do 
        execute s1 using v_start;
        set v_start = v_start + 1 day;
    end while;
    commit;
    end