使用 MERGE 语句实现增删改
Ø 简介
在平常编写增删改的 SQL 语句时,我们用的最多的就是 INSERT、UPDATE 和 DELETE 语句,这是最基本的增删改语句。其实,SQL Server 中还有另外一个可以实现增删改的语句,那就是本文将要介绍的 MERGE 语句。
1. 什么是 MERGE 语句
1) MERGE 语句可以在一条语句中,根据与源表联接的结果,对目标表执行插入、更新或删除操作。 例如,根据在另一个表中找到的差异在一个表中插入、更新或删除行,可以对两个表进行同步。
2) 为什么使用 MERGE 语句呢?
1. 试想一下,如果我们想要完成这件事情:将查询的结果集写入 A 表中,如果 A 表已经存在了该记录,就执行 UPDATE 语句(更新);否则,执行 INSERT 语句(新增)。(删除也是如此)
2. 如果按照我们的思路,是不是首先应该查出数据,在根据关键字段去 A 表中匹配,如果匹配到则执行 UPDATE 语句,否则执行 INSERT 语句。但是这样一来我们必须执行两次查询结果集:第一次查询比对,第二次查询后执行新增或更新操作,这样就相当繁琐也影响性能。
3. 而 MERGE 语句可以很轻松的帮我们解决这个问题,帮我们简洁了代码和优化性能。
2. 我的示例
1) 使用 MERGE语句完成新增或更新操作
INSERT INTO Sys_DbLog(LogTime, Type, Itme, Message, Remark) VALUES(GETDATE(), 'info', 'SP_Update_AchievCommission', '存储过程执行', NULL);
BEGIN TRY
WITH ce1(OrderNum, TotalMoney) AS
(
SELECT OrderNum, SUM(T2.TotalMoney) AS TotalMoney FROM Orders AS T1
INNER JOIN OrderDetail AS T2 ON(T1.Id = T2.OrderId)
WHERE 1=1
AND (T1.OrderStatusId > 1 AND T1.OrderStatusId < 10)
AND (T1.PayStatusId = 2 AND T1.PayTime >= @StartTime AND T1.PayTime <= @EndTime)
GROUP BY T1.OrderNum
) --订单明细的总实付金额
MERGE INTO Crm_AchievCommission AS T1
USING
(
SELECT T1.OrderNum, T1.PayTime, T1.CityId AS OrderCityId, T3.CityId AS CustCityId, T4.CityId AS EmplCityId, T4.EmployeeId, T5.ProductId,
CAST(ROUND((T1.RealTotal - ISNULL(T1.Freight, 0)) * (ISNULL(T5.TotalMoney, 0) / T7.TotalMoney), 2) AS numeric(19,2)) AS RealTotal/*四舍五入保留两位小数*/,
T6.CommissionRate, T6.ExtraCommissionRate FROM Orders AS T1
INNER JOIN UserInfo AS T2 ON(T1.UserId = T2.Id)
INNER JOIN Customer AS T3 ON(T2.CustomerId = T3.Id)
INNER JOIN Sys_EmployeeProfile AS T4 ON(T1.SalesUserId = T4.EmployeeId)
INNER JOIN OrderDetail AS T5 ON(T1.Id = T5.OrderId)
INNER JOIN Crm_CommissionRates AS T6 ON(T5.ProductId = T6.ProductId)
INNER JOIN ce1 AS T7 ON(T1.OrderNum = T7.OrderNum)
WHERE 1=1
AND T1.UserId > 0
AND T2.CustomerId > 0
AND T1.SalesUserId > 0
AND (T1.OrderStatusId > 1 AND T1.OrderStatusId < 10)
AND (T1.PayStatusId = 2 AND T1.PayTime >= @StartTime AND T1.PayTime <= @EndTime)
) AS T2 ON(T1.OrderNum = T2.OrderNum AND T1.ProductId = T2.ProductId)
WHEN MATCHED
THEN UPDATE SET
OrderCityId = T2.OrderCityId,
CustCityId = T2.CustCityId,
EmplCityId = T2.EmplCityId,
EmployeeId = T2.EmployeeId,
RealTotal = T2.RealTotal,
UpdateTime = GETDATE()
WHEN NOT MATCHED
THEN INSERT(OrderNum, PayTime, OrderCityId, CustCityId, EmplCityId, EmployeeId, ProductId, RealTotal, CommissionRate, ExtraCommissionRate, CreateTime, UpdateTime)
VALUES(T2.OrderNum, T2.PayTime, T2.OrderCityId, T2.CustCityId, T2.EmplCityId, T2.EmployeeId, T2.ProductId, T2.RealTotal, T2.CommissionRate, T2.ExtraCommissionRate, GETDATE(), NULL);
END TRY
BEGIN CATCH
DECLARE @Message nvarchar(4000) = '错误行号:' + CAST(ERROR_LINE() AS nvarchar(20)) + ',错误信息:' + ERROR_MESSAGE();
INSERT INTO Sys_DbLog(LogTime, Type, Itme, Message, Remark) VALUES(GETDATE(), 'error', 'SP_Update_AchievCommission', @Message, NULL);
END CATCH
3. 更多介绍
1) 官网介绍
https://docs.microsoft.com/zh-cn/sql/t-sql/statements/merge-transact-sql?view=sql-server-2017
2) 其他
https://www.cnblogs.com/billqian/p/5157052.html
使用 MERGE 语句实现增删改的更多相关文章
- 四种简单的sql语句(增删改查语句)
四种简单的sql语句(增删改查语句) 一.插入语句 insert into [table] ([column],[column],[column]) values(?,?,?) 二.删除语句 dele ...
- dml语句就是你常写的sql语句,增删改查
dml语句就是你常写的sql语句,增删改查
- 利用sql语句进行增删改查
1.查询 函数:raw(sql语句) 语法:Entry.objects.raw(sql) 返回:QuerySet 2.增删改 from django.db import connection def ...
- 常见 SQL语句使用 增删改查
一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...
- SQL简单语句(增删改查)
简单的SQL语句增删改查操作 说明: 在mysql里面亲测结果正确 用到的表(学生表:studnets) 1.创建一个学生表,(学号,姓名,性别,家庭住址) mysql> create t ...
- SQL语句简单增删改查
常用数据类型 Int:整数,长度没有作用 Varchar:字符串,varchar(3)表示最多存放3个字符,1个中文或英文或符合都占1个字符 Decimal:小数,decimal(5,2)表示共存5位 ...
- SQL SQL语句的增删改查
一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...
- SQL语句的增删改查
一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...
- SQL语句的增删改查(详细)--转载
转载源: http://blog.csdn.net/a88055517/article/details/6736284/ 一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [ ...
随机推荐
- hashlib模块
老师博客:http://www.cnblogs.com/Eva-J/articles/7228075.html#_label12 摘要算法 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个 ...
- 分治FFT的三种含义
分治FFT是几个算法的统称.它们之间并无关联. 分治多项式乘法 问题如求\(\prod_{i=1}^na_ix+b\). 若挨个乘复杂度为\(O(n^2\log n)\),可分治做这件事,复杂度为\( ...
- JS 设计模式一 -- 原型模式
原型模式 概念: 原型模式 是指原型实例指向创建对象的种类,并通过拷贝这些原型创建新的对象,是一种用来创建对象的模式,也就是创建一个对象作为另一个对象的prototype属性. 实现原型模式: 方法一 ...
- 阿里云 轻量应用服务器(LAMP) 使用日志记录
phpStudy(PHP运行环境一键安装包) https://www.jb51.net/softs/182860.html 0:PHP开发工具 https://netbeans.org/downloa ...
- 好坑吖,几乎GG,关于Nginx和supervisor的配置
从没想过部署个站点居然这么费劲.这还是搞了好多回且环境都具备的前提一下. 不过问题还是挺刁钻的,下面详细说一下. 1.net core编译少dll文件问题 发布到服务器上执行dotnet FileSe ...
- springboot使用多数据源以及配置
1. 首先在application中配置数据源地址 my.datasource.koi.type=com.alibaba.druid.pool.DruidDataSource my.datasourc ...
- 输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)
对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流: Ob ...
- Word Representations 词向量
常用的词向量方法word2vec. 一.Word2vec 1.参考资料: 1.1) 总览 https://zhuanlan.zhihu.com/p/26306795 1.2) 基础篇: 深度学习wo ...
- Centos7修改时区
设置时区同样, 在 CentOS 7 中, 引入了一个叫 timedatectl 的设置设置程序. 用法很简单: # timedatectl # 查看系统时间方面的各种状态 Local time: 四 ...
- 进程Process之join、daemon(守护)、terminate(关闭)、multiprocessing之锁、信号量和事件
一.Process 参数介绍: 1 group参数未使用,值始终为None 2 target表示调用对象,即子进程要执行的任务 3 args表示调用对象的位置参数元组,args=(1,2,'a',) ...