SQLServer MERGE 用法

本文深入探讨SQL Merge语句的使用技巧,通过具体案例展示如何高效地从JSON数据中提取信息并应用于数据库的更新与插入操作。文章涵盖Merge语句的基本语法、常见坑点及官方示例,适合数据库开发者及SQL进阶学习者。

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

今天写存储过程的时候,遇到了从一个大json串中取一个id号比对,如果是存在的就更新,不存在就新增。查了资料,觉得还是用merge比较好,这个用法坑也不少,一起来看看代码吧。

MERGE tABatch AS t  -- 需要操作的主体表
USING(
	SELECT batchNo,COUNT(0) AS waitTotal
	FROM (
	SELECT batchNo FROM OPENJSON(@checkJson)
	WITH(batchNo VARCHAR(50) '$.batchNo')
    ) t GROUP BY t.batchNo
	) AS s (batchNo,waitTotal) -- USING里面是数据源,as以后,必须按照顺序指定字段名
    ON t.batchNo = s.batchNo  -- 这里是对比的条件
	WHEN MATCHED THEN 
	-- 如果有匹配就更新,只用写要更新的内容即可
		UPDATE SET t.waitTotal = t.waitTotal+s.waitTotal
	WHEN NOT MATCHED THEN 
	-- 没有匹配就新增,注意这里的INSERT不能再跟表名了
	INSERT  
	(
		batchNo,
		waitTotal,
		createTime
	)VALUES(
		s.batchNo,
		s.waitTotal,
		getdate()
	);
-- merge必须分号结尾,不然报错

上面是我的示例,如果不放心可以来看看官方的:

CREATE PROCEDURE dbo.InsertUnitMeasure  
    @UnitMeasureCode nchar(3),  
    @Name nvarchar(25)  
AS   
BEGIN  
    SET NOCOUNT ON;  
-- Update the row if it exists.      
    UPDATE Production.UnitMeasure  
SET Name = @Name  
WHERE UnitMeasureCode = @UnitMeasureCode  
-- Insert the row if the UPDATE statement failed.  
IF (@@ROWCOUNT = 0 )  
BEGIN  
    INSERT INTO Production.UnitMeasure (UnitMeasureCode, Name)  
    VALUES (@UnitMeasureCode, @Name)  
END  
END;  
GO  
-- Test the procedure and return the results.  
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Test Value';  
SELECT UnitMeasureCode, Name FROM Production.UnitMeasure  
WHERE UnitMeasureCode = 'ABC';  
GO  
  
-- Rewrite the procedure to perform the same operations using the 
-- MERGE statement.  
-- Create a temporary table to hold the updated or inserted values 
-- from the OUTPUT clause.  
CREATE TABLE #MyTempTable  
    (ExistingCode nchar(3),  
     ExistingName nvarchar(50),  
     ExistingDate datetime,  
     ActionTaken nvarchar(10),  
     NewCode nchar(3),  
     NewName nvarchar(50),  
     NewDate datetime  
    );  
GO  
ALTER PROCEDURE dbo.InsertUnitMeasure  
    @UnitMeasureCode nchar(3),  
    @Name nvarchar(25)  
AS   
BEGIN  
    SET NOCOUNT ON;  
   -- 重点看这一段
    MERGE Production.UnitMeasure AS target  
    USING (SELECT @UnitMeasureCode, @Name) AS source (UnitMeasureCode, Name)  
    ON (target.UnitMeasureCode = source.UnitMeasureCode)  
    WHEN MATCHED THEN   
        UPDATE SET Name = source.Name  
WHEN NOT MATCHED THEN  
    INSERT (UnitMeasureCode, Name)  
    VALUES (source.UnitMeasureCode, source.Name)  
    OUTPUT deleted.*, $action, inserted.* INTO #MyTempTable;  
END;  
GO  
-- Test the procedure and return the results.  
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'New Test Value';  
EXEC InsertUnitMeasure @UnitMeasureCode = 'XYZ', @Name = 'Test Value';  
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Another Test Value';  
  
SELECT * FROM #MyTempTable;  
-- Cleanup   
DELETE FROM Production.UnitMeasure WHERE UnitMeasureCode IN ('ABC','XYZ');  
DROP TABLE #MyTempTable;  
GO

 

SQL Server的`MERGE`语句(也称为“合并”或“事务性插入/更新”)是一种用于高效地更新数据库中的记录的强大工具,尤其适用于那些需要处理存在冲突情况(如源数据与目标表已有相同键值的数据不一致)的情景。 `MERGE`的基本语法如下: ```csharp MERGE INTO target_table USING source_table ON (target_table.key_column = source_table.key_column) WHEN MATCHED THEN UPDATE SET target_column = source_column WHEN NOT MATCHED BY TARGET THEN INSERT (column1, column2, ...) VALUES (value1, value2, ...) WHEN NOT MATCHED BY SOURCE THEN DELETE; ``` 这里解释一下各个部分: 1. `INTO target_table`: 指定要操作的目标表。 2. `USING source_table`: 使用哪个表作为源数据进行比较,通常包含要插入、更新或删除的记录。 3. `ON condition`: 定义匹配条件,通常是基于共享的关键字段。 4. `WHEN MATCHED`: 当目标表中有匹配项时执行的操作,可以选择更新特定列的值。 5. `SET target_column = source_column`: 更新目标表中的列。 6. `WHEN NOT MATCHED BY TARGET`: 如果目标表中没有匹配项,但源表有,则插入新行。 7. `THEN INSERT`: 插入新的记录到目标表,列出要插入的列和值。 8. `WHEN NOT MATCHED BY SOURCE`: 如果源表中也没有匹配项,意味着要从目标表中删除已存在的记录。 使用`MERGE`的好处包括: - 提供了一种非破坏性的数据更新机制,只对实际需要更改的部分进行操作。 - 可以同时处理插入、更新和删除操作,简化了维护逻辑。 - 自动处理了并发控制和锁定,减少死锁可能性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值