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块。 –