【问题标题】:Why did part of transaction succeed when another part failed?为什么另一部分失败时部分事务成功?
【发布时间】:2022-01-20 17:15:00
【问题描述】:

外循环读取导入表中所有不同的文件名。在事务内部,我调用一个 proc 来处理单个文件的行,在系统中进行各种插入和更新。完成后,我从该文件中删除行。然后我承诺。 今天,我在尝试将空值插入主键时遇到错误。好的,我会弄清楚是什么原因造成的。但是,当我查看导入表时,该文件的所有行都被删除了!为什么?

declare @filename varchar(55);
declare fn cursor for select distinct filename from iox277 order by filename;
begin try
    open fn;
    fetch next from fn into @filename;
    while @@fetch_status = 0 begin
        begin transaction
        exec spIntake277 @filename; -- insert failed here    
        delete from iox277 where filename = @filename; -- delete still happened!!
        commit;
        fetch next from fn into @filename;
    end
end try
begin catch
    rollback;
    close fn;
    deallocate fn;
    select 'ERROR', error_message();
    return;
end catch

这是调用内部 sp 的主存储过程的主体。内部没有交易。内部犯了试图将null插入PK的错误。

【问题讨论】:

  • 在您的catch 中调用rollback,它会回滚迄今为止发生的所有事情 - 包括(我有点猜测,因为您没有向我们展示)您在表格中的原始插入。
  • 鉴于您的代码 EATS 捕获块中的错误,假设相同的事情发生在您的内部 SP 内部似乎是合乎逻辑的,以便外部 SP 看不到错误。
  • 当“...insert failed here...”发生时,事务是被标记为“注定”还是异常被默默吞没?
  • @DaleK 是的。没有嵌套事务。但我认为你的 cmets 让我找到了一个可能的解决方案。在嵌套 proc 中,我尝试设置与父 proc 相同的 catch 块(如上所示)。我通过 select 语句返回错误,就好像它们要返回到应用程序一样,但事实并非如此。我认为我应该在嵌套的过程中使用 throw ,以便错误看起来像外部过程的错误,然后应该触发回滚。下次我要试试。我如何评价你的评论?
  • 我通过 select 语句返回错误这是你的问题。不要这样做。重新抛出错误。

标签: sql sql-server azure tsql


【解决方案1】:

感谢大家的 cmets。他们为我在 SQL 编程的 20 年中从未听说过的事情做出了贡献。

  • 我正在用临时表替换游标:
   select (row_number() over(order by <column>))RN, * into #tbl from <table>

(只是在这里发布,希望以后对某人有所帮助)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-07
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    相关资源
    最近更新 更多