SQL Server不会将触发器事务回滚到保存点

时间:2019-03-13 00:17:23

标签: sql sql-server tsql triggers transactions

我在尝试根据自己的观点触发交易时遇到问题。这是我的DDL设置:

CREATE TABLE entity1 (
    id INT NOT NULL IDENTITY PRIMARY KEY,
    attr1 INT NOT NULL,
    attr2 INT NOT NULL
);
GO

CREATE TABLE entity2 (
    entity1_id INT NOT NULL FOREIGN KEY REFERENCES entity1(id),
    attr3 INT NOT NULL,
    attr4 INT NOT NULL
);
GO

CREATE VIEW my_view AS
SELECT attr1, attr2, attr3, attr4
FROM entity1 AS e1 
INNER JOIN entity2 AS e2 
ON e1.id = e2.entity1_id;
GO

CREATE TRIGGER tg_my_view_ins ON my_view
INSTEAD OF INSERT AS
BEGIN
    BEGIN TRY
        SAVE TRANSACTION here; -- checkpoint
        INSERT INTO entity1 (attr1, attr2) 
        SELECT attr1, attr2 FROM inserted;
        INSERT INTO entity2 (entity1_id, attr3, attr4) 
        SELECT SCOPE_IDENTITY(), attr3, attr4 FROM inserted;
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION here; -- rollback to checkpoint in case on an error
    END CATCH
END
GO

如您所见,我在触发器中创建了一个保存点,并在出现任何错误的情况下进行了回滚(我假设约束错误也由TRY / CATCH块处理)。 问题是,当我在事务中执行错误的插入操作时,触发器错误处理块不会回滚:

BEGIN TRY
    BEGIN TRANSACTION;

        -- successful insert
        INSERT INTO my_view (attr1, attr2, attr3, attr4) VALUES (1,2,3,4);
        SELECT * FROM entity1; -- one entity

        -- i wrap the bad insert into try/catch so the error is discarded, 
        -- but still rolled back
        BEGIN TRY
            INSERT INTO my_view (attr1, attr2, attr3) VALUES (3,2,1);
        END TRY
        BEGIN CATCH
        END CATCH;

        SELECT * FROM entity1; -- should only have one entity, but has two
    ROLLBACK; -- discard the whole transaction
END TRY
BEGIN CATCH
    ROLLBACK; -- discard the whole transaction in case of any errors
END CATCH;

result output

我似乎无法以发生错误时不会创建孤立记录的方式来设置触发器。我尝试在触发器中使用BEGIN TRANSACTION hereCOMMIT TRANSACTION here而不是SAVE TRANSACTION here,但是没有运气。处理触发器内约束错误的正确方法是什么?

如果可能的话,我想保持执行设置的状态。我创建并回滚事务以进行测试。我将错误的插入文件包装到try / catch块中,以丢弃我知道应该发生的错误。

0 个答案:

没有答案