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 (頁面存檔備份,存於網際網路檔案館)