MERGE¶
说明¶
MERGE可以从源数据中通过条件限制选择出一行或者是多行数据对目标表或者目标视图进行更新或插入操作。
MERGE可以在一条SQL语句中同时实现对数据库表的INSERT、UPDATE、DELETE多项操作。
MERGE的操作结果是非常确定的,除非使用相同的数据,否则不能一次对目标表的同一行进行多次的更新操作。
参数¶
INTO Clause
用于指定需要更新或插入数据的表名或视图名;当对一个视图操作的时候,这个视图必须是可更新的
USING Clause
用于指定源数据中需要用于插入或更新的数据。源数据可以来自于表、视图或通过子查询获取。
ON Clause
用于MERGE更新或插入操作的条件限定。对于目标表中匹配成功的行,神通数据库会对目标表中的相应行进行更新操作;对于目标表中不能匹配成功的行,神通数据库会对目标表中的相应行进行插入操作。如果想要对源数据表中的所有行执行相应的操作,可以在ON Clause中使用类似ON (0=1) 或ON(1=1)这样的恒值过滤器。
merge_update_clause
用于指定目标表中需要更新字段的新数据。在满足ON Clause限定条件为真的情况下,数据库会执行更新操作。如果更新操作被执行,那么依附于目标表的更新触发器会被激活。
此处的where_clause是用于让数据库只对那些满足WHERE条件的目标表的行进行更新操作,否则数据库在执行MERGE操作的时候会跳过相应的行。
此处的DELETE where_clause是用于在对数据更新的同时对满足where条件的行进行删除操作。当删除操作被执行,依附于目标表中的删除触发器将会被激活。但值得注意的是,进行DELETE where_clause判断的行一定是需要进行更新操作的行,而且如果DELETE where_clause条件中用到了目标表的值,则此时的值使用的是更新后的新值。
merge_insert_clause
指定当ON Clause条件限定为假时用于向目标表中进行插入操作的数据值。当插入操作被执行的时候,所有依附于目标表中的插入触发器全会被激活。如果在INSERT关键字后面出现了字段列表,那么在字段列表中的字段数和VALUES关键字中的数据数必须匹配,否则自动扩展出相应的值。
此处的where_clause是用于限定只有在WHERE条件为真的时候才执行INSERT操作,同时此处的条件限定只对源数据表有效。数据库会跳过对所有不满足限定条件的行执行INSERT操作。
注解
在执行MERGE语句对目标表进行INSERT和UPDATE操作和对源数据表进行SELECT操作的时候,必须具有对目标表和源数据表的相应权限;在执行DELETE操作的时候,也需要有相应的权限。
如果出现目标表一行对应源表多行的情况,则要保证源值相同、目标值相同、源值和目标值相同,避免出现对目标表的同一行进行多次修改。
如果在merge语句出现列不确定是属于源表还是目标表的时候,出现在on条件报错,否则按照从update_set、update_where、delete_where、insert_values、insert_where的顺序(如果出现子查询,则只查找其左子树),从当前列的位置开始往后查找,找到第一个和该列同名,且有表名,则该表就是其所属表,就是其所属表,否则认为该列来之目标表。
如果子查询中的列不确定时,先查找from后面的表,再在本层从头到后查找,如果查不到,返回上层查找,如果上层是merge层,按照update_set、update_where、delete_where、insert_values、insert_where的顺序,从头到后查找,找到第一个和该列同名,且有表名,则该表就是其所属表,否则先查找目标表,再查找源表,如果都找不到,则报错。
对于INSERT分支,如果出现目标列,除了子查询外,都报错。
对于事件触发器,根据UPDATE、DELETE、INSERT分支是否存在,触发相应的事件触发器。也就是如果目标表存在UPDATE、DELETE、INSERT事件触发器,且UPDATE、DELETE、INSERT分支都存在,则UPDATE、DELETE、INSERT事件触发器都进行触发。
如果需要对在一条SQL语句中对数据进行多项DML操作,而且数据的操作量较大,建议使用MERGE语句。
示例¶
示例1: 合并表
-- 清理环境
DROP TABLE tab1 CASCADE;
DROP TABLE tab2 CASCADE;
-- 创建表并插入数据
CREATE TABLE tab1(a INT , b VARCHAR(20));
INSERT INTO tab1 VALUES(1 , '11');
INSERT INTO tab1 VALUES(2 , '12');
INSERT INTO tab1 VALUES(3 , '13');
INSERT INTO tab1 VALUES(6 , '16');
SELECT * FROM tab1 ORDER BY a, b;
A(int) |B(varchar) |
----------------------------
1 |11 |
----------------------------
2 |12 |
----------------------------
3 |13 |
----------------------------
6 |16 |
总数目:4
CREATE TABLE tab2(a INT , b VARCHAR(20));
INSERT INTO tab2 VALUES(1 , '21');
INSERT INTO tab2 VALUES(2 , '22');
INSERT INTO tab2 VALUES(3 , '23');
INSERT INTO tab2 VALUES(4 , '24');
INSERT INTO tab2 VALUES(5 , '25');
SELECT * FROM tab2 ORDER BY a, b;
A(int) |B(varchar) |
----------------------------
1 |21 |
----------------------------
2 |22 |
----------------------------
3 |23 |
----------------------------
4 |24 |
----------------------------
5 |25 |
总数目:5
-- 合并表
MERGE INTO tab2 USING tab1 ON (tab1.a = tab2.a)
WHEN MATCHED THEN
UPDATE SET tab2.b = tab1.b
DELETE WHERE tab2.a = 3
WHEN NOT MATCHED THEN
INSERT VALUES(tab1.a , tab1.b) WHERE tab1.a = 6;
-- 查看合并结果
SELECT * FROM tab1 ORDER BY a, b;
A(int) |B(varchar) |
----------------------------
1 |11 |
----------------------------
2 |12 |
----------------------------
3 |13 |
----------------------------
6 |16 |
总数目:4
SELECT * FROM tab2 ORDER BY a, b;
A(int) |B(varchar) |
----------------------------
1 |11 |
----------------------------
2 |12 |
----------------------------
4 |24 |
----------------------------
5 |25 |
----------------------------
6 |16 |
总数目:5
-- 删除表
drop table tab1;
drop table tab2;