我有一个存储过程 proc_in
将数据插入到 tbl
表
create table tbl(id int identity, val nvarchar(50))
create procedure proc_in
as
begin
insert into tbl(val)
values ('test')
end
而且我有 proc_out
我打电话给 proc_in
create procedure proc_out
as
begin
exec proc_in
DECLARE @MessageText NVARCHAR(100);
SET @MessageText = N'This is a raiserror %s';
RAISERROR(@MessageText, 16, 1, N'MSG')
end
我如何编写 proc_out
使其始终返回 raiserror
以在 TBL
表中插入。
我这样称呼proc_out
begin tran
declare @err int = 0
exec @err = proc_out
if @ERR = 0
commit tran
else
rollback tran
答案 0 :(得分:0)
您将调用包装在调用上下文中的单个事务中,因此:
.editorconfig
将始终回滚该事务中发生的所有事情。
避免这种情况的一种方法是将事务移动到您的“proc_out”SP 中,例如
begin tran
declare @err int = 0
exec @err = proc_out
if @ERR = 0
commit tran
else
rollback tran
或者,我还没有尝试过,您可以尝试使用 create procedure proc_out
as
begin
set nocount, xact_abort on;
exec proc_in;
begin tran;
-- All your other code
if @Err = 1 begin
rollback;
declare @MessageText nvarchar(100);
set @MessageText = N'This is a raiserror %s';
--raiserror(@MessageText, 16, 1, N'MSG');
-- Actually for most cases now its recommended to use throw
throw 51000, @MessageText 1;
end; else begin
commit;
end;
return 0;
end;
例如
savepoint
然后将其称为:
create procedure proc_out
as
begin
set nocount on;
exec proc_in;
save transaction SavePoint1;
declare @MessageText nvarchar(100);
set @MessageText = N'This is a raiserror %s';
raiserror(@MessageText, 16, 1, N'MSG');
return 0;
end;
不过,我不喜欢这种方法,因为对 SP 内部工作原理的了解现在已经泄露到调用上下文中。
有些错误无论如何都会回滚整个事务。
了解此处的 XACT_ABORT
设置很重要。
当 SET XACT_ABORT 为 OFF 时,在某些情况下,只会回滚引发错误的 Transact-SQL 语句,事务继续处理。根据错误的严重程度,即使 SET XACT_ABORT 为 OFF,整个事务也可能会回滚。 OFF 是 T-SQL 语句的默认设置,而 ON 是触发器的默认设置。