Oracle数据库Merge Into 如何使用Sequence 而不“浪费”

本文探讨了在使用Oracle数据库的Merge Into语句时如何避免Sequence值的浪费。通过创建函数get_sequence_nextval来获取Sequence值,解决了Merge Into预编译导致的Sequence值丢失问题,实现了值的连续性,但同时也可能影响性能。建议根据实际需求权衡利弊选择合适的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、问题背景:该问题是在做Data Stage时引出来的一个问题,必须使用Merge Into的时候会浪费很多NextVal。

2、测试前提:创建脚本。

-- 创建源表
create table sourceTest(
id int,
name varchar2(100),
seq_value int,
t_stamp date
);


-- 创建目标表
create table targetTest(
id int,
name varchar2(100),
seq_value int,
t_stamp date
);


-- 创建sequence
create sequence seq_test
minvalue 1
maxvalue 999999
increment by 1
cache 40
nocycle;


-- 添加测试数据
insert into sourceTest(id,name,t_Stamp) values(null,null,sysdate);
insert into sourceTest(id,name,t_Stamp) values(1,'one',sysdate - 1);
insert into sourceTest(id,name,t_Stamp) values(2,'two',sysdate - 2);
insert into sourceTest(id,name,t_Stamp) values(3,null,sysdate - 3);
insert into sourceTest(id,name,t_Stamp) values(null,'four',sysdate + 1);
commit;

 3、测试

merge into targetTest t
using (select id, name,seq_value,t_stamp from sourceTest) s
on (s.id = t.id and s.name = t.name)
when matched then
  update set t.seq_value = s.seq_value, t.t_stamp = sysdate
when not matched then
  insert (id, name, seq_value,t_stamp) values (s.id, s.name,test.seq_test.nextval,s.t_stamp);

  第一次执行,结果:

  

   IDNAMESEQ_VALUET_STAMP
1 one12012-11-17 下午 03:11:46
2  22012-11-18 下午 03:11:46
33 32012-11-15 下午 03:11:46
4 four42012-11-19 下午 03:11:46
52two52012-11-16 下午 03:11:46

第二次执行,结果:

 

   IDNAMESEQ_VALUET_STAMP
11one 2012-11-18 下午 03:20:28
2  22012-11-18 下午 03:11:46
33 32012-11-15 下午 03:11:46
4 four42012-11-19 下午 03:11:46
52two 2012-11-18 下午 03:20:28
6  82012-11-18 下午 03:11:46
73 92012-11-15 下午 03:11:46
8 four102012-11-19 下午 03:11:46

从上面的结果,我们可以非常清晰的看到6和7那里去了?--浪费掉了。

4、解决。创建一个函数来获取相应的值。

create or replace function get_sequence_nextval(f_schema in varchar2, f_sequence_name in  varchar2) return number
is
  v_nextval         number;
begin
  execute immediate 'select ' || f_schema || '.'||f_sequence_name||'.nextval from dual' into v_nextval;
 return v_nextval;
exception
  when others then
   raise_application_error(sqlcode,sqlerrm);
end;

 

 将3测试中的代码调整为:test.seq_test.nextval  ==> test.get_sequence_nextval('test','seq_test')

 再次调用,我们可以看到三条记录11、12、13已经紧跟着10了。--不浪费了。

 

   IDNAMESEQ_VALUET_STAMP
11one 2012-11-18 下午 03:28:35
2  22012-11-18 下午 03:11:46
33 32012-11-15 下午 03:11:46
4 four42012-11-19 下午 03:11:46
52two 2012-11-18 下午 03:28:35
6  82012-11-18 下午 03:11:46
73 92012-11-15 下午 03:11:46
8 four102012-11-19 下午 03:11:46
9  112012-11-18 下午 03:11:46
103 122012-11-15 下午 03:11:46
11 four132012-11-19 下午 03:11:46

 

 5、结论及分析:

使用Merge Into调用Sequence 类似于预编译,会直接将值赋组合相应的调用,而不管该matched 或 not matched是否成功执行。而使用一个function进行封闭以后,因为预编译时无法知道该值,所以不会进行预处理,因此也不会浪费sequence的值。但是,使用function来讲,会带来另外一个问题,性能因为无端的增加了一下调用。

所以,根据自己的实际情况,选择适合自己的才是最好的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值