动态创建sql触发器并在出错时回滚

时间:2010-08-04 15:53:12

标签: sql sql-server

我正在创建一个存储过程,它将在给定表名的情况下创建3个触发器(插入,更新,删除)。

这是一个例子来说明我遇到的问题:

CREATE PROCEDURE [dbo].[sp_test] 
AS
BEGIN

    BEGIN TRAN

    -- Create trigger 1
    DECLARE @sql NVARCHAR(MAX) = 'CREATE TRIGGER test1 ON  TableXML AFTER INSERT AS BEGIN END'
    EXEC sp_executesql @sql

    -- Create trigger 2, but this one will fail because Table_1 contain an ntext field.
    SET @sql = 'CREATE TRIGGER test1 ON  Table_1 AFTER INSERT AS 
                BEGIN
                    select * from inserted
                END'
    EXEC sp_executesql @sql

    COMMIT TRAN

END

所以我认为在事务中包装调用,将不会创建第一个触发器。因为第二个会失败。但是无论如何都会创建第一个触发器....如何防止这种情况发生。我希望整个事情都是原子的。

4 个答案:

答案 0 :(得分:3)

尝试使用BEGIN TRY

CREATE PROCEDURE [dbo].[sp_test] 
AS
BEGIN

    BEGIN TRY
        BEGIN TRAN

        DECLARE @sql NVARCHAR(MAX) = 'CREATE TRIGGER test1 ON  TableXML AFTER INSERT AS BEGIN END'
        EXEC sp_executesql @sql

        SET @sql = 'CREATE TRIGGER test1 ON  Table_1 AFTER INSERT AS 
                    BEGIN
                        select * from inserted
                    END'
        EXEC sp_executesql @sql

        COMMIT TRAN
    END TRY
    BEGIN CATCH
        RAISERROR('Errormessage', 18, 1)
        ROLLBACK TRAN
    END CATCH

END

答案 1 :(得分:1)

您的程序中没有错误处理或回滚语句。

答案 2 :(得分:1)

在某些数据库中,诸如CREATE TRIGGER之类的DDL语句将自动提交;如果sql-server是其中之一,你就不能。 (Oracle和MySQL都是如此; RDB不是这样;不确定sql-server。)

答案 3 :(得分:1)

您没有对错误进行Rollback来电。

使用SQL Server的Try / Catch,您可以执行类似Vidar所提到的操作,或者如果Sql Server自动提交触发器(如Brian H提到的那样,您可以在Catch块中使用,则可以执行此操作:< / p>

BEGIN CATCH
   RAISERROR('Errormessage', 18, 1)
   DROP Trigger test1
END CATCH