开发者

Create sql trigger dynamically and rollback if error

I'm creating a stored procedure that will create 3 triggers (insert, update, delete) given a table name.

Here is an example to illustrate the issue I'm experiencing :

CREATE PROCEDURE [dbo].[sp_test] 
AS
BEGIN

    BEGIN TRAN

    -- Creat开发者_C百科e 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

So I thought that wrapping the call in a transaction, the first trigger won't be created. Since the second will fail. BUT the first trigger is created anyway .... How can I prevent this from happening. I want the whole thing to be atomics.


Try this, with 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


You have no error handling or rollback statement in your procedure.


In some databases, DDL statements such as CREATE TRIGGER will automatically commit themselves; if sql-server is one of them, you can't. (This is true of Oracle and MySQL; not true of RDB; not sure about sql-server.)


You don't have a Rollback call on an error.

Using SQL Server's Try/Catch, you could do something like what Vidar mentioned, or you if Sql Server automatically commits triggers (as Brian H mentioned as a posibility) you could instead have in your Catch block:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜