简体   繁体   English

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

[英]global temporary table in db2 stored procedure

Just getting into DB2, and have decided to use global temporary table in my stored proc for my task. 刚进入DB2,并决定在我的存储proc中使用全局临时表来完成我的任务。

The task would be the next: just populate some data for each day (during for example 5 days), selecting random rows from the other table I'm getting my date like: 接下来的任务是:每天填充一些数据(例如5天),从另一个表中选择随机行,我得到的日期如下:

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

I wanted to store somewhere that list of int to reuse them. 我想将int列表存储在某个地方以重用它们。 The idea was the next - 下一个想法是-

            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 

PS I use DB2 LUW v10.5.0.7 PS我使用DB2 LUW v10.5.0.7

UPD_1: I would like to do DDL and DML operation in one loop. UPD_1:我想在一个循环中执行DDL和DML操作。 For example I want to add partititon and then insert the data to the same table. 例如,我想添加partititon,然后将数据插入同一张表。 like this: 像这样:

    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

In this case I would get an error, SQLCODE=-327, SQLSTATE=22525 THE ROW CANNOT BE INSERTED BECAUSE IT IS OUTSIDE THE BOUND OF THE PARTITION RANGE FOR THE LAST PARTITION. 在这种情况下,我会得到一个错误,SQLCODE = -327,SQLSTATE = 22525无法插入行,因为它超出了最后一个分区的分区范围。

Cause of I'm trying to alter table and insert in the same time, not step by step. 我试图在同一时间而不是一步一步地更改表和插入的原因。 But can't really get how to do it step by step excep of replace insert with dynamic sql, like: 但实际上无法真正获得如何用动态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;

If you use Data Studio, that will parse your code locally and hi-light any syntax errors. 如果您使用Data Studio,它将在本地解析您的代码并突出显示任何语法错误。 The procedure creates for me (on Db2 11.1 anyway) once I added the work ROWS after PRESERVE 该程序为我创建(在DB2 11.1反正)我一旦添加了工作ROWSPRESERVE

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

BTW your code would be better (IMHO) using a variable and static SQL rather than dynamically building a SQL statement. 顺便说一句,使用变量和静态SQL会比动态构建SQL语句更好(IMHO)。 Also you can use VALUES with multiple rows, no need to select from a dummy DUAL tables. 您也可以将VALUES用于多行,而无需从虚拟DUAL表中进行选择。

I'm not sure what your task is, but I'm not sure you are close to the best solution here... ;-) 我不确定您的任务是什么,但不确定您是否在这里找到最佳解决方案... ;-)

Here is an example of using the RAND() function to populate the session table. 这是一个使用RAND()函数填充会话表的示例。

Notice that the insert statement gets compiled only one time, but executed as many times as the date-range. 请注意,insert语句仅被编译一次,但是执行的次数与日期范围相同。

For production use you should add relevant error-handling. 对于生产用途,应添加相关的错误处理。

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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM