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の実装が必要になるためです。
どちらが優れているのですか?より良い解決策があれば、共有してください。
エヴァー[MERGE](https://msdn.microsoft.com/en-を聞きますus/library/bb510625.aspx)?存在しない場合は挿入し、存在する場合は更新する。すべてのチェックの必要はありません。 – xQbert
@xQbert私は 'MERGE 'のファンでもありますが、私はこの記事を知っておくべきだと思います。私はそれが教育的だと分かった。 https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ – scsimon
他の人は言っているように、マージを使用しますが、間違いなく2番目のバリアントは使用しないでください。この種のロジックに対して例外処理を使用します。あなたはcatchブロックに入った理由を前提にしています。 –