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實現。
哪一個更好?爲什麼?如果你有更好的解決方案,請分享。
聽說過的[MERGE](https://msdn.microsoft.com/en-我們/庫/ bb510625.aspx)?如果不存在則插入,如果存在則更新。不需要所有的檢查。 – xQbert
@xQbert我也是'MERGE'的粉絲,仍然在使用它,但我認爲應該讓這篇文章知道。我發現它教育。 https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ – scsimon
正如其他人所說,使用合併,但絕對不使用第二個變種 - 你不應該使用這種邏輯的異常處理。你正在假設你爲什麼進入catch塊。 –