2016-11-22 98 views
0

我有一種情況需要使用不是插入觸發器。我的同事和我想知道哪一個更有效(內存使用率,運行時間等)。MSSQL有效觸發器INSTEAD OF INSERT

觸發器檢查記錄是否存在於表中,如果沒有插入新行,則使用其鍵更新現有行。本例中的主鍵是(DocumentId,VatRate)的組合鍵。

第一種變體與檢查記錄是否已經存在:

CREATE TRIGGER docvatsum_trg 
ON DocumentVatSummary 
INSTEAD OF INSERT 
AS 
BEGIN 
     IF EXISTS (
     SELECT 1 FROM DocumentVatSummary a 
     JOIN inserted b ON (a.DocumentId = b.DocumentId AND a.VatRate = b.VatRate) 
    ) 
     BEGIN 
     UPDATE DocumentVatSummary 
     SET 
      DocumentVatSummary.VatBase = i.VatBase, 
      DocumentVatSummary.VatTotal = i.VatTotal 
     FROM inserted i 
     WHERE 
      DocumentVatSummary.DocumentId = i.DocumentId AND 
      DocumentVatSummary.VatRate = i.VatRate 
     END 
     ELSE 
     BEGIN 
     INSERT INTO DocumentVatSummary 
     SELECT * FROM inserted 
     END 
END; 

第二個變量試圖插入,如果插入失敗的更新如下:

CREATE TRIGGER docvatsum_trg 
ON DocumentVatSummary 
INSTEAD OF INSERT 
AS 
BEGIN 
    SAVE TRANSACTION savepoint 
    BEGIN TRY 
     INSERT INTO DocumentVatSummary 
     SELECT * FROM inserted 
    END TRY 
    BEGIN CATCH 
     IF XACT_STATE() = 1 
     BEGIN 
      ROLLBACK TRAN savepoint 

      UPDATE DocumentVatSummary 
      SET 
       DocumentVatSummary.VatBase = i.VatBase, 
       DocumentVatSummary.VatTotal = i.VatTotal 
      FROM inserted i 
      WHERE 
       DocumentVatSummary.DocumentId = i.DocumentId AND 
       DocumentVatSummary.VatRate = i.VatRate 
     END 
    END CATCH 
END; 

注:回滾到保存點是因爲在TSQL中運行事務的TRY-CATCH實現。

哪一個更好?爲什麼?如果你有更好的解決方案,請分享。

+3

聽說過的[MERGE](https://msdn.microsoft.com/en-我們/庫/ bb510625.aspx)?如果不存在則插入,如果存在則更新。不需要所有的檢查。 – xQbert

+0

@xQbert我也是'MERGE'的粉絲,仍然在使用它,但我認爲應該讓這篇文章知道。我發現它教育。 https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ – scsimon

+0

正如其他人所說,使用合併,但絕對不使用第二個變種 - 你不應該使用這種邏輯的異常處理。你正在假設你爲什麼進入catch塊。 –

回答

1

使用您的觸發MERGE如下解釋:

MERGE SYNTAX

代碼示例:

DECLARE @SummaryOfChanges TABLE(Change VARCHAR(20)); 

MERGE INTO Sales.SalesReason AS Target 
USING (VALUES ('Recommendation','Other'), 
       ('Review', 'Marketing'), 
       ('Internet', 'Promotion')) 
     AS Source (NewName, NewReasonType) 
ON Target.Name = Source.NewName 
WHEN MATCHED THEN 
UPDATE SET ReasonType = Source.NewReasonType 
WHEN NOT MATCHED BY TARGET THEN 
INSERT (Name, ReasonType) VALUES (NewName, NewReasonType) 
OUTPUT $action INTO @SummaryOfChanges; 
相關問題