Der*_*omm 5 sql-server sql-server-2008-r2 ddl rollback
在 SQL Server 2008 R2 中工作时,我试图将一组 DDL 语句作为一个组回滚(想想数据库的升级脚本),但遇到了麻烦。
取以下代码:
begin try
begin tran
create table foo (i int)
alter table foo add x dog
insert into foo select 1,1
insert into foo select 1,1,1
commit tran
end try
begin catch
rollback tran
print @@error
end catch
Run Code Online (Sandbox Code Playgroud)
我期待尝试在更改表语句上失败,下降到捕获,回滚事务,并打印错误消息。但是,如果您检查对象/表,您会看到 foo 仍然存在(因此创建表没有正确回滚)。
select * from sys.objects where name = 'foo'
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么?
发生错误是因为由于延迟名称解析而引发的错误是重新编译错误的一部分。查看 SQL BOL,当它们发生在与 try...catch 相同的级别时,它们不会被困住。但是,如果它发生在不同的级别,无论是动态 SQL 还是 SP 调用,它都会被捕获并回滚。
使用 Profiler,您可以看到“alter table foo add x dog”语句在执行之前重新编译,然后出错并绕过 catch 块。

如果您将语句包装在动态 SQL 中,则错误不会返回到 Profiler 并且事务将回滚

您看到此结果的原因是 SQL Server 实际上并未捕获您的 ALTER TABLE 错误。您会注意到,当您运行此命令时,您会看到红色错误消息而不是打印行 - 您可以通过更改print @@error为类似print 'HELLO!'; 来验证这一点。在这种情况下,您将不会看到“HELLO!” 打印; 您将会看到错误。在线书籍列出了您无法发现的错误情况。
这里的另一种选择是在SET XACT_ABORT ON开始交易之前。然后,您可以在收到第一个错误时回滚更改。
| 归档时间: |
|
| 查看次数: |
5227 次 |
| 最近记录: |