2011-10-07 42 views
1

我需要为我的应用程序提供自动更新功能。 我在应用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 

现在在上面的例子,如果我得到的第三条语句错误“修改程序[DBO]。[TEST2]”那我要回滚前两个变化,也即创建的“测试1 SP “并将数据插入”测试“表

我应该如何处理此任务?任何帮助都感激不尽。

如果您需要任何更多的信息,然后让我知道

回答

1

通常情况下,你会想在开始添加BEGIN TRAN,取出GO语句,然后处理ROLLBACK TRAN/COMMIT TRANTRY..CATCH块。

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

一个简单的系统就是在启动时备份数据库,如果有任何失败(假设您是唯一一个访问数据库的人)。另一种方法是记录每个成功运行的批处理,并具有相应的回滚脚本,以便在以后的批处理失败时运行该脚本以将所有内容都回收。这显然需要更多的工作(为每个脚本PLUS编写一个撤消脚本,充分测试回滚),并且如果在升级过程中人们仍然访问数据库,也可能会出现问题。

编辑: 这里有一个简单的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块不能跨批次(也许这就是我说的交易couldn”我在想什么的吨),所以在你的情况下,它可能会更类似于:

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 

不幸的是,由于单独的批次从t他GO陈述你不能使用GOTO,你不能使用TRY..CATCH,你不能持续跨越批次的变量。这就是为什么我使用创建表来表示错误的非常简单的技巧。

一个更好的方法是简单地有一个错误表,并在其中寻找行。请记住,您的ROLLBACK也会在最后删除这些行。

+0

交易可以跨越批次。 –

+0

呵呵。不知道为什么我认为他们不能。感谢您指出了这一点。我已经删除了我的答案的一部分。我认为其余的依然是相关的。 –

+0

感谢您的建议。 我的数据库是一种巨大的,所以我不会更喜欢备份/恢复。第二种方法对于我使每个执行的SQL的回滚语句更好。你能告诉我如何使用上面的例子来实现它。 非常感谢。 – user867198