如何提交嵌套存储过程,一般是 raiserror 时

时间:2021-02-03 22:11:07

标签: sql sql-server tsql stored-procedures raiserror

我有一个存储过程 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

1 个答案:

答案 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 是触发器的默认设置。