2016-11-22 7 views
0

代わりに挿入トリガーを使用する必要があります。私の同僚と私はどちらがより効果的か(メモリ使用量、実行時間など)不思議です。MSSQLの有効トリガー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-を聞きますus/library/bb510625.aspx)?存在しない場合は挿入し、存在する場合は更新する。すべてのチェックの必要はありません。 – xQbert

+0

@xQbert私は 'MERGE 'のファンでもありますが、私はこの記事を知っておくべきだと思います。私はそれが教育的だと分かった。 https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ – scsimon

+0

他の人は言っているように、マージを使用しますが、間違いなく2番目のバリアントは使用しないでください。この種のロジックに対して例外処理を使用します。あなたは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; 
関連する問題