14

SQL Server Books Online を見ると、Microsoft は、ストアド プロシージャでネストされたトランザクションを処理する (間違った) メソッドを持っているようです。

ネスティング トランザクション

明示的なトランザクションはネストできます。これは主に、既にトランザクション内にあるプロセスから、またはアクティブなトランザクションを持たないプロセスから呼び出すことができるストアド プロシージャ内のトランザクションをサポートすることを目的としています。

この例は、独自のトランザクションを開始するストアド プロシージャを示しています(「プロシージャは、それを実行するプロセスのトランザクション モードに関係なく、そのトランザクションを強制します。」) :

CREATE PROCEDURE TransProc @PriKey INT, @CharCol CHAR(3) AS
   BEGIN TRANSACTION InProc
      ...
   COMMIT TRANSACTION InProc;

このプロシージャは、トランザクションを実行せずに呼び出すことができます。

EXECUTE TransProc 3,'bbb';

または明示なトランザクションの場合:

BEGIN TRANSACTION OutOfProc;

EXEC TransProc 1, 'aaa';

COMMIT TRANSACTION OutOfProc

彼らが対処していないのは、保存されたプロデュアが次の場合に何が起こるかです。

  • エラーで失敗しますが、トランザクションは実行されたままになります
  • エラーで失敗しますが、トランザクションを実行したままにしません
  • エラーが発生しますが、トランザクションを開いたまま実行を続けます
  • エラーが発生しますが、トランザクションをロールバックして実行を継続します

ありません:

  • SET XACT_ABORT ON
  • @@トランカウント

標準的な例のどこでも。

私がもっとよく知らなかったら、次の行だと思っていたでしょう:

次の例は、ネストされたトランザクションの使用目的を示しています。

実際に読むべき

次の例は、ネストされたトランザクションを使用しない方法を示しています。

誰かがこの BOL の例の頭または尾を作ることができない限り?

4

2 に答える 2

44

トランザクションで try catch ブロックを使用する必要があります。したがって、catch ブロックでエラーが発生した場合は、トランザクションをロールバックできます。

そのためには、以下のSQLサーバーコードを参照してください。

BEGIN TRANSACTION;

BEGIN TRY
    -- Some code
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH

    ROLLBACK TRANSACTION;
END CATCH;
于 2012-11-01T05:28:49.870 に答える
16
CREATE PROCEDURE [usp_my_procedure_name]
AS
BEGIN
  SET NOCOUNT ON;
  DECLARE @trancount int;
  SET @trancount = @@trancount;
  BEGIN TRY
    IF @trancount = 0
      BEGIN TRANSACTION
      ELSE
        SAVE TRANSACTION usp_my_procedure_name;

    -- Do the actual work here

    lbexit:
      IF @trancount = 0
      COMMIT;
  END TRY
  BEGIN CATCH
    DECLARE @error int,
            @message varchar(4000),
            @xstate int;

    SELECT
      @error = ERROR_NUMBER(),
      @message = ERROR_MESSAGE(),
      @xstate = XACT_STATE();

    IF @xstate = -1
      ROLLBACK;
    IF @xstate = 1 AND @trancount = 0
      ROLLBACK
    IF @xstate = 1 AND @trancount > 0
      ROLLBACK TRANSACTION usp_my_procedure_name;

    RAISERROR ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message);
  END CATCH
END
于 2013-02-06T12:50:08.637 に答える