zoukankan      html  css  js  c++  java
  • 使用 MERGE 语句实现增删改

    Ø  简介

    在平常编写增删改的 SQL 语句时,我们用的最多的就是 INSERTUPDATE 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

  • 相关阅读:
    gcc编译时头文件和库文件搜索路径
    vim 使用
    stdlib.h stdio.h
    sys/types.h fcntl.h unistd.h sys/stat.h
    gcc 使用
    grep 正则表达式
    firefox
    CentOS7 屏幕亮度的命令行管理
    linuxqq
    rpm 与 yum 源
  • 原文地址:https://www.cnblogs.com/abeam/p/9556080.html
Copyright © 2011-2022 走看看