[英]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反正)我一旦添加了工作ROWS
后PRESERVE
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.