首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XACT_ABORT在批处理中与sp_recompile的行为不一致

XACT_ABORT在批处理中与sp_recompile的行为不一致
EN

Stack Overflow用户
提问于 2012-11-30 18:46:14
回答 1查看 232关注 0票数 0

我有两个类似的TSQL脚本,我在其中设置了XACT_ABORT。我期望_test表在脚本执行后不存在,因为我有意使用在事务中包装的语句,这将引发错误。

第一个脚本正确地回滚_test表的创建。

代码语言:javascript
复制
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
CREATE TABLE dbo._test(ID int IDENTITY(1, 1) NOT NULL)
EXEC sp_does_not_exist --raises error!
GO
IF @@TRANCOUNT > 0
    COMMIT;

但是,第二个脚本不会回滚_test的创建,并且该表在脚本执行后存在:

代码语言:javascript
复制
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
CREATE TABLE dbo._test(ID int IDENTITY(1, 1) NOT NULL)
EXEC sp_recompile sp_does_not_exist; --raises error!
GO
IF @@TRANCOUNT > 0
    COMMIT;

为什么第二个脚本在执行后不删除_test表?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-30 21:34:47

您还没有提到您的Server版本,但是由于您的脚本中唯一的区别是sp_recompile,所以这似乎是一个很好的查看位置。在2008年R2中,它有以下逻辑:

代码语言:javascript
复制
BEGIN TRANSACTION
-- CHECK VALIDITY OF OBJECT NAME --
--  (1) Must exist in current database
--  (2) Must be a table or an executable object
select @objid = object_id(@objname, 'local')

    if @objid is null OR
        (ObjectProperty(@objid, 'IsTable') = 0 AND
         ObjectProperty(@objid, 'IsExecuted') = 0)
    begin
        COMMIT TRANSACTION
        raiserror(15165,-1,-1 ,@objname)
        return @@error
    end

因此,sp_recompile在尝试直接访问对象之前检查对象是否存在,如果找不到对象,则会引发严重程度的错误。严重性级别小于零的RAISERROR 的文档被解释为零,而严重性级别的文档在严重性为零时不会引发系统错误。

实际上,将RAISERRORsp_recompile添加到脚本中表明它不影响@@TRANCOUNT

代码语言:javascript
复制
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
CREATE TABLE dbo._test(ID int IDENTITY(1, 1) NOT NULL)
select @@trancount as 'before raiserror'    
raiserror(15165,-1,-1 ,'sp_does_not_exist')
select @@trancount as 'after raiserror' 

GO
IF @@TRANCOUNT > 0
    COMMIT;

在引发错误之前和之后,@@TRANCOUNT是1,所以没有什么可以触发回滚。但是,如果这样做,则不会执行第二个SELECT,因为该错误是由数据库引擎“直接”引发的:

代码语言:javascript
复制
SET XACT_ABORT ON
GO
BEGIN TRANSACTION
CREATE TABLE dbo._test(ID int IDENTITY(1, 1) NOT NULL)
select @@trancount as 'before raiserror'    
exec sp_does_not_exist
select @@trancount as 'after raiserror' 

GO
IF @@TRANCOUNT > 0
    COMMIT;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13651216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档