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);
第一次执行,结果:
|
ID |
NAME |
SEQ_VALUE |
T_STAMP |
1 |
|
one |
1 |
2012-11-17 下午 03:11:46 |
2 |
|
|
2 |
2012-11-18 下午 03:11:46 |
3 |
3 |
|
3 |
2012-11-15 下午 03:11:46 |
4 |
|
four |
4 |
2012-11-19 下午 03:11:46 |
5 |
2 |
two |
5 |
2012-11-16 下午 03:11:46 |
第二次执行,结果:
|
ID |
NAME |
SEQ_VALUE |
T_STAMP |
1 |
1 |
one |
|
2012-11-18 下午 03:20:28 |
2 |
|
|
2 |
2012-11-18 下午 03:11:46 |
3 |
3 |
|
3 |
2012-11-15 下午 03:11:46 |
4 |
|
four |
4 |
2012-11-19 下午 03:11:46 |
5 |
2 |
two |
|
2012-11-18 下午 03:20:28 |
6 |
|
|
8 |
2012-11-18 下午 03:11:46 |
7 |
3 |
|
9 |
2012-11-15 下午 03:11:46 |
8 |
|
four |
10 |
2012-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了。--不浪费了。
|
ID |
NAME |
SEQ_VALUE |
T_STAMP |
1 |
1 |
one |
|
2012-11-18 下午 03:28:35 |
2 |
|
|
2 |
2012-11-18 下午 03:11:46 |
3 |
3 |
|
3 |
2012-11-15 下午 03:11:46 |
4 |
|
four |
4 |
2012-11-19 下午 03:11:46 |
5 |
2 |
two |
|
2012-11-18 下午 03:28:35 |
6 |
|
|
8 |
2012-11-18 下午 03:11:46 |
7 |
3 |
|
9 |
2012-11-15 下午 03:11:46 |
8 |
|
four |
10 |
2012-11-19 下午 03:11:46 |
9 |
|
|
11 |
2012-11-18 下午 03:11:46 |
10 |
3 |
|
12 |
2012-11-15 下午 03:11:46 |
11 |
|
four |
13 |
2012-11-19 下午 03:11:46 |
5、结论及分析:
使用Merge Into调用Sequence 类似于预编译,会直接将值赋组合相应的调用,而不管该matched 或 not matched是否成功执行。而使用一个function进行封闭以后,因为预编译时无法知道该值,所以不会进行预处理,因此也不会浪费sequence的值。但是,使用function来讲,会带来另外一个问题,性能因为无端的增加了一下调用。
所以,根据自己的实际情况,选择适合自己的才是最好的。
分享到:
相关推荐
### Oracle数据库基本操作知识点 #### 一、表空间操作 **1. 文件系统:** - **创建表空间:** - 数据表空间: 使用`CREATE TABLESPACE`命令创建一个新的数据表空间。例如: ```sql CREATE TABLESPACE tablespace...
若不使用绑定变量,尤其是来自Java等应用程序的SQL语句,会导致大量硬解析(Hard Parse),即数据库必须为每个不同的SQL文本创建新的解析计划,这不仅消耗了更多的CPU资源,还可能导致共享池内存的快速耗尽,进而影响...
- **合并记录**:使用MERGE INTO语句。 ##### 9. 创建和管理表 - 使用CREATE TABLE语句创建新表。 - 使用ALTER TABLE语句修改现有表的结构。 ##### 10. 约束介绍 - **主键**:唯一标识表中的每条记录。 - **外键**...
在SQL*Plus中连接到Oracle数据库时,可以使用`conn`命令。例如: ```sql conn 用户名/密码 ``` 查看当前登录用户: ```sql show user; ``` 连接到特定的数据库实例: ```sql conn [用户名/密码@网络 [as sysdba...
- **Oracle**:一款广泛使用的商业关系型数据库管理系统。 - **SQL**(Structured Query Language):用于管理和处理Oracle数据库中的数据的标准语言。 ##### 1.2 数据库安全 - **认证**:验证用户身份的过程。 - *...
- 在不使用时,可以通过服务管理器手动停止Oracle服务,以节省系统资源。 **1.6 手动关闭Oracle服务** - 通过命令行或其他工具手动停止Oracle服务。 #### 二、SQL*Plus工具的使用 **2.1 SQL*Plus简介** - **SQL...
字符串字段中含有\"\'\",如果用来组合sql语句,会造成语句不准确。 比如:replace(f1,\'\'\'\',\'\') <2>.字符串字段中含有\"\\t \\n\",如果用来在c或者c++程序中输出到文件,格式无法保证。 比如:replace(f2,...
此操作是强列推荐不使用的,因为不能应用表的索引。 推荐方案:用NOT EXISTS 或(Outer-Join+判断为空)方案代替 例如: SELECT deptno FROM dept WHERE deptno NOT IN(SELECT deptno FROM emp) 建议写成...