Eri*_*ard 85 sql t-sql sql-server
我对TSQL中的某些东西感到惊讶.我认为,如果xact_abort打开,调用类似的东西
raiserror('Something bad happened', 16, 1);
Run Code Online (Sandbox Code Playgroud)
将停止执行存储过程(或任何批处理).
但我的ADO.NET错误消息恰恰相反.我在异常消息中收到了raiserror错误消息,以及之后发生的下一个错误消息.
这是我的解决方法(无论如何这是我的习惯),但它似乎不应该是必要的:
if @somethingBadHappened
begin;
raiserror('Something bad happened', 16, 1);
return;
end;
Run Code Online (Sandbox Code Playgroud)
文档说这个:
当SET XACT_ABORT为ON时,如果Transact-SQL语句引发运行时错误,则终止并回滚整个事务.
这是否意味着我必须使用显式交易?
Phi*_*eck 46
这是By Design TM,正如您可以在Connect上看到的SQL Server团队对类似问题的回答:
感谢您的反馈意见.根据设计,XACT_ABORT设置选项不会影响RAISERROR语句的行为.我们将考虑您的反馈,以便为将来的SQL Server版本修改此行为.
是的,对于一些希望RAISERROR
具有高严重性(例如16
)与SQL执行错误相同的人来说,这是一个问题- 事实并非如此.
您的解决方法只是您需要做的事情,使用显式事务对您要更改的行为没有任何影响.
nin*_*rid 23
如果使用try/catch块,则严重性为11-19的raiserror错误号将导致执行跳转到catch块.
任何高于16的严重性都是系统错误.要演示以下代码,请设置try/catch块并执行我们假设将失败的存储过程:
假设我们有一个表[dbo].[错误]保存错误假设我们有一个存储过程[dbo].[AssumeThisFails],当我们执行它时会失败
-- first lets build a temporary table to hold errors
if (object_id('tempdb..#RAISERRORS') is null)
create table #RAISERRORS (ErrorNumber int, ErrorMessage varchar(400), ErrorSeverity int, ErrorState int, ErrorLine int, ErrorProcedure varchar(128));
-- this will determine if the transaction level of the query to programatically determine if we need to begin a new transaction or create a save point to rollback to
declare @tc as int;
set @tc = @@trancount;
if (@tc = 0)
begin transaction;
else
save transaction myTransaction;
-- the code in the try block will be executed
begin try
declare @return_value = '0';
set @return_value = '0';
declare
@ErrorNumber as int,
@ErrorMessage as varchar(400),
@ErrorSeverity as int,
@ErrorState as int,
@ErrorLine as int,
@ErrorProcedure as varchar(128);
-- assume that this procedure fails...
exec @return_value = [dbo].[AssumeThisFails]
if (@return_value <> 0)
raiserror('This is my error message', 17, 1);
-- the error severity of 17 will be considered a system error execution of this query will skip the following statements and resume at the begin catch block
if (@tc = 0)
commit transaction;
return(0);
end try
-- the code in the catch block will be executed on raiserror("message", 17, 1)
begin catch
select
@ErrorNumber = ERROR_NUMBER(),
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ERROR_PROCEDURE();
insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
-- if i started the transaction
if (@tc = 0)
begin
if (XACT_STATE() <> 0)
begin
select * from #RAISERRORS;
rollback transaction;
insert into [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
select * from #RAISERRORS;
insert [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
return(1);
end
end
-- if i didn't start the transaction
if (XACT_STATE() = 1)
begin
rollback transaction myTransaction;
if (object_id('tempdb..#RAISERRORS') is not null)
insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
else
raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState);
return(2);
end
else if (XACT_STATE() = -1)
begin
rollback transaction;
if (object_id('tempdb..#RAISERRORS') is not null)
insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure)
values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure);
else
raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState);
return(3);
end
end catch
end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
52104 次 |
最近记录: |