techbank.jp コミュニティ

     あれ?どうやるんだっけ?を解決する

坊やがゆくtech

12月 2009 - 投稿

  • トランザクションのネストと@@TRANCOUNTの関係、コミット/ロールバックについてまとめ

    Microsoft TechNet「トランザクションのネスト」にて簡潔に説明されているので引用させていただきます。

    @@TRANCOUNTのカウント(ざっくり)

    • BEGIN TRANSACTION ステートメントは @@TRANCOUNT を 1 ずつ増やします。
    • COMMIT TRANSACTION は @@TRANCOUNT を 1 ずつ減らします。
    • ROLLBACK TRANSACTION ステートメントは、ネストしたトランザクションがすべてロールバックされ、@@TRANCOUNT は 0 になります。
    • @@TRANCOUNT が 0 の場合は、トランザクションにいません。
    http://technet.microsoft.com/ja-jp/library/aa213076(SQL.80).aspx

    トランザクションの外側と内側の概念、超重要!

    Microsoft SQL Server は、内部トランザクションのコミットを無視します。
    トランザクションは、最も外側のトランザクションが終了したときの処理に基づいてコミットまたはロールバックされます。
    外側のトランザクションがコミットされた場合、ネストした内部トランザクションもコミットされます。
    外側のトランザクションがロールバックされた場合、内部トランザクションが個々にコミットされているかどうかに関係なく、内部トランザクションもすべてがロールバックされます。

    http://technet.microsoft.com/ja-jp/library/aa213076(SQL.80).aspx

    つまり一番外側のコミット/ロールバックに依存するということです。
    ※部分的にロールバックしたい場合はセーブポイントを使用します。

    図説およびサンプルコード(英語)
    http://www.vfpconversion.com/Article.aspx?quickid=0305111

    内側のトランザクションのエラー処理などはクセがあるので上記のサンプルコードを参考にされると良いでしょう。
    具体的には「内側のトランザクションではROLLBACKは発行せずにCOMMITで終了して戻り値で判断する。そしてROLLBACKは外側のトランザクションで行う。」です。

    -- Normal exit
    IF @@TRANCOUNT > 0
     COMMIT
    RETURN(0)
    
    -- Error Exit
    ErrExit:
    IF @@TRANCOUNT > 1
     COMMIT
    ELSE
     IF @@TRANCOUNT = 1
      ROLLBACK
    RETURN(-1)
    

    参考:
    SQL Server 2000でのコネクション/トランザクション問題
    http://d.hatena.ne.jp/PoohKid/20060608/p2

techbank.jp