将SQL MERGE与vars而不是表一起使用

时间:2013-05-30 11:53:53

标签: sql sql-server sql-server-2008 tsql sql-server-2008-r2

采取下表(一个非常简单的例子):

CREATE TABLE [dbo].[tbl_Order_Lines] (
    [LineID] [int] IDENTITY(1, 1) NOT NULL ,
    [OrderID] [int] NOT NULL ,
    [StockCode] [varchar](20) NOT NULL ,
    [Quantity] [smallint] NOT NULL
)

我有一个proc来控制插入到这个表中,但有一次你来到臭名昭着的“UPSERT”场景。

我们假设我的程序有以下变量:

@OrderID INT ,
@StockCode VARCHAR(20) ,
@Quantity SMALLINT

我目前做的如下:

IF ( NOT EXISTS ( SELECT    *
                  FROM      [dbo].[tbl_Order_Lines]
                  WHERE     [OrderID] = @OrderID
                            AND [StockCode] = @StockCode )
   ) 
    INSERT  INTO [dbo].[tbl_Order_Lines]
            ( [OrderID] ,
              [StockCode] ,
              [Quantity] 
            )
    VALUES  ( @OrderID ,
              @StockCode ,
              @Quantity 
            ) 
ELSE 
    UPDATE  [dbo].[tbl_Order_Lines]
    SET     Quantity = @Quantity
    WHERE   [OrderID] = @OrderID
            AND [StockCode] = @StockCode

我的意图是废除这个旧方法并使用MERGE语句 - 但是我正在努力绕过MERGE语句,这是我到目前为止所做的:< / p>

MERGE dbo.tbl_Order_Lines
    USING ( 
    VALUES
        ( @Quantity
        ) ) AS Source ( Quantity )
    ON dbo.tbl_Order_Lines.OrderID = @OrderID AND StockCode = @StockCode
    WHEN MATCHED THEN
        UPDATE SET Quantity = source.Quantity
    WHEN NOT MATCHED THEN
        INSERT  (
                  OrderID ,
                  StockCode ,
                  Quantity 
                )        VALUES
                ( @OrderID ,
                  @StockCode ,
                  Source.Quantity 
                );

我的问题:

  1. 我对此MERGE的尝试似乎有效 - 但它看起来非常混乱和令人困惑 - 是否有更好的方式来写这个?
  2. 如何将此MERGE语句修改为DELETE个匹配行(基于OrderID&amp; StockCodeif @Quantity = 0

2 个答案:

答案 0 :(得分:1)

您可以使用特殊的$action关键字来收紧最后一部分。

Case $action 
    When 'INSERT' Then 'OK_ADDED'
    When 'UPDATE' Then 'OK_UPDATED'
    When 'DELETE' Then 'OK_REMOVED'
End
  

$动作

     

仅适用于MERGE语句。在MERGE语句的OUTPUT子句中指定nvarchar(10)类型的列,该列返回每行的三个值之一:'INSERT','UPDATE'或'DELETE',根据对该行执行的操作

Output Clause

答案 1 :(得分:0)

好的,这就是我提出的:

MERGE dbo.tbl_Order_Lines
    USING ( VALUES ( @Quantity ) ) AS Source ( Quantity )
    ON dbo.tbl_Order_Lines.OrderID = @OrderID AND StockCode = @StockCode
    WHEN MATCHED AND @Quantity > 0 THEN
        UPDATE SET Quantity = source.Quantity
    WHEN MATCHED AND @Quantity <= 0 THEN
        DELETE
    WHEN NOT MATCHED AND @Quantity > 0 THEN
        INSERT  (
                  OrderID ,
                  StockCode ,
                  Quantity 
                )
            VALUES
                ( @OrderID ,
                  @StockCode ,
                  Source.Quantity 
                )
    OUTPUT
        COALESCE(Inserted.LineID, Deleted.LineID) AS ResultID ,
        CASE WHEN Deleted.LineID IS NULL
                  AND Inserted.LineID IS NOT NULL THEN 'OK_ADDED'
             WHEN Deleted.LineID IS NOT NULL
                  AND Inserted.LineID IS NOT NULL THEN 'OK_UPDATED'
             WHEN Deleted.LineID IS NOT NULL
                  AND Inserted.LineID IS NULL THEN 'OK_REMOVED'
        END AS ResultDesc
        INTO @tbl_LineChanges ( ResultID, ResultDesc );

仍然很想知道是否有一种写作方式!#/ p>