merge用法(读书笔记)
来源:互联网 发布:直播软件推广 编辑:程序博客网 时间:2024/06/04 01:31
《剑破冰山》--merge用法
CREATE TABLE test092801(NAME VARCHAR2(20),money NUMBER);INSERT INTO test092801 VALUES ('A',10);INSERT INTO test092801 VALUES ('B',20);CREATE TABLE test092802(NAME VARCHAR2(20),money NUMBER);INSERT INTO test092802 VALUES ('A',30);INSERT INTO test092802 VALUES ('C',20);COMMIT;
SQL> SELECT * FROM test092801; NAME MONEY-------------------- ----------A 10B 20 SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 30C 20
需求:从test092801表更新数据到test092802,如果test092802表name字段的记录在test092801表中存在,就将money值相加,
如果不存在,则将test092801的记录插到test092802表中
用merge可以用时合并update和Insert动作,如下
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 WHEN NOT MATCHED THEN 7 INSERT 8 VALUES (test092801.name,test092801.money); 2 rows merged SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 40C 20B 20
oracle10g中merge得到改善,可以Update和Insert选其一
可选择仅更新目标表
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money;
可选择仅插入目标表
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN NOT MATCHED THEN 4 INSERT 5 VALUES (test092801.name,test092801.money);
可对merge语句加条件
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money 6 WHERE test092801.name = 'A'; 1 row merged SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 10C 20B 20
可用delete子句清除行
前提条件,要找到满足test092801.name=test092802.name的记录,如果test092802.name = 'A'并不满足test092801.name = test092802.name
过滤出的记录集,那么delete是不会生效的。在满足前提的条件下,可以删除目标表的记录
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 DELETE WHERE (test092802.name = 'A'); 2 rows merged SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------C 20B 40
可采用无条件方式Insert
在语法on 后面写上恒不等式1=2,那么insert就变成无条件Insert,同于Insert.....select,如下:
MERGE INTO test092802USING test092801 ON (1=2)WHEN MATCHED THEN UPDATE INSERT VALUES (test092801.name,test092801.money);
merge语法注意点
在merge INTO test092802 ON ...的merge表达式中,如果一条test092802记录被连接到多条test092801记录,就产生ora-30926错误
SQL> DROP TABLE test092801; Table droppedSQL> DROP TABLE test092802; Table droppedSQL> CREATE TABLE test092801(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092801 VALUES ('A',10); 1 row insertedSQL> INSERT INTO test092801 VALUES ('A',30); 1 row insertedSQL> INSERT INTO test092801 VALUES ('B',20); 1 row insertedSQL> CREATE TABLE test092802(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092802 VALUES ('A',30); 1 row insertedSQL> INSERT INTO test092802 VALUES ('C',20); 1 row insertedSQL> COMMIT; Commit complete
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money; MERGE INTO test092802USING test092801 ON (test092801.name = test092802.name)WHEN MATCHED THEN UPDATE SET test092802.money = test092801.money+test092802.money ORA-30926: 无法在源表中获得一组稳定的行
oracle中的merge语句应该保证on中条件的唯一性,test092801.name = 'A'时,test092802表记录对应到test092801表的两条记录,所以就出错
需要注意的是,在merge INTO test092802 ON ...的merge表达式中,如果反过来,一条test092801记录被连接到多条test092802记录,是可以使
多条test092802记录都被更新而不会出错。
SQL> DROP TABLE test092801; Table droppedSQL> DROP TABLE test092802; Table droppedSQL> CREATE TABLE test092801(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092801 VALUES ('A',10); 1 row insertedSQL> INSERT INTO test092801 VALUES ('B',20); 1 row insertedSQL> CREATE TABLE test092802(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092802 VALUES ('A',30); 1 row insertedSQL> INSERT INTO test092802 VALUES ('A',40); 1 row insertedSQL> INSERT INTO test092802 VALUES ('C',20); 1 row insertedSQL> COMMIT; Commit complete
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money; 2 rows mergedSQL> COMMIT; Commit complete SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 40A 50C 20
可以看到,为A的两条记录都被更新了。
即目标表可以有多条记录,但是源表只可以有一条记录与之对应。
delete子句的where顺序必须在最后
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 DELETE WHERE (test092802.name = 'A') 7 WHERE test092801.name = 'A'; MERGE INTO test092802USING test092801 ON (test092801.name = test092802.name)WHEN MATCHED THEN UPDATE SET test092802.money = test092801.money+test092802.money DELETE WHERE (test092802.name = 'A') WHERE test092801.name = 'A' ORA-00933: SQL 命令未正确结束
修改如下
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 WHERE test092801.name = 'A' 7 DELETE WHERE (test092802.name = 'A') 8 ; 2 rows merged SQL> commit; Commit complete SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------C 20
DELETE 子句只可以删除目标表,而不可以删除源表
注意的是,无论DELETE WHERE (test092802.name = 'A')这个语句将test092802改成test092801,效果都是一样的,都是对目标表进行删除
SQL> DROP TABLE test092801; Table droppedSQL> DROP TABLE test092802; Table droppedSQL> CREATE TABLE test092801(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092801 VALUES ('A',10); 1 row insertedSQL> INSERT INTO test092801 VALUES ('B',20); 1 row insertedSQL> CREATE TABLE test092802(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092802 VALUES ('A',30); 1 row insertedSQL> INSERT INTO test092802 VALUES ('C',20); 1 row insertedSQL> COMMIT; Commit complete
SQL> SELECT * FROM test092801; NAME MONEY-------------------- ----------A 10B 20 SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 30C 20
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 WHERE test092801.name = 'A' 7 DELETE WHERE (test092802.name = 'A') 8 ; 1 row merged SQL> SELECT * FROM test092801; NAME MONEY-------------------- ----------A 10B 20 SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------C 20
可以看到目标表中的A记录被删除,如果将DELETE WHERE (test092802.name = 'A')改为DELETE WHERE (test092801.name = 'A'),是否就会把源表
的记录删除呢,试验如下:
SQL> MERGE INTO test092802 2 USING test092801 ON (test092801.name = test092802.name) 3 WHEN MATCHED THEN 4 UPDATE 5 SET test092802.money = test092801.money+test092802.money 6 WHERE test092801.name = 'A' 7 DELETE WHERE (test092801.name = 'A') 8 ; 0 rows merged SQL> SELECT * FROM test092801; NAME MONEY-------------------- ----------A 10B 20 SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------C 20
发现其实test092801源表的记录还是保留着,仍然只是目标表(MERGE后面的就是目标表)被删除
更新同一张表的数据,需担心using的空值
SQL> DROP TABLE test092802; Table dropped SQL> SQL> CREATE TABLE test092802(NAME VARCHAR2(20),money NUMBER); Table createdSQL> INSERT INTO test092802 VALUES ('A',30); 1 row insertedSQL> INSERT INTO test092802 VALUES ('C',20); 1 row insertedSQL> COMMIT; Commit complete
SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 30C 20
需求为对test092802表进行自我更新,如果在test092802表中发现name = 'D'的记录,就将该记录的Money字段更新为100,如果name = 'D'的
记录不存在,则自动增加name = 'D'的记录
SQL> MERGE INTO test092802 2 USING (SELECT * FROM test092802 WHERE NAME = 'D') t 3 ON (t.name = test092802.name) 4 WHEN MATCHED THEN 5 UPDATE 6 SET test092802.money = 100 7 WHEN NOT MATCHED THEN 8 INSERT 9 VALUES ('D',200) 10 ; 0 rows merged SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 30C 20
但是查询发现,test092802毫无变化
原因是using后面必须包含要更新或插入的行,而第一个USING (SELECT * FROM test092802 WHERE NAME = 'D') t根本没有这一行
改写如下:
SQL> MERGE INTO test092802 2 USING (SELECT COUNT(*) cnt FROM test092802 WHERE NAME = 'D') t 3 ON (t.cnt<>0) 4 WHEN MATCHED THEN 5 UPDATE 6 SET test092802.money = 100 7 WHEN NOT MATCHED THEN 8 INSERT 9 VALUES ('D',200) 10 ; 1 row merged SQL> SELECT * FROM test092802; NAME MONEY-------------------- ----------A 30C 20D 200
0 0
- merge用法(读书笔记)
- merge 复杂用法(sqlserver)
- merge用法
- MERGE用法
- merge用法
- merge用法
- MERGE 用法
- MERGE 用法
- merge用法
- SVN用法(merge,branch,switch)
- SVN用法(merge,branch,switch)
- oracle-merge用法详解
- oracle-merge用法详解
- oracle-merge用法详解
- oracle-merge用法详解
- oracle-merge用法详解
- oracle-merge用法详解
- oracle-merge用法详解
- gdb学习
- java volatile
- jdk 安装
- windows下运行的linux服务器批量管理工具(带UI界面)
- ubuntu下安装mysql出现FATAL ERROR: Could not find mysqld的处理
- merge用法(读书笔记)
- Mockups知识点
- [树莓派内核学习] u-boot移植
- 农历和阳历的相互转化
- 《数据结构》实验一: VC编程工具的灵活使用
- day34,page55
- 关于if (!cin)
- JSP编程技术5-购物车的实现-session会话对象
- hdu 5055 Bob and math problem