我正在创建一个存储过程,它将在给定表名的情况下创建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
所以我认为在事务中包装调用,将不会创建第一个触发器。因为第二个会失败。但是无论如何都会创建第一个触发器....如何防止这种情况发生。我希望整个事情都是原子的。
答案 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