take the following table (a very simplified example):
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
)
I have a proc that controls insertions into this table, but at one point you come to the infamous "UPSERT" scenario.
Let's assume my procedure has the following vars:
@OrderID INT ,
@StockCode VARCHAR(20) ,
@Quantity SMALLINT
I currently do as follows:
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
My intention is to do away with this old method and use the MERGE
statement - however i'm struggling to get my head round the MERGE
statement, this is what i have so far:
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
);
My Question(s):
MERGE
seems to work - yet it looks VERY messy and confusing - is there a better way of writing this? MERGE
statement to DELETE
matching rows (based on OrderID
& StockCode
) if @Quantity = 0
You could tighten up the last part by using the special $action
keyword.
Case $action
When 'INSERT' Then 'OK_ADDED'
When 'UPDATE' Then 'OK_UPDATED'
When 'DELETE' Then 'OK_REMOVED'
End
$action
Is available only for the MERGE statement. Specifies a column of type nvarchar(10) in the OUTPUT clause in a MERGE statement that returns one of three values for each row: 'INSERT', 'UPDATE', or 'DELETE', according to the action that was performed on that row.
OK, this is what i came up with:
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 );
Would still love to know if there is a tider way of writing this!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.