最近使用 merge into 语句时发现,update,delete之间存在一些微妙的关系,特将结论和测试过程列举如下:
测试环境:oracle11g
结论:在merge into中,当update子句中存在where clause时,只有满足on和update中的where双重条件时,才会执行delete 子句。--创建测试表,并插入数据
CREATE TABLE t1 (
"ID" NUMBER(10) NOT NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER(10) NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t1 VALUES ('1201', 'Peter', '23', 'male');
INSERT INTO t1 VALUES ('6695', 'Lu', '12', 'female');
INSERT INTO t1 VALUES ('6720', 'Ka', '22', 'female');
CREATE TABLE t2 (
"ID" NUMBER NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t2 VALUES ('1201', 'John', '47', 'male');
INSERT INTO t2 VALUES ('1202', 'lili', '30', 'female');
--结果0
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- ---------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
SQL> select * from t2; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
1202 lili 30 female
--测试1
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name<>'Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果1
--创建测试表,并插入数据
CREATE TABLE t1 (
"ID" NUMBER(10) NOT NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER(10) NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t1 VALUES ('1201', 'Peter', '23', 'male');
INSERT INTO t1 VALUES ('6695', 'Lu', '12', 'female');
INSERT INTO t1 VALUES ('6720', 'Ka', '22', 'female');
CREATE TABLE t2 (
"ID" NUMBER NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t2 VALUES ('1201', 'John', '47', 'male');
INSERT INTO t2 VALUES ('1202', 'lili', '30', 'female'); --结果
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- ---------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
SQL> select * from t2; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
1202 lili 30 female
--测试1
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name<>'Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果1
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female可见,通过上述代码,只是将 t2 中 id 为 1202 的记录insert到了t1中,并没有将t1中name为Peter的记录删除,即delete语句没有执行。
rollback 回退结果。
现在表t1中内容为:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
--测试2:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name='Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果2:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female因为先执行了update,将t1中id为1201中的name修改为了John,所以不满足delete条件,delete不执行。从该测试中可以知道,当满足on条件时,先执行update后执行delete。同样rollback,
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- -------------------
6695 Lu 12 female
6720 Ka 22 female
1201 Peter 23 male--测试3:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where b.id='1201'
delete where (b.id = '1201')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ;
--结果3:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female
当既满足on条件又满足update中的where条件时,delete语句执行了。
为了确保万一,我们验证一下不满足update中where条件的情况:
--测试4:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where b.id<>'1201'
delete where (b.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ;
--结果4:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
6695 Lu 12 female
6720 Ka 22 female
1201 Peter 23 male
1202 lili 30 female如上,对于1201记录,虽然既满足on条件,又满足delete中的where条件,但是因为不满足update的where条件,所以delete并没有执行。综上:在merge into中,当update子句中存在where clause时,只有满足on和update中的where双重条件时,才会执行delete 子句。
如有疏漏的地方,欢迎大家指正~
测试环境:oracle11g
结论:在merge into中,当update子句中存在where clause时,只有满足on和update中的where双重条件时,才会执行delete 子句。--创建测试表,并插入数据
CREATE TABLE t1 (
"ID" NUMBER(10) NOT NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER(10) NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t1 VALUES ('1201', 'Peter', '23', 'male');
INSERT INTO t1 VALUES ('6695', 'Lu', '12', 'female');
INSERT INTO t1 VALUES ('6720', 'Ka', '22', 'female');
CREATE TABLE t2 (
"ID" NUMBER NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t2 VALUES ('1201', 'John', '47', 'male');
INSERT INTO t2 VALUES ('1202', 'lili', '30', 'female');
--结果0
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- ---------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
SQL> select * from t2; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
1202 lili 30 female
--测试1
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name<>'Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果1
--创建测试表,并插入数据
CREATE TABLE t1 (
"ID" NUMBER(10) NOT NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER(10) NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t1 VALUES ('1201', 'Peter', '23', 'male');
INSERT INTO t1 VALUES ('6695', 'Lu', '12', 'female');
INSERT INTO t1 VALUES ('6720', 'Ka', '22', 'female');
CREATE TABLE t2 (
"ID" NUMBER NULL ,
"NAME" VARCHAR2(255 BYTE) NULL ,
"AGE" NUMBER NULL ,
"SE" VARCHAR2(255 BYTE) NULL
)
;
INSERT INTO t2 VALUES ('1201', 'John', '47', 'male');
INSERT INTO t2 VALUES ('1202', 'lili', '30', 'female'); --结果
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- ---------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
SQL> select * from t2; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
1202 lili 30 female
--测试1
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name<>'Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果1
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female可见,通过上述代码,只是将 t2 中 id 为 1202 的记录insert到了t1中,并没有将t1中name为Peter的记录删除,即delete语句没有执行。
rollback 回退结果。
现在表t1中内容为:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 Peter 23 male
6695 Lu 12 female
6720 Ka 22 female
--测试2:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where t1.name='Peter'
delete where (t1.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ; --结果2:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
1201 John 47 male
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female因为先执行了update,将t1中id为1201中的name修改为了John,所以不满足delete条件,delete不执行。从该测试中可以知道,当满足on条件时,先执行update后执行delete。同样rollback,
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- -------------------
6695 Lu 12 female
6720 Ka 22 female
1201 Peter 23 male--测试3:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where b.id='1201'
delete where (b.id = '1201')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ;
--结果3:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
6695 Lu 12 female
6720 Ka 22 female
1202 lili 30 female
当既满足on条件又满足update中的where条件时,delete语句执行了。
为了确保万一,我们验证一下不满足update中where条件的情况:
--测试4:
MERGE INTO t1 b
USING t2 e
ON (b.ID = e.ID)
WHEN MATCHED THEN
update
set b.NAME = E.NAME,
b.AGE = E.AGE,
b.SE = E.SE
where b.id<>'1201'
delete where (b.name = 'Peter')
WHEN NOT MATCHED THEN
insert (b.ID,b.NAME,b.AGE,b.SE)
values(E.ID,E.NAME,E.AGE,E.SE) ;
--结果4:
SQL> select * from t1; ID NAME AGE SE
---------- -------------------- ---------- --------------------
6695 Lu 12 female
6720 Ka 22 female
1201 Peter 23 male
1202 lili 30 female如上,对于1201记录,虽然既满足on条件,又满足delete中的where条件,但是因为不满足update的where条件,所以delete并没有执行。综上:在merge into中,当update子句中存在where clause时,只有满足on和update中的where双重条件时,才会执行delete 子句。
如有疏漏的地方,欢迎大家指正~
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货