首页 > 数据库 > 数据库开发技术 > 飘香新特性之Merge语法增强
即将发布的PG 17针对MERGE关键字有如下几点新特性:
Allow partitions to be merged using ALTER TABLE ... MERGE PARTITIONS (Dmitry Koval)
Allow MERGE to modify updatable views (Dean Rasheed)
Add WHEN NOT MATCHED BY SOURCE to MERGE (Dean Rasheed)
Allow MERGE to use the RETURNING clause (Dean Rasheed)
https://www.postgresql.org/docs/devel/release-17.html
MERGE PARTITIONS的用法前几天写过文章:分区表的两大刚需|拆分分区 |合并分区
后面几点主要与Merge Into语法有关,而不是分区表的Merge。
[ WITH with_query [, ...] ]
MERGE INTO target_table_name [ [ AS ] target_alias ]
USING data_source ON join_condition
when_clause [...]
PG 17对Merge Into语法增加了Returning子句
[ WITH with_query [, ...] ]
MERGE INTO target_table_name [ [ AS ] target_alias ]
USING data_source ON join_condition
when_clause [...][ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
本文将主要针对Merge语句增加的Returning子句进行测试。
参考六种常见的组合模式,在17里测试Merge语句与Returning子句
用b_merge来更新a_merge中的数据:
merge into a_merge a
using (select b.aid,b.name,b.year from b_merge b) c on (a.id=c.aid)
when matched then
update set year=c.year
when not matched then
insert values(c.aid,c.name,c.year)
returning * ;
aid | name | year | id | name | year
-----+----------+------+----+----------+------
2 | zhangbin | 30 | 2 | zhangbin | 30
3 | fuguo | | 3 | fuguo |
4 | yihe | 33 | 4 | yihe | 33
(3 rows)
MERGE 3
用b_merge来更新a_merge,但仅有update部分,没有insert部分。
merge into a_merge a
using (select b.aid,b.name,b.year from b_merge b) c on (a.id=c.aid)
when matched then
update set year=c.year
returning * ;
aid | name | year | id | name | year
-----+----------+------+----+----------+------
1 | liuwei | 80 | 1 | liuwei | 80
2 | zhangbin | 30 | 2 | zhangbin | 30
3 | fuguo | | 3 | fuguo |
4 | yihe | 33 | 4 | yihe | 33
(4 rows)
MERGE 4
3.目标表不匹配仅执行insert
用b_merge来更新a_merge中的数据,此时只有insert,没有写update:
merge into a_merge a
using (select b.aid,b.name,b.year from b_merge b) c on (a.id=c.aid)
when not matched then
insert values(c.aid,c.name,c.year)
returning * ;
aid | name | year | id | name | year
-----+----------+------+----+----------+------
5 | tiantian | 23 | 5 | tiantian | 23
(1 row)
MERGE 1
在on中进行join匹配之后,还可以在后面的when子句中对on筛选出来的记录再做一次条件判断,控制哪些要更新,哪些要插入,哪些要删除。
用b_merge去更新a_merge,分别在insert和update后添加条件限制,控制数据的更新和插入:
merge into a_merge a
using (select b.aid,b.name,b.year,b.city from b_merge b) c on (a.id=c.aid)
when matched and c.city != '江西' then
update set name=c.name
when not matched and c.city = '江西' then
insert values(c.aid,c.name,c.year)
returning * ;
aid | name | year | city | id | name | year
-----+----------+------+--------+----+----------+------
2 | zhangbin | 70 | 吉林 | 2 | zhangbin | 30
3 | fuguo | | 山东 | 3 | fuguo |
4 | yihe++ | 33 | 黑龙江 | 4 | yihe++ | 33
5 | tiantian | 23 | 河南 | 5 | tiantian | 23
6 | ningqin | 23 | 江西 | 6 | ningqin | 23
(5 rows)
MERGE 5
无条件全插入,on条件设置为永假,用b_merge来更新c_merge:
merge into c_merge c
using (select b.aid,b.name,b.city from b_merge b) b on (1=0)
when not matched then
insert values(b.aid,b.name,b.city)
returning * ;
aid | name | city | id | name | city
-----+----------+--------+----+----------+--------
3 | fuguo | 山东 | 3 | fuguo | 山东
5 | tiantian | 河南 | 5 | tiantian | 河南
2 | zhangbin | 吉林 | 2 | zhangbin | 吉林
4 | yihe++ | 黑龙江 | 4 | yihe++ | 黑龙江
1 | liuwei++ | 江西 | 1 | liuwei++ | 江西
6 | ningqin | 江西 | 6 | ningqin | 江西
7 | bing | 四川 | 7 | bing | 四川
(7 rows)
MERGE 7
6.匹配则delete
when匹配子句里除了update,也可以执行delete子句。
用b_merge来匹配删除a_merge,删除时可进行二次匹配删除。
merge into a_merge a
using (select b.aid,b.name,b.year,b.city from b_merge b) c on (a.id=c.aid)
when matched and c.city = '江西' then
delete
returning * ;
aid | name | year | city | id | name | year
-----+----------+------+------+----+---------+------
1 | liuwei++ | 80 | 江西 | 1 | liuwei | 80
6 | ningqin | 23 | 江西 | 6 | ningqin | 23
(2 rows)
MERGE 2
只有符合关联条件且满足条件的数据才会被删除。
merge into a_merge a
using (select b.aid,b.name,b.year,b.city from b_merge b) c on (a.id=c.aid)
when matched and c.city = '江西' then
delete
returning a.*, merge_action() ;
id | name | year | merge_action
----+---------+------+--------------
1 | liuwei | 80 | DELETE
6 | ningqin | 23 | DELETE
(2 rows)
MERGE 2
非常棒的功能!
原文作者:象楚之行;如有侵权,请联系管理员删除。