Merge (SQL)
关系数据库管理系统使用SQLMERGE语句(也被称为upsert)来处理数据:它根据特定的匹配条件,决定是插入(INSERT)新记录,还是更新(UPDATE)或删除(DELETE)现有记录。该语句在SQL:2003标准中被正式引入,并在SQL:2008标准中得到了进一步扩展。
用法
[编辑]MERGE INTO tablename USING table_reference ON (condition)
WHEN MATCHED THEN
UPDATE SET column1 = value1 [, column2 = value2 ...]
WHEN NOT MATCHED THEN
INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...]);
MERGE语句在目标表(INTO表)和源表(USING表/视图/子查询)之间执行右连接(Right Join)——其中目标表为左表,源表为右表。四种可能的组合产生了以下规则:
- 源表中有,目标表中也有(ON条件匹配):执行UPDATE。
- 源表中有,目标表中没有(ON条件不匹配):执行INSERT。
- 源表中没有,目标表中有:不执行任何操作。
- 源表和目标表中都没有:不执行任何操作。
注意:根据SQL:2003标准,如果多个源表行匹配同一个目标表行,必须报错。你不能使用一条MERGE语句多次更新同一行目标表数据。
实现情况
[编辑]PostgreSQL[1]、Oracle、DB2、SQL Server等主流数据库均支持标准语法。
同义词
[编辑]一些数据库实现采用了Upsert(Update和Insert的混成词)这一术语,指代“如果记录不存在则插入,如果已存在则更新”的数据库语句或组合。PostgreSQL (v9.5+)[2]、SQLite(v3.24+)[3] 、Microsoft Azure SQL Database[4]均使用此术语。
SQL:2003标准定义了MERGE 语句,用以提供类似的功能。
通常情况下,数据库操作运行在多个代理(Agent/进程)同时对同一个数据库执行查询的环境中。如果数据库管理系统(DBMS)本身不支持原生版本的UPSERT或MERGE,则该操作应当封装在一个事务(Transaction)中,以确保其隔离性(Isolation)和原子性(Atomicity)。
其他非标准实现
[编辑]在MySQL中,UPSERT操作是通过INSERT ... ON DUPLICATE KEY UPDATE语法实现的(即:如果行已存在,则执行更新操作)[5]。但限制是连接必须基于主键或唯一索引。此外还支持>REPLACE INTO(先删再插)[6],即首先尝试进行插入操作;如果插入失败,则删除已存在的行(若存在),最后再插入新记录。还支持INSERT IGNORE[7],告知服务器忽略“重复键(duplicate key)”错误并继续执行(即:现有的行不会被插入或更新,但所有新的行都会被正常插入)。
SQLite:支持INSERT OR REPLACE INTO。还支持REPLACE INTO作为兼容MySQL的别名。[8]
Firebird支持MERGE INTO。还支持单行版本的UPDATE OR INSERT INTO tablename (columns) VALUES (values) [MATCHING (columns)],但后者无法在插入和更新时采取不同的操作(例如仅为新行设置序列值)。
IBM DB2:扩展了多个WHEN MATCHED和WHEN NOT MATCHED子句,并支持通过... AND some-condition条件进行细分过滤。
Microsoft SQL Server:支持通过 WHEN NOT MATCHED BY SOURCE 来处理源表中不存在但目标表中存在的行(即支持了左连接语义)。
PostgreSQL自第15版本起开始支持MERGE语句,但在此之前,它通过INSERT INTO ... ON CONFLICT [ conflict_target ] conflict_action.[9]语法来支持合并操作。
CUBRID支持MERGE INTO语句[10],同时也支持使用INSERT ... ON DUPLICATE KEY UPDATE语法[11]。为了兼容MySQL,它还支持REPLACE INTO。[12]
Apache Phoenix支持UPSERT VALUES[13]和UPSERT SELECT[14]语法。
Spark SQL在操作中支持UPDATE SET *和INSERT *子句。[15]
Apache Impala支持UPSERT INTO ... SELECT语法。[16]
在NoSQL中的应用
[编辑]类似的概念也应用于某些NoSQL数据库中。
在MongoDB中,可以通过update操作更新与键相关联的值中的字段。如果找不到该键,update操作会报错。但在update操作中可以设置upsert标志:在这种情况下,如果键不存在,则存储一个与给定键关联的新值;否则,整个值将被替换。
在Redis中,SET操作用于设置与给定键关联的值。由于Redis不了解该值内部结构的任何细节,因此“更新(update)”操作没有意义。所以SET操作始终具有“设置或替换(set or replace)”的语义。
参考文献
[编辑]- ^ E.1. Release 15. PostgreSQL Documentation. 13 October 2022 [13 October 2022]. (原始内容存档于13 October 2022) (英语).
- ^ PostgreSQL Upsert Using INSERT ON CONFLICT statement. PostgreSQL Tutorial. (原始内容存档于Nov 28, 2022).
- ^ "upsert (页面存档备份,存于互联网档案馆)", SQLite, visited 6-6-2018.
- ^ MERGE (Transact-SQL). Transact-SQL Reference (Database Engine). Microsoft Learn. (原始内容存档于Jun 24, 2016).
- ^ MySQL :: MySQL 5.1 Reference Manual :: 12.2.4.3 INSERT ... ON DUPLICATE KEY UPDATE Syntax
- ^ MySQL 5.1 Reference Manual: 11.2.6 REPLACE Syntax. [2026-03-13]. (原始内容存档于2016-05-06).
- ^ MySQL 5.5 Reference Manual :: 13.2.5 INSERT Syntax. [29 October 2013]. (原始内容存档于2013-10-24).
- ^ SQL As Understood By SQLite: INSERT. [2012-09-27]. (原始内容存档于2012-09-23).
- ^ PostgreSQL INSERT page. [2026-03-13]. (原始内容存档于2016-12-28).
- ^ New CUBRID 9.0.0. CUBRID Official Blog. 2012-10-30 [2012-11-08]. (原始内容存档于2012-11-05).
- ^ CUBRID :: Data Manipulation Statements :: Insert :: ON DUPLICATE KEY UPDATE Clause. [2026-03-13]. (原始内容存档于2016-10-07).
- ^ CUBRID :: Data Manipulation Statements :: Replace. [2026-03-13]. (原始内容存档于2016-10-07).
- ^ UPSERT VALUES. [2026-03-13]. (原始内容存档于2016-12-27).
- ^ UPSERT SELECT. [2026-03-13]. (原始内容存档于2016-12-27).
- ^ MERGE INTO (Delta Lake on Databricks). [2026-03-13]. (原始内容存档于2022-10-01).
- ^ UPSERT Statement (Apache Impala Documentation). [2026-03-13]. (原始内容存档于2025-02-20).
- Hsu, Leo; Obe, Regina. Cross Compare of SQL Server, MySQL, and PostgreSQL. Postgres OnLine Journal. May 18, 2008 [8 October 2010]. (原始内容存档于2010-11-26).
- Chodorow, Kristina; Mike Dirolf. MongoDB: The Definitive Guide. O'Reilly. September 2010. ISBN 978-1-449-38156-1.
外部链接
[编辑]- Oracle 11g Release 2 documentation (页面存档备份,存于互联网档案馆) on
MERGE - Firebird 2.1 documentation (页面存档备份,存于互联网档案馆) on
MERGE - DB2 v9 MERGE statement (页面存档备份,存于互联网档案馆)
- Microsoft SQL Server documentation (页面存档备份,存于互联网档案馆)
- HSQLdb 2.0 Data Change Statements (页面存档备份,存于互联网档案馆)
- H2 (1.2) SQL Syntax page (页面存档备份,存于互联网档案馆)