sql >> データベース >  >> RDS >> Sqlserver

SQLServerで「COMMITTRANSACTIONリクエストに対応するBEGINTRANSACTIONがありません」を修正する方法

    「COMMITTRANSACTIONリクエストに対応するBEGINTRANSACTIONがありません」というエラーメッセージ3902、レベル16が表示された場合は、COMMITが迷っている可能性があります。 ステートメント。

    エラー処理を実装し、コード内の他の場所でトランザクションをすでにコミットまたはロールバックしていることを忘れているために、これが発生している可能性があります。

    エラーの例

    エラーを示す簡単な例を次に示します。

    SELECT ProductName, ProductPrice FROM Products;
    COMMIT TRANSACTION;

    結果:

    (7 rows affected)
    Msg 3902, Level 16, State 1, Line 2
    The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

    これは、SET IMPLICIT_TRANSACTIONSの場合に発生します OFFです 。 SET IMPLICIT_TRANSACTIONSの場合は、以下を参照してください。 ONです 。

    エラー処理によるエラーの例

    エラー処理を実装し、コード内の他の場所でトランザクションをすでにコミットまたはロールバックしていることを忘れているために、これが発生している可能性があります。

    例:

    BEGIN TRANSACTION
        BEGIN TRY 
    
            INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
            VALUES ( 5006, SYSDATETIME(), 1006 );
            
            INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
            VALUES ( 5006, 1, 1, 20, 25.99 );
            
            INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
            VALUES ( 5006, 2, 7, 120, 9.99 );
    
            COMMIT TRANSACTION;
    
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION;
        END CATCH
    COMMIT TRANSACTION;

    結果:

    (1 row affected)
    (1 row affected)
    (1 row affected)
    Msg 3902, Level 16, State 1, Line 20
    The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

    この場合、私はすでにCOMMIT TRANSACTIONを持っていました TRYで ブロック。したがって、2番目のCOMMIT TRANSACTIONまでに が検出された場合、トランザクションはすでにコミットされています。

    トランザクションでエラーが発生し、ロールバックされた場合でも、同じことがわかります。ロールバックするとトランザクションが終了するため、これ以上COMMITは発生しません。 ステートメントが必要です。

    したがって、この問題を修正するには、最後のCOMMIT TRANSACTIONを削除するだけです。 、およびトランザクションコードは次のようになります:

    BEGIN TRANSACTION
        BEGIN TRY 
    
            INSERT INTO Orders ( OrderId, OrderDate, CustomerId )
            VALUES ( 5006, SYSDATETIME(), 1006 );
            
            INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
            VALUES ( 5006, 1, 1, 20, 25.99 );
            
            INSERT INTO OrderItems ( OrderId, OrderItemId, ProductId, Quantity, ItemPrice )
            VALUES ( 5006, 2, 7, 120, 9.99 );
    
            COMMIT TRANSACTION;
            
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION;
        END CATCH

    暗黙のトランザクション

    暗黙のトランザクションを有効にしている場合、最初の例とは異なる結果が得られる可能性があります。

    IMPLICIT_TRANSACTIONSを設定した場合 ONへ 、これが私たちが得るものです:

    SET IMPLICIT_TRANSACTIONS ON;
    SELECT ProductName, ProductPrice FROM Products;
    COMMIT TRANSACTION;

    結果:

    +---------------------------------+----------------+
    | ProductName                     | ProductPrice   |
    |---------------------------------+----------------|
    | Left handed screwdriver         | 25.99          |
    | Long Weight (blue)              | 14.75          |
    | Long Weight (green)             | 11.99          |
    | Sledge Hammer                   | 33.49          |
    | Chainsaw                        | 245.00         |
    | Straw Dog Box                   | 55.99          |
    | Bottomless Coffee Mugs (4 Pack) | 9.99           |
    +---------------------------------+----------------+
    (7 rows affected)

    エラーは発生しません。

    これは、特定のT-SQLステートメントが実行されると自動的にトランザクションを開始するためです。見えないBEGIN TRANSACTIONが前に付いているかのようです ステートメント。

    IMPLICIT_TRANSACTIONSの場合 OFFです 、これらのステートメントは自動的にコミットされます。目に見えないCOMMIT TRANSACTIONが成功したかのようです 声明。このシナリオでは、トランザクションは自動コミットモードになっています。

    IMPLICIT_TRANSACTIONSの場合 ONです 、目に見えないCOMMIT TRANSACTIONはありません 声明。これらのステートメントは、まだ非表示のBEGIN TRANSACTIONによって開始されます 、ただし、明示的に終了する必要があります。

    暗黙的なトランザクションは、明示的にコミットされるか、明示的にロールバックされるまで進行中です。

    したがって、この例では、迷子のCOMMIT TRANSACTION 暗黙のトランザクションを終了するには、ステートメントが実際に必要でした。


    1. SQLを使用して連続する日付範囲を検出する

    2. OracleのCOS()関数

    3. WHERE句の列名エイリアスを参照してください

    4. 割り当て順序スキャン