SQL Server中Upsert的三种方式

本文介绍SQLServer中实现Upsert功能的三种常见方法及其性能比较。通过实验对比了先查询后操作、先更新后判断插入以及使用MERGE语句的方法,在不同场景下的性能表现,发现对于大多数应用而言,方法2在可读性和性能方面表现更佳。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文介绍了SQL Server中Upsert的三种常见写法以及他们的性能比较。

SQL Server并不支持原生的Upsert语句,通常使用组合语句实现upsert功能。

 

假设有表table_A,各字段如下所示:

int型Id为主键。

 

方法1:先查询,根据查询结果判断使用insert或者update

IF EXISTS (SELECT 1 FROM table_A WHERE Id = @Id)
    BEGIN
        UPDATE dbo.table_A
        SET Value = @Value
        WHERE Id = @Id;
    END
ELSE
    BEGIN
        INSERT INTO dbo.table_A (Id, Value)
        VALUES(@Id, @Value)
    END

 

方法2:先更新,根据更新结果影响的条目数判断是否需要插入

UPDATE dbo.table_A
SET Value = @Value
WHERE Id = @Id;
    
IF(@@ROWCOUNT = 0)
BEGIN
    INSERT INTO dbo.table_A (Id, Value)
    VALUES(@Id, @Value)
END

 

方法3:使用MERGE语句,将待upsert的数据作为source,merge到目标表 

MERGE INTO table_A as T
USING (SELECT @Id AS id, @Value AS value ) AS S
ON T.Id = S.id
WHEN MATCHED THEN
    UPDATE SET T.Value = S.value
WHEN NOT MATCHED THEN
    INSERT(Id, Value) VALUES(S.id, S.value);

 

性能比较

在50万行数据项中随机upsert10万次

 

场景一:upsert数据项100%命中update

 

场景二:upsert数据项100%命中insert

 

场景三:upsert数据项Id为随机数,~50%insert,~50%update

 

从图中可以看出实验数据存在部分偏差,大体上这三种方法在性能上的差别非常小。对于绝大多数upsert并非关键路径的程序,方法2在可读性和执行性能上综合来讲是较优的方案。

在对性能苛求的场景,可以选用MERGE语句,以下是MERGE语句的优点:”

  1. Faster performance. The Engine needs to parse, compile, and execute only one query instead of three (and no temporary variable to hold the key).
  2. Neater and simpler T-SQL code (after you get proficient in MERGE).
  3. No need for explicit BEGIN TRANSACTION/COMMIT. MERGE is a single statement and is executed in one implicit transaction.
  4. Greater functionality. MERGE can delete rows that are not matched by source (SRC table above). For example, we can delete row 1 from A_Table because its Data column does not match Search_Col in the SRC table. There is also a way to return inserted/deleted values using the OUTPUT clause.“

引用:http://www.sergeyv.com/blog/archive/2010/09/10/sql-server-upsert-equivalent.aspx

转载于:https://www.cnblogs.com/zhenfengren/p/5618511.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值