SQL Server笔记 -- 第16章:MERGE

从SQL Server 2008开始,可以使用MERGE语句在单个语句中执行插入、更新或删除操作。

MERGE语句允许您将数据源与目标表或视图联接,然后根据该联接的结果对目标执行多个操作。

第16.1节:MERGE用于插入/更新/删除

sql 复制代码
MERGE INTO targetTable
USING sourceTable ON (targetTable.PKID = sourceTable.PKID)
WHEN MATCHED AND (targetTable.PKID > 100) THEN DELETE
WHEN MATCHED AND (targetTable.PKID <= 100) THEN UPDATE
    SET targetTable.ColumnA = sourceTable.ColumnA,
        targetTable.ColumnB = sourceTable.ColumnB
WHEN NOT MATCHED THEN
    INSERT (ColumnA, ColumnB) 
    VALUES (sourceTable.ColumnA, sourceTable.ColumnB);
WHEN NOT MATCHED BY SOURCE THEN DELETE ; --< 必需

描述:

  • MERGE INTO targetTable - 要修改的表
  • USING sourceTable - 数据源(可以是表、视图或表值函数)
  • ON ... - targetTable和sourceTable之间的联接条件。
  • WHEN MATCHED - 找到匹配时要采取的操作
    • AND (targetTable.PKID > 100) - 操作要满足的附加条件
    • THEN DELETE - 从targetTable删除匹配的记录
    • THEN UPDATE - 更新由SET ...指定的匹配记录的列
  • WHEN NOT MATCHED - 在targetTable中未找到匹配时要采取的操作
  • WHEN NOT MATCHED BY SOURCE - 在sourceTable中未找到匹配时要采取的操作

注释:

  • 如果不需要特定操作,则省略该条件,例如删除WHEN NOT MATCHED THEN INSERT将阻止插入记录
  • Merge语句需要终止分号。

限制:

  • WHEN MATCHED不允许INSERT操作
  • UPDATE操作只能更新一行一次。这意味着联接条件必须产生唯一匹配。

第16.2节:使用CTE源进行Merge

sql 复制代码
WITH SourceTableCTE AS (
    SELECT * FROM SourceTable
)
MERGE TargetTable AS target
USING SourceTableCTE AS source
ON (target.PKID = source.PKID)
WHEN MATCHED THEN
    UPDATE SET target.ColumnA = source.ColumnA
WHEN NOT MATCHED THEN
    INSERT (ColumnA) VALUES (Source.ColumnA);

第16.3节:Merge示例 - 同步源表和目标表

为了说明MERGE语句,考虑以下两个表

  • dbo.Product:此表包含有关公司当前销售的产品信息
  • dbo.ProductNew:此表包含有关公司将来将销售的产品信息

以下T-SQL将创建并填充这两个表

sql 复制代码
IF OBJECT_id(N'dbo.Product',N'U') IS NOT NULL 
    DROP TABLE dbo.Product
GO

CREATE TABLE dbo.Product (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(64),
    PRICE MONEY
)

IF OBJECT_id(N'dbo.ProductNew',N'U') IS NOT NULL 
    DROP TABLE dbo.ProductNew
GO

CREATE TABLE dbo.ProductNew (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(64),
    PRICE MONEY
)

INSERT INTO dbo.Product 
VALUES(1,'IPod',300),
      (2,'IPhone',400),
      (3,'ChromeCast',100),
      (4,'raspberry pi',50)

INSERT INTO dbo.ProductNew 
VALUES(1,'Asus Notebook',300),
      (2,'Hp Notebook',400),
      (3,'Dell Notebook',100),
      (4,'raspberry pi',50)

现在,假设我们要将dbo.Product目标表与dbo.ProductNew表同步。此任务的标准如下:

  1. 同时存在于dbo.ProductNew源表和dbo.Product目标表中的产品在dbo.Product目标表中更新为新值。
  2. dbo.ProductNew源表中存在但dob.Product目标表中不存在的任何产品都插入到dbo.Product目标表中。
  3. dbo.Product目标表中存在但dbo.ProductNew源表中不存在的任何产品必须从dbo.Product目标表中删除。

以下是执行此任务的MERGE语句。

sql 复制代码
MERGE dbo.Product AS SourceTbl
USING dbo.ProductNew AS TargetTbl
ON (SourceTbl.ProductID = TargetTbl.ProductID)
WHEN MATCHED AND SourceTbl.ProductName <> TargetTbl.ProductName 
              OR SourceTbl.Price <> TargetTbl.Price THEN
    UPDATE SET SourceTbl.ProductName = TargetTbl.ProductName,
               SourceTbl.Price = TargetTbl.Price
WHEN NOT MATCHED THEN
    INSERT (ProductID, ProductName, Price)
    VALUES (TargetTbl.ProductID, TargetTbl.ProductName, TargetTbl.Price)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE
OUTPUT $action, INSERTED.*, DELETED.*;

注意:MERGE语句末尾必须有分号。

第16.4节:使用派生源表进行MERGE

sql 复制代码
MERGE INTO TargetTable AS Target
USING (VALUES (1,'Value1'), (2, 'Value2'), (3,'Value3')) 
      AS Source (PKID, ColumnA)
ON Target.PKID = Source.PKID
WHEN MATCHED THEN
    UPDATE SET target.ColumnA = source.ColumnA
WHEN NOT MATCHED THEN
    INSERT (PKID, ColumnA) 
    VALUES (Source.PKID, Source.ColumnA);

第16.5节:使用EXCEPT进行Merge

使用EXCEPT防止更新未更改的记录

sql 复制代码
MERGE TargetTable targ
USING SourceTable AS src
ON src.id = targ.id
WHEN MATCHED AND EXISTS (
    SELECT src.field
    EXCEPT
    SELECT targ.field
) THEN
    UPDATE SET field = src.field
WHEN NOT MATCHED BY TARGET THEN
    INSERT (id, field)
    VALUES (src.id, src.field)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;
相关推荐
云烟成雨TD17 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
于慨17 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
swg32132117 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
gelald17 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川17 小时前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月18 小时前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming66618 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川18 小时前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java
eddieHoo18 小时前
查看 Tomcat 的堆内存参数
java·tomcat
那个失眠的夜18 小时前
Mybatis延迟加载策略
xml·java·数据库·maven·mybatis