web-dev-qa-db-ja.com

INSERTEDテーブルのROLLBACK makeデータはAFTER INSERT TRIGGERで削除されます

問題を示す例を挙げます。次のようにテーブルを作成します。

CREATE TABLE a
(
  id INT
)

AFTER INSERTトリガーを作成して、id = 1をテーブル "a"に挿入できないようにします

CREATE TRIGGER [dbo].[insert_a]
ON [dbo].[a] AFTER INSERT 
AS
BEGIN

DECLARE @id INT
SELECT @id=id FROM inserted
IF @id=1
 BEGIN
  RAISERROR('1',12,1)
  ROLLBACK;
 END
SELECT * FROM inserted
END

次に、id = 1をテーブル "a"に挿入します。

INSERT INTO a VALUES(1)

INSERTEDテーブルから何も取得されません。

次にロールバックすると、次のことがわかります。

  • テーブル "a"のデータはROLLBACKでした(知っています)

  • iNSERTEDテーブルのデータも削除されます。なぜですか?

トリガーでAFTER INSERTをINSTEAD OF INSERTに変更した場合。

ALTER TRIGGER [dbo].[insert_a]
ON [dbo].[a] INSTEAD OF INSERT 
AS
BEGIN

DECLARE @id INT
SELECT @id=id FROM inserted
IF @id=1
 BEGIN
  RAISERROR('1',12,1)
  ROLLBACK
 END

SELECT * FROM inserted
END

INSERT INTO a VALUES(1)

次に、結果を取得します。

id
1

つまり、INSERTEDテーブルのデータはROLLBACKされていても削除されません。

説明してくれませんか?

2
Dunguyen

どちらの場合も、行は挿入されていません。

ために after insertトリガーのロールバックはトランザクションの一部です。詳細については、このQ&Aを参照してください。

SQLサーバー-挿入後/挿入後-ロールバック

上記Q&Aより引用。

1つ(または複数)の行をテーブルに挿入しています。次に、まだトランザクション内で、AFTER INSERTトリガーが実行され、特定の条件をチェックします。通常、トリガー内で使用可能なInserted疑似テーブルを使用します。これには、挿入された行が含まれます。

トリガーでROLLBACK TRANSACTIONを呼び出すと、はい-トランザクションはすべての処理が行われた状態でロールバックされ、INSERTが発生しなかったかのように、データベーステーブルには何も表示されません。

ために instead of trigger表示されている1のid値は、テーブルのものではありません。これはトリガー内のコードからのものです。この1の値は、

SELECT * FROM inserted

このコードを実行すると、レコードは返されません。

ALTER TRIGGER [dbo].[insert_a]
ON [dbo].[a] INSTEAD OF INSERT 
AS
BEGIN

DECLARE @id INT
SELECT @id=id FROM inserted
IF @id=1
 BEGIN
  RAISERROR('1',12,1)
  ROLLBACK
 END

SELECT * FROM inserted
END
GO
INSERT INTO a VALUES(1);
GO
SELECT * FROM dbo.a;
GO
1
SqlWorldWide