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