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
刚接触 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