Merge (SQL)

关系数据库管理系统使用SQL'语句(也被称为upsert**)来处理数据:它根据特定的匹配条件,决定是插入(INSERT)新记录,还是更新(UPDATE)或删除(DELETE)现有记录。该语句在标准中被正式引入,并在标准中得到了进一步扩展。
用法
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 ...]);

语句在目标表(表)和源表(表/视图/子查询)之间执行右连接(Right Join)——其中目标表为左表,源表为右表。四种可能的组合产生了以下规则:
*源表中有,目标表中也有(条件匹配):执行。
*源表中有,目标表中没有(条件不匹配):执行。
*源表中没有,目标表中有:不执行任何操作。
*源表和目标表中都没有:不执行任何操作。

注意:根据标准,如果多个源表行匹配同一个目标表行,必须报错。你不能使用一条语句多次更新同一行目标表数据。
实现情况
PostgreSQL、Oracle、DB2、SQL Server等主流数据库均支持标准语法。
同义词
一些数据库实现采用了Upsert(Update和Insert的混成词)这一术语,指代“如果记录不存在则插入,如果已存在则更新”的数据库语句或组合。PostgreSQL (v9.5+)、SQLite(v3.24+) 、Microsoft Azure SQL Database均使用此术语。

标准定义了MERGE 语句,用以提供类似的功能。

通常情况下,数据库操作运行在多个代理(Agent/进程)同时对同一个数据库执行查询的环境中。如果数据库管理系统(DBMS)本身不支持原生版本的UPSERT或MERGE,则该操作应当封装在一个事务(Transaction)中,以确保其隔离性(Isolation)和原子性(Atomicity)。

其他非标准实现
在MySQL中,UPSERT操作是通过语法实现的(即:如果行已存在,则执行更新操作)。但限制是连接必须基于主键或唯一索引。此外还支持(先删再插),即首先尝试进行插入操作;如果插入失败,则删除已存在的行(若存在),最后再插入新记录。还支持,告知服务器忽略“重复键(duplicate key)”错误并继续执行(即:现有的行不会被插入或更新,但所有新的行都会被正常插入)。

SQLite:支持。还支持作为兼容MySQL的别名。

Firebird支持。还支持单行版本的,但后者无法在插入和更新时采取不同的操作(例如仅为新行设置序列值)。

IBM DB2:扩展了多个和子句,并支持通过条件进行细分过滤。

Microsoft SQL Server:支持通过 WHEN NOT MATCHED BY SOURCE 来处理源表中不存在但目标表中存在的行(即支持了左连接语义)。

PostgreSQL自第15版本起开始支持MERGE语句,但在此之前,它通过.语法来支持合并操作。

CUBRID支持MERGE INTO语句,同时也支持使用语法。为了兼容MySQL,它还支持。

支持和UPSERT SELECT语法。

Spark SQL在操作中支持和子句。

支持语法。
在NoSQL中的应用
类似的概念也应用于某些NoSQL数据库中。

在MongoDB中,可以通过操作更新与键相关联的值中的字段。如果找不到该键,操作会报错。但在操作中可以设置标志:在这种情况下,如果键不存在,则存储一个与给定键关联的新值;否则,整个值将被替换。

在Redis中,操作用于设置与给定键关联的值。由于Redis不了解该值内部结构的任何细节,因此“更新(update)”操作没有意义。所以操作始终具有“设置或替换(set or replace)”的语义。
参考文献
*
*

外部链接

评论 (0)

  • 还没有评论,来抢沙发吧。