`
zzc1684
  • 浏览: 1190161 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Using MERGE in SQL Server to insert, update and delete at the same time

阅读更多

Problem
In a typical data warehousing application, quite often during the ETL cycle you need to perform INSERT, UPDATE and DELETE operations on a TARGET table by matching the records from the SOURCE table. For example, a products dimension table has information about the products; you need to sync-up this table with the latest information about the products from the source table. You would need to write separate INSERT, UPDATE and DELETE statements to refresh the target table with an updated product list or do lookups. Though it seems to be straight forward at first glance, but it becomes cumbersome when you have do it very often or on multiple tables, even the performance degrades significantly with this approach.  In this tip we will walk through how to use the MERGE statement and do this in one pass.

Solution
Beginning with SQL Server 2008, now you can use MERGE SQL command to perform these operations in a single statement. This new command is similar to the UPSERT (fusion of the words UPDATE and INSERT.) command of Oracle; it inserts rows that don't exist and updates the rows that do exist. With the introduction of the MERGE SQL command, developers can more effectively handle common data warehousing scenarios, like checking whether a row exists, and then executing an insert or update or delete.

The MERGE statement basically merges data from a source result set to a target table based on a condition that you specify and if the data from the source already exists in the target or not. The new SQL command combines the sequence of conditional INSERT, UPDATE and DELETE commands in a single atomic statement, depending on the existence of a record. The new MERGE SQL command looks like as below:

 

MERGE <target_table> [AS TARGET]
USING <table_source> [AS SOURCE]
ON <search_condition>
[WHEN MATCHED 
THEN <merge_matched> ]
[WHEN NOT MATCHED [BY TARGET]
THEN <merge_not_matched> ]
[WHEN NOT MATCHED BY SOURCE
THEN <merge_ matched> ];

 

The MERGE statement basically works as separate insert, update, and delete statements all within the same statement. You specify a "Source" record set and a "Target" table, and the join between the two. You then specify the type of data modification that is to occur when the records between the two data are matched or are not matched. MERGE is very useful, especially when it comes to loading data warehouse tables, which can be very large and require specific actions to be taken when rows are or are not present.

 

Putting it all together

 

In this example I will take a Products table as target table and UpdatedProducts as a source table containing updated list of products. I will then use the MERGE SQL command to synchronize the target table with the source table.

 

  • First Let's create a target table and a source table and populate some data to these tables.

 

MERGE SQL statement - Part 1

--Create a target table
CREATE TABLE Products
(
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Rate MONEY
) 
GO
--Insert records into target table
INSERT INTO Products
VALUES
(1, 'Tea', 10.00),
(2, 'Coffee', 20.00),
(3, 'Muffin', 30.00),
(4, 'Biscuit', 40.00)
GO
--Create source table
CREATE TABLE UpdatedProducts
(
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Rate MONEY
) 
GO
--Insert records into source table
INSERT INTO UpdatedProducts
VALUES
(1, 'Tea', 10.00),
(2, 'Coffee', 25.00),
(3, 'Muffin', 35.00),
(5, 'Pizza', 60.00)
GO
SELECT * FROM Products
SELECT * FROM UpdatedProducts
GO

 

  • Next I will use the MERGE SQL command to synchronize the target table with the refreshed data coming from the source table.

 

MERGE SQL statement - Part 2

--Synchronize the target table with
--refreshed data from source table
MERGE Products AS TARGET
USING UpdatedProducts AS SOURCE 
ON (TARGET.ProductID = SOURCE.ProductID) 
--When records are matched, update 
--the records if there is any change
WHEN MATCHED AND TARGET.ProductName <> SOURCE.ProductName 
OR TARGET.Rate <> SOURCE.Rate THEN 
UPDATE SET TARGET.ProductName = SOURCE.ProductName, 
TARGET.Rate = SOURCE.Rate 
--When no records are matched, insert
--the incoming records from source
--table to target table
WHEN NOT MATCHED BY TARGET THEN 
INSERT (ProductID, ProductName, Rate) 
VALUES (SOURCE.ProductID, SOURCE.ProductName, SOURCE.Rate)
--When there is a row that exists in target table and
--same record does not exist in source table
--then delete this record from target table
WHEN NOT MATCHED BY SOURCE THEN 
DELETE
--$action specifies a column of type nvarchar(10) 
--in the OUTPUT clause that returns one of three 
--values for each row: 'INSERT', 'UPDATE', or 'DELETE', 
--according to the action that was performed on that row
OUTPUT $action, 
DELETED.ProductID AS TargetProductID, 
DELETED.ProductName AS TargetProductName, 
DELETED.Rate AS TargetRate, 
INSERTED.ProductID AS SourceProductID, 
INSERTED.ProductName AS SourceProductName, 
INSERTED.Rate AS SourceRate; 
SELECT @@ROWCOUNT;
GO

 

When the above is run this is the output.  There were 2 updates, 1 delete and 1 insert.

 

 

If we select all records from the Products table we can see the final results.  We can see the Coffee rate was updated from 20.00 to 25.00, the Muffin rate was updated from 30.00 to 35.00, Biscuit was deleted and Pizza was inserted.

 

 

Notes

 

  • The MERGE SQL statement requires a semicolon (;) as a statement terminator. Otherwise Error 10713 is raised when a MERGE statement is executed without the statement terminator.
  • When used after MERGE, @@ROWCOUNT returns the total number of rows inserted, updated, and deleted to the client.
  • At least one of the three MATCHED clauses must be specified when using MERGE statement; the MATCHED clauses can be specified in any order. However a variable cannot be updated more than once in the same MATCHED clause.
  • Of course it's obvious, but just to mention, the person executing the MERGE statement should have SELECT Permission on the SOURCE Table and INSERT, UPDATE and DELETE Permission on the TARGET Table.
  • MERGE SQL statement improves the performance as all the data is read and processed only once whereas in previous versions three different statements have to be written to process three different activities (INSERT, UPDATE or DELETE) in which case the data in both the source and target tables are evaluated and processed multiple times; at least once for each statement.
  • MERGE SQL statement takes same kind of locks minus one Intent Shared (IS) Lock that was due to the select statement in the ‘IF EXISTS' as we did in previous version of SQL Server.
  • For every insert, update, or delete action specified in the MERGE statement, SQL Server fires any corresponding AFTER triggers defined on the target table, but does not guarantee on which action to fire triggers first or last. Triggers defined for the same action honor the order you specify.

 

Next Steps

 



Last Update: 3/10/2009


About the author
MSSQLTips author Arshad Ali
Arshad Ali is a SQL and BI Developer focusing on Data Warehousing projects for Microsoft.

View all my tips



print tip Print   inShare4     Become a paid author




Recommended For You

 









 

Learn more about SQL Server tools

 

Comments and Feedback:

 

Tuesday, March 10, 2009 - 10:54:55 AM - jcelko Read The Tip

Very nice job!  The only thing I would add is an example with more predicates in the WHEN clause -- 

WHEN MATCHED AND SOURCE. foobar > TARGET.foobar THEN ..

WHEN MATCHED AND SOURCE. foobar <= TARGET.foobar THEN ..

You can get a lot of power in one statement and avoid procedural coding.  

 

 

Wednesday, March 11, 2009 - 1:33:23 PM - arshad0384 Read The Tip

First of all thanks for your appreciation and thanks again for addition, this will help the readers.

 

Tuesday, September 28, 2010 - 1:46:27 PM - kv Read The Tip
How do we use the merge function when the source and target are on different databases?

 

Thursday, March 10, 2011 - 5:09:03 PM - Don Read The Tip

Best example and explanation of a multi-matched/not matched merge I have encountered. Well Done!

 

Friday, May 04, 2012 - 3:52:15 PM - joseph Jelasker Read The Tip

 

Sorry Please avoid the previous request becaust it has some typo mistakes..Please consider this.

i have  to have 3 insert statements ,to Target Table,  inside  "Not MATCHED BLOCK" .I can't do bulk insert because the subsequence insert has to take the previously inserted Identity Column(basically primary key).. i fail to do that.can you pls provide me the solution..

 

Thanks in Advance,Joseph S. Jelaskar

 

Monday, May 14, 2012 - 5:59:56 PM - George Quiroga Read The Tip

Will the MERGE work if the target table is not identical to the source table? For instance my target table only has a subset of the columns that are in the source table and it is those columns that I want updated. The columns are named the same in both tables but they are in different positions since the source table has many more columns than the destination table.

Thanks,

GQ

 

Friday, May 25, 2012 - 10:49:28 AM - Chandrashekar Venkatraman Read The Tip

Very Good Post. Am going to use this for a project of mine.

 

Wednesday, May 30, 2012 - 6:14:47 AM - sylvia moestl vasilik Read The Tip

Good solid sample code that I'll use again - especially like the output of the different actions (insert, delete, update) which I didn't realize you could do.

 

Thursday, June 21, 2012 - 6:27:16 AM - vinod Read The Tip

Nice one....

Thank you:)

 

Monday, July 30, 2012 - 10:11:20 PM - Vishal Read The Tip

Good 1 !!

 

Sunday, August 05, 2012 - 9:30:37 PM - SSMS Read The Tip

Can we use merge for tables from 2 different databases, for example the source table is from staging database and the targer table is in live database?

 

Friday, August 10, 2012 - 8:38:41 AM - Carrie Chung Read The Tip

Good and clear example to explain the concept.

 

Monday, August 13, 2012 - 2:11:51 AM - Arshad Read The Tip

Thanks Carrie Chung for your appreciation!

 

Friday, August 24, 2012 - 12:36:58 PM - Leo Korogodski Read The Tip

What if you don't have a source table? I want to insert a single row (id, value1, value2, value3, ...) if the id doesn't match or update the existing row if the id does match. Do I really have to create a one-row temporary table for this?

 

Wednesday, November 14, 2012 - 1:26:58 AM - Achilles Read The Tip

Thanks, solved my issue

 

Wednesday, August 07, 2013 - 12:54:52 PM - Abraham Babu Read The Tip

I do have a Update Trigger in a table. Update Trigger works fine when separate Update statement is fired. However, when MERGE statement issues a UPDATE command, the trigger is not invoked. Is there any precaution i need to make here?

Regards,

Abraham Babu

 

Thursday, September 12, 2013 - 1:06:39 PM - John Read The Tip

I do have one question regarding the MERGE command.  Can it handle an update and then an insert.  For example, if there is a match between the Target and Source then I want one field in the Target updated and then the Source record added.  How would this be done in the MERGE command?  Since SQL keeps giving the error that it does not allow INSERTS on MATCHES.

Regards,

John

 

Thursday, September 12, 2013 - 2:29:11 PM - Arshad Ali Read The Tip

Yes John, I think you are right you can use either UPDATE or INSERT at one time. But that does not mean you cannot achieve what you want to. There is a trick for this.

Here is a tip which takes similar approach for managing slowly changing dimension. (it updates the matching target record and then insert the matched source record into target table along with the new records).

http://www.mssqltips.com/sqlservertip/2883/using-the-sql-server-merge-statement-to-process-type-2-slowly-changing-dimensions/

Please let me know if you face any issue.

 

 

 

Monday, October 07, 2013 - 11:08:18 AM - Joan Read The Tip

Thanks for this useful post.

 

Tuesday, December 03, 2013 - 12:57:07 PM - Sean Ed Read The Tip

Thanks for the script!  It helped me design my import.

 

One thind I'd recommend adding for indexes is an IS NOT NULL statement for the inserts.  Even if there isn't a null, I saw an instance where the script was stopped with an error without the statement.

 

 

 

Tuesday, April 08, 2014 - 10:15:48 AM - Erhan Read The Tip

Very useful, thank you!

 

分享到:
评论

相关推荐

    实验-三、数据库安全性(目的、要求和模板).doc

    实验-三、数据库安全性(目的、要求和模板).doc

    基于Docker搭建K8s集群离线包

    基于Docker搭建K8s集群离线包,包含部署时所需的全部文件,可在内网环境中使用,K8s为1.23.0版本,docker为20.10.9-3版本

    基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip

    基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行!基于springboot+vue实现的求

    基于Android系统Api封装常用工具类.zip

    基于Android系统Api封装常用工具类.zip

    基于PCA和SVM的人脸识别

    svm 基于PCA(主成分分析)和SVM(支持向量机)的人脸识别是一种常见的方法。这里是一个简要说明: PCA(主成分分析): PCA是一种降维技术,它通过线性变换将高维数据转换为低维数据,同时保留最大的数据方差。 在人脸识别中,PCA被用来提取人脸图像中的主要特征,从而减少数据的维度,并保留最重要的信息。 SVM(支持向量机): SVM是一种监督学习算法,用于分类和回归分析。 在人脸识别中,SVM被用来构建一个分类器,以将提取的人脸特征映射到相应的人脸身份标签。 基于PCA和SVM的人脸识别流程: 训练阶段: 收集训练数据集,包括多个人的人脸图像和相应的标签。 对每个人脸图像应用PCA,将其转换为低维特征向量。 使用这些特征向量训练一个SVM分类器,使其能够将人脸特征向量与相应的人脸标签关联起来。 测试阶段: 对待识别的人脸图像应用相同的PCA转换,将其转换为与训练数据相同的低维特征向量。 使用训练好的SVM分类器,将待识别的人脸特征向量与已知的人脸标签进行比较,从而确定其身份。 优点: PCA可以有效地降低数据的维度,减少计算复杂度,并提取最相关的特征。 SVM在处理

    天津科技大学-答辩通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    Java SE Development Kit 11.0.23 macOS x64 DMG Installer

    Java SE Development Kit 11.0.23 macOS x64 DMG Installer

    课设&大作业-SSM毕业设计项目.zip

    【资源说明】【毕业设计】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。 2、适用人群:主要针对计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、数学、电子信息等)的同学或企业员工下载使用,具有较高的学习借鉴价值。 3、不仅适合小白学习实战练习,也可作为大作业、课程设计、毕设项目、初期项目立项演示等,欢迎下载,互相学习,共同进步!

    studyopencv2

    studyopencv2

    实验五-使用matlab实现卷积的运算.pdf

    实验五-使用matlab实现卷积的运算.pdf

    2024年中国纸杯蛋糕盒行业研究报告.docx

    2024年中国纸杯蛋糕盒行业研究报告

    总结作图常用的操作 Python数据分析及可视化-Matplotlib极简入门.zip

    matplotlib绘图 通过 Matplotlib,开发者可以仅需要几行代码,便可以生成绘图、直方图、功率谱、条形图、错误图、散点图等。 Matplotlib基础知识 1.Matplotlib中的基本图表包括的元素 x轴和y轴 水平和垂直的轴线 x轴和y轴刻度 刻度标示坐标轴的分隔,包括最小刻度和最大刻度 x轴和y轴刻度标签 表示特定坐标轴的值 绘图区域 实际绘图的区域 2.hold属性 hold属性默认为True,允许在一幅图中绘制多个曲线;将hold属性修改为False,每一个plot都会覆盖前面的plot。 但是不推荐去动hold这个属性,这种做法(会有警告)。因此使用默认设置即可。 3.网格线 grid方法 使用grid方法为图添加网格线 设置grid参数(参数与plot函数相同) .lw代表linewidth,线的粗细 .alpha表示线的明暗程度 4.axis方法 如果axis方法没有任何参数,则返回当前坐标轴的上下限 5.xlim方法和ylim方法 除了plt.axis方法,还可以通过xlim,ylim方法设置坐标轴范围

    java本科毕业设计基于RFID技术的国有资产管理系统源码后台项目.zip

    高分设计源码,详情请查看资源内容中使用说明 高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明

    springboot部署系统(自动化部署+缓存管理+业务降级+应用监控).zip

    springboot框架 一、Spring Boot基础应用 Spring Boot特征 概念: 约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中。 2,使编码变得简单,SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率,比如@Configuration和@bean注解结合,基于@Configuration完成类扫描,基于@bean注解把返回值注入IOC容器。 3.自动配置:SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们。 4.使部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow.我们只需要一个Java的运行环境就可以跑SpringBoot的项目了

    CUDA规约求和.cu

    CUDA规约求和.cu

    工程有限公司计算机信息系统数据信息安全管理办法.doc

    工程有限公司计算机信息系统数据信息安全管理办法.doc

    小学教育信息化工作计划.doc

    小学教育信息化工作计划.doc

    springboot停车位管理源码.rar

    springboot停车位管理源码.rarspringboot停车位管理源码.rarspringboot停车位管理源码.rar

    实验七-管道通信.doc

    实验七-管道通信.doc

    基于YOLOv5行人车辆跟踪检测识别计数系统源码.zip

    YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

Global site tag (gtag.js) - Google Analytics