使用带有事务的脚本文件自动更新

时间:2011-10-07 09:52:43

标签: sql sql-server-2008

我需要为我的应用程序提供自动更新功能。 我在应用SQL更新时遇到问题。我在.sql文件中有更新的SQL语句,我想要实现的是,如果一个语句失败,那么必须回滚整个脚本文件 防爆。

create procedure [dbo].[test1]        
@P1 varchar(200),        
@C1 int        
as        
begin 
Select 1
end

GO

Insert into test (name) values ('vv')

Go

alter procedure [dbo].[test2]        
@P1 varchar(200),        
@C1 int        
as        
begin 
Select 1
end

GO

现在在上面的例子中,如果我在“alter procedure [dbo]。[test2]”的第三个语句中得到错误,那么我想回滚前两个更改,即创建SP“test1”并插入数据进入“测试”表

我该如何处理这项任务?任何帮助将不胜感激。

如果您需要更多信息,请告诉我

1 个答案:

答案 0 :(得分:1)

通常,您希望在开头添加BEGIN TRAN,删除GO语句,然后使用{{1}处理ROLLBACK TRAN / COMMIT TRAN阻止。

在处理DML时,虽然通常有一些语句必须在批处理的开头,但是你不能将它们包装在TRY..CATCH块中。在这种情况下,您需要将一个知道如何回滚的系统组合在一起。

一个简单的系统只是在开始时备份数据库并在任何失败时恢复它(假设您是唯一一次访问数据库的人)。另一种方法是记录成功运行的每个批处理并拥有相应的回滚脚本,如果以后的批处理失败,您可以运行这些脚本以将所有内容放回原处。这显然需要更多的工作(为每个脚本写一个撤销脚本PLUS完全测试回滚),如果人们在升级过程中仍在访问数据库,也可能会出现问题。

修改 以下是带有事务处理的简单TRY..CATCH块的示例:

TRY..CATCH

然而,BEGIN TRY BEGIN TRANSACTION -- All of your code here, with `RAISERROR` used for any of your own error conditions COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION END CATCH 块不能跨越批次(也许这就是我在说交易时不能想到的),所以在你的情况下它可能更像是:

TRY..CATCH

不幸的是,由于IF (OBJECT_ID('dbo.Error_Happened') IS NOT NULL) DROP TABLE dbo.Error_Happened GO BEGIN TRANSACTION <Some line of code> IF (@@ERROR <> 0) CREATE TABLE dbo.Error_Happened (my_id INT) IF (OBJECT_ID('dbo.Error_Happened') IS NOT NULL) BEGIN <Another line of code> IF (@@ERROR <> 0) CREATE TABLE dbo.Error_Happened (my_id INT) END ... IF (OBJECT_ID('dbo.Error_Happened) IS NOT NULL) BEGIN ROLLBACK TRANSACTION DROP TABLE dbo.Error_Happened END ELSE COMMIT TRANSACTION 语句中的单独批次无法使用GO,因此您无法使用GOTO,并且无法将变量保留在批次。这就是为什么我使用创建表来表示错误的非常狡猾的技巧。

更好的方法是简单地使用错误表并查找其中的行。请注意,您的TRY..CATCH也会在结尾删除这些行。