Oracle9i引入了MERGE命令,使我们能够在一个SQL语句中对一个表同时执行inserts和updates操作,MERGE命令从一个或多个数据源中选择行来updating或inserting到一个或多个表.最近工作中需要处理一批号码数据.之前数据库中有一个号码的黑名单,用户信息群发的黑名单用户过滤,表格字段如下
black_dn( dn varchar(13),flag number(2))
此表格中保存了一份号码黑名单数据,dn为号码,flag为地市标志.现在又有了一份黑名单.这份黑名单中可能有重复的,可能有之前已经导入到黑名单表格中的.需要把这份黑名单无重复的添加近black_dn表中于是我按照black_dn创建了一个新的表
create balck_dn_new as select * from black_dn where 0=1;
然后将新的数据使用sqlload全部导入到新的表中,接着我需要更新black_dn中的数据,于是使用了如下的SQL
MERGE INTO BLAKC_DN B1
USING BLACK_DN_NEW B2
ON (B1.DN=B2.DN AND B1.FLAG=B2.FLAG)
WHEN MATCHED THEN
UPDATE SET
B1.DN=B2.DN
B1.FLAG=B2.FLAG
WHEN NOT MATCHED THEN
INSERT VALUES(B2.DN,B2.FLAG);
但是数据库反馈了ORA-00904: "B1"."DN": 无效的标识符,刚开始非常想不通为什么会提示这个错误.明明字段是没有错误的.于是乎又是找了一通资料,发现了问题所在,如果你在on后引用了哪些列,这些列是不允许更新的.但是oracle这个提示错误个人觉得是有问题的.为了正确使用,我又为把balck_dn表扩展为
BLACK_DN (DN VARCHAR(13),FLAG NUMBER(2),IFLAG NUMBER(2))
在IFLAG字段中全部填入了0,然后修改了SQL
MERGE INTO BLAKC_DN B1
USING BLACK_DN_NEW B2
ON (B1.DN=B2.DN AND B1.FLAG=B2.FLAG)
WHEN MATCHED THEN
UPDATE SET
B1.IFLAG=10
WHEN NOT MATCHED THEN
INSERT VALUES(B2.DN,B2.FLAG,1);
本以为OK了,结果oracle还是不干,反馈错误ORA-30926: 无法在源表中获得一组稳定的行,这个地方balck_dn_new和black_dn出现了多对一的现象也是不允许的啊,为了正确使用MERGE,于是对balck_dn进行了排重工作
Delete From balck_dn_new a
Where a.Rowid >
(Select Min(x.Rowid) From balck_dn_new b Where b.a = a.a);
接着用上面的merger的SQL语句,成功处理,目的达到了.
Oracle 10g中MERGE有如下一些改进:
1、UPDATE或INSERT子句是可选的
2、UPDATE和INSERT子句可以加WHERE子句
3、ON条件中使用常量过滤谓词来insert所有的行到目标表中,不需要连接源表和目标表
4、UPDATE子句后面可以跟DELETE子句来去除一些不需要的行