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;
相关推荐
Andy Dennis2 小时前
一文漫谈设计模式之创建型模式(一)
java·开发语言·设计模式
belldeep2 小时前
Java:Tomcat 9 和 mermaid.min.js 10.9 上传.csv文件实现 Markdown 中 Mermaid 图表的渲染
java·tomcat·mermaid·去除flexmark
sg_knight2 小时前
如何通过 SQL*Plus 连接 Oracle 数据库(使用 Instant Client)
运维·数据库·sql·oracle·database·关系型数据库·sql puls
AutumnorLiuu2 小时前
C++并发编程学习(二)—— 线程所有权和管控
java·c++·学习
Demon_Hao2 小时前
JAVA缓存的使用RedisCache、LocalCache、复合缓存
java·开发语言·缓存
踏雪羽翼2 小时前
android 解决混淆导致AGPBI: {“kind“:“error“,“text“:“Type a.a is defined multiple times
android·java·开发语言·混淆·混淆打包出现a.a
lang201509282 小时前
Tomcat Maven插件:部署与卸载的架构设计
java·tomcat·maven
serve the people2 小时前
python环境搭建 (六) Makefile 简单使用方法
java·服务器·python
不剪发的Tony老师2 小时前
Chartbrew:一个开源的数据可视化平台
sql·数据分析·可视化