簡體   English   中英

db2存儲過程中的全局臨時表

[英]global temporary table in db2 stored procedure

剛進入DB2,並決定在我的存儲proc中使用全局臨時表來完成我的任務。

接下來的任務是:每天填充一些數據(例如5天),從另一個表中選擇隨機行,我得到的日期如下:

    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 

PS我使用DB2 LUW v10.5.0.7

UPD_1:我想在一個循環中執行DDL和DML操作。 例如,我想添加partititon,然后將數據插入同一張表。 像這樣:

    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無法插入行,因為它超出了最后一個分區的分區范圍。

我試圖在同一時間而不是一步一步地更改表和插入的原因。 但實際上無法真正獲得如何用動態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,它將在本地解析您的代碼並突出顯示任何語法錯誤。 該程序為我創建(在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

順便說一句,使用變量和靜態SQL會比動態構建SQL語句更好(IMHO)。 您也可以將VALUES用於多行,而無需從虛擬DUAL表中進行選擇。

我不確定您的任務是什么,但不確定您是否在這里找到最佳解決方案... ;-)

這是一個使用RAND()函數填充會話表的示例。

請注意,insert語句僅被編譯一次,但是執行的次數與日期范圍相同。

對於生產用途,應添加相關的錯誤處理。

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