1

あるデータベースに、別のデータベースのテーブルの ID を参照するテーブルがあります。挿入/更新の代わりにトリガーを設定して、他のテーブルに存在しない ID を挿入しないようにしました。これらのトリガーで、存在しない ID が見つかった場合はトランザクションを中止し、そうでない場合はトランザクションを続行します。

これが私が試したことです:

CREATE TRIGGER [dbo].[tr_check_student_insert]
    ON [dbo].[student]
    INSTEAD OF INSERT
AS
BEGIN
    SET XACT_ABORT ON

    IF (EXISTS ... )
    BEGIN
        RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
    END

    IF (EXISTS ... )
    BEGIN
        RAISERROR (N'[class_id] does not exist in [class]',11,1)
    END

    INSERT INTO [dbo].[student] ...
END

その後、SET XACT_ABORT ON を使用しても RAISERROR がトランザクションを中止せず、エラーが発生した後も挿入 (または更新) が発生することを発見しました。

各条件を IF/ELSE IF ステートメントでラップし、ELSE で挿入を呼び出すことができることはわかっていますが、代わりにトランザクション全体をすぐに終了してロールバックする方法があるかどうか疑問に思っています。

4

1 に答える 1

1

BEGIN TRANSACTIONとを使用ROLLBACKする必要がありますTRY CATCH

次のようなことを試してください:

CREATE TRIGGER [dbo].[tr_check_student_insert]
    ON [dbo].[student]
    INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;

    IF (EXISTS ... )
    BEGIN
        RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
    END

    IF (EXISTS ... )
    BEGIN
        RAISERROR (N'[class_id] does not exist in [class]',11,1)
    END

    INSERT INTO [dbo].[student] ...

;
COMMIT
END TRY

BEGIN CATCH

IF @@TRANCOUNT > 0
     ROLLBACK

    SELECT
        ERROR_NUMBER() AS ErrorNumber
        ,ERROR_SEVERITY() AS ErrorSeverity
        ,ERROR_STATE() AS ErrorState
        ,ERROR_PROCEDURE() AS ErrorProcedure
        ,ERROR_LINE() AS ErrorLine
        ,ERROR_MESSAGE() AS ErrorMessage;
       RETURN;
END CATCH

END
于 2015-03-04T17:09:27.307 に答える