我需要为我的应用程序提供自动更新功能。 我在应用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”并插入数据进入“测试”表
我该如何处理这项任务?任何帮助将不胜感激。
如果您需要更多信息,请告诉我
答案 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
也会在结尾删除这些行。