【问题标题】:applying sql transactions on non consecutive steps在非连续步骤上应用 sql 事务
【发布时间】:2015-04-02 05:36:29
【问题描述】:

我有以下SQL语句场景:

DELETE FROM T1
DELETE FROM T2
DELETE FROM T3
DELETE FROM T4
DELETE FROM T5

在上述情况下我需要实现:

  1. 如果下一条 SQL 语句失败,则会回滚上一条语句,如果成功则移动到下一条语句。

  2. 但是对于第 5 步,我需要回滚第 3 步,按原样提交第 4 步。

任何意见,请多多指教。

【问题讨论】:

  • 那么为什么不重新排序第 3 步和第 4 步呢?
  • 由于某些业务逻辑,我们不能改变语句的顺序。

标签: sql sql-server sql-server-2008 tsql transactions


【解决方案1】:

在 SQL Server 中,没有嵌套事务之类的东西。但是您可以通过一些错误处理编排来做到这一点。

此示例代码只是在 T5 命令遇到错误的情况下再次从 T4 重新发出删除命令。

SET NOCOUNT ON;

-- (use temp table, since table vars do not participate in transactions)
CREATE TABLE #T1(C int);
CREATE TABLE #T2(C int);
CREATE TABLE #T3(C int);
CREATE TABLE #T4(C int);
CREATE TABLE #T5(C int);

INSERT INTO #T1 SELECT 1;
INSERT INTO #T2 SELECT 1;
INSERT INTO #T3 SELECT 1;
INSERT INTO #T4 SELECT 1;
INSERT INTO #T5 SELECT 1;

BEGIN TRY 

    BEGIN TRAN TR1;

    DELETE FROM #T1;
    DELETE FROM #T2;
    DELETE FROM #T3;    
    DELETE FROM #T4;
    --select 1/0 as 'forced error @ stage1';
END TRY
BEGIN CATCH
    PRINT 'error @stage1';
    PRINT 'rollback @stage1';

    ROLLBACK TRAN TR1;  
    RETURN;
END CATCH

BEGIN TRY
    DELETE FROM #T5;
    select 1/0 as 'forced error @stage2';
    COMMIT TRAN TR1;
END TRY
BEGIN CATCH
    PRINT 'error @stage2';  
    ROLLBACK TRAN TR1;  

    BEGIN TRY
        print 'redo delete T4'
        BEGIN TRAN TR2;
        DELETE FROM #t4;
        --select 1/0 as 'forced error @redo delete';
        COMMIT TRAN TR2;
    END TRY
    BEGIN CATCH
        ROLLBACK TRAN TR2;
        PRINT 'second chance delete from T4 failed';    
    END CATCH

END CATCH

select count(*) as count,'T1' as 'table' from #T1
union all
select count(*) as count,'T2' as 'table' from #T2
union all
select count(*) as count,'T3' as 'table' from #T3
union all
select count(*) as count,'T4' as 'table' from #T4
union all
select count(*) as count,'T5' as 'table' from #T5

DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
DROP TABLE #T4;
DROP TABLE #T5;

【讨论】:

    【解决方案2】:

    您可以在 TRY-CATCH 块中使用 SAVE POINTSGOTO

    这可以实现您在问题中想要的两个目标:

    每次使用取消注释特定的“SELECT 1/0”语句来测试它:

    SET NOCOUNT ON;
    
    CREATE TABLE #T1(ID int);
    CREATE TABLE #T2(ID int);
    CREATE TABLE #T3(ID int);
    CREATE TABLE #T4(ID int);
    CREATE TABLE #T5(ID int);
    
    INSERT INTO #T1 SELECT 1;
    INSERT INTO #T2 SELECT 1;
    INSERT INTO #T3 SELECT 1;
    INSERT INTO #T4 SELECT 1;
    INSERT INTO #T5 SELECT 1;
    
    BEGIN TRAN 
            BEGIN TRY
                DELETE FROM #T1
                --SELECT 1/0
            END TRY
            BEGIN CATCH
                ROLLBACK TRAN
                GOTO LAST2
            END CATCH
    
        SAVE TRAN pice1
            BEGIN TRY
                DELETE FROM #T2
                --SELECT 1/0
            END TRY
            BEGIN CATCH
                ROLLBACK TRAN 
                GOTO LAST2
            END CATCH
    
        SAVE TRAN pice2
            BEGIN TRY
                DELETE FROM #T3
                --SELECT 1/0
            END TRY
            BEGIN CATCH
                ROLLBACK TRAN pice1
                GOTO LAST
            END CATCH
    
        SAVE TRAN pice3
            BEGIN TRY
                DELETE FROM #T4
                --SELECT 1/0
            END TRY
            BEGIN CATCH
                ROLLBACK TRAN pice2
                GOTO LAST
            END CATCH
    
        SAVE TRAN pice4
            BEGIN TRY
                DELETE FROM #T5
                SELECT 1/0
            END TRY
            BEGIN CATCH
                ROLLBACK TRAN pice2
                DELETE FROM #T4
                GOTO LAST
            END CATCH
    
    LAST:
    COMMIT TRAN
    LAST2:
    SELECT COUNT(*) CT,'T1' [TABLE] FROM #T1
    UNION
    SELECT COUNT(*) CT,'T2' [TABLE] FROM #T2
    UNION
    SELECT COUNT(*) CT,'T3' [TABLE] FROM #T3
    UNION
    SELECT COUNT(*) CT,'T4' [TABLE] FROM #T4
    UNION
    SELECT COUNT(*) CT,'T5' [TABLE] FROM #T5
    
    DROP TABLE #T1;
    DROP TABLE #T2;
    DROP TABLE #T3;
    DROP TABLE #T4;
    DROP TABLE #T5;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 2018-09-02
      • 2012-08-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      • 1970-01-01
      相关资源
      最近更新 更多