次の方法で共有


トランザクションの保存 (Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceMicrosoft Fabric の SQL データベース

トランザクション内でセーブポイントを設定します。

Transact-SQL 構文表記規則

Syntax

SAVE { TRAN | TRANSACTION } { savepoint_name | @savepoint_variable }
[ ; ]

Arguments

savepoint_name

セーブポイントに割り当てる名前を指定します。 セーブポイント名は識別子の規則に従う必要があります。文字数は半角 32 文字に制限されます。 データベース エンジン インスタンスで大文字と小文字が区別されない場合でも、savepoint_nameでは常に大文字と小文字が区別されます。

@savepoint_variable

有効なセーブポイント名を含むユーザー定義の変数名を指定します。 変数は、charvarcharnchar、または nvarchar データ型を使用して宣言する必要があります。 32 文字を超える文字を変数に渡すことができますが、最初の 32 文字のみが使用されます。

Remarks

トランザクション内でセーブポイントを設定できます。 セーブポイントは、トランザクションの一部が条件付きで取り消された場合にトランザクションが返すことができる一貫性の状態を定義します。 トランザクションをセーブポイントにロールバックする場合は、必要に応じてさらに Transact-SQL ステートメントと COMMIT TRANSACTION ステートメントで完了するか、トランザクションを最初にロールバックして完全に取り消す必要があります。 トランザクション全体を取り消すには、フォーム ROLLBACK TRANSACTION transaction_nameを使用します。 この場合、そのトランザクションのすべてのステートメントまたはプロシージャが取り消されます。

トランザクションでは重複するセーブポイント名を使用できますが、セーブポイント名を指定する ROLLBACK TRANSACTION ステートメントは、その名前を使用してトランザクションを最新の SAVE TRANSACTION にロールバックするだけです。

SAVE TRANSACTION は、 BEGIN DISTRIBUTED TRANSACTION で明示的に開始されるか、ローカル トランザクションから昇格された分散トランザクションではサポートされていません。

データベース エンジンは、個別に管理可能な入れ子になったトランザクションをサポートしていません。 内部トランザクションのコミットは @@TRANCOUNT デクリメントされますが、他の影響はありません。 セーブポイントが存在し、ROLLBACK ステートメントで指定されていない限り、内部トランザクションのロールバックは常に外部トランザクションをロールバックします。

ロック動作

savepoint_nameを指定するROLLBACK TRANSACTION ステートメントは、エスカレートされたロックと変換されたロックを除き、セーブポイントを超えて取得されたすべてのロックを解放します。 これらのロックは解放されず、以前のロック モードに変換されません。

Permissions

public ロールのメンバーシップが必要です。

Examples

この記事のコード サンプルでは、AdventureWorks2025 または AdventureWorksDW2025 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。

次の例は、ストアド プロシージャが実行される前にトランザクションが開始された場合に、トランザクション セーブポイントを使用してストアド プロシージャによって行われた変更のみをロールバックする方法を示しています。

IF EXISTS (SELECT name FROM sys.objects
           WHERE name = N'SaveTranExample')
    DROP PROCEDURE SaveTranExample;
GO

CREATE PROCEDURE SaveTranExample
    @InputCandidateID INT
AS
-- Detect whether the procedure was called
-- from an active transaction and save
-- that for later use.
-- In the procedure, @TranCounter = 0
-- means there was no active transaction
-- and the procedure started one.
-- @TranCounter > 0 means an active
-- transaction was started before the
-- procedure was called.
DECLARE @TranCounter INT;
SET @TranCounter = @@TRANCOUNT;

IF @TranCounter > 0
    -- Procedure called when there is
    -- an active transaction.
    -- Create a savepoint to be able
    -- to roll back only the work done
    -- in the procedure if there is an
    -- error.
    SAVE TRANSACTION ProcedureSave;
ELSE
    -- Procedure must start its own
    -- transaction.
    BEGIN TRANSACTION;
-- Modify database.
BEGIN TRY
    DELETE HumanResources.JobCandidate
        WHERE JobCandidateID = @InputCandidateID;
    -- Get here if no errors; must commit
    -- any transaction started in the
    -- procedure, but not commit a transaction
    -- started before the transaction was called.
    IF @TranCounter = 0
        -- @TranCounter = 0 means no transaction was
        -- started before the procedure was called.
        -- The procedure must commit the transaction
        -- it started.
        COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    -- An error occurred; must determine
    -- which type of rollback will roll
    -- back only the work done in the
    -- procedure.
    IF @TranCounter = 0
        -- Transaction started in procedure.
        -- Roll back complete transaction.
        ROLLBACK TRANSACTION;
    ELSE
        -- Transaction started before procedure
        -- called, do not roll back modifications
        -- made before the procedure was called.
        IF XACT_STATE() <> -1
            -- If the transaction is still valid, just
            -- roll back to the savepoint set at the
            -- start of the stored procedure.
            ROLLBACK TRANSACTION ProcedureSave;
            -- If the transaction is uncommitable, a
            -- rollback to the savepoint is not allowed
            -- because the savepoint rollback writes to
            -- the log. Just return to the caller, which
            -- should roll back the outer transaction.

    -- After the appropriate rollback, return error
    -- information to the caller.
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT @ErrorMessage = ERROR_MESSAGE();
    SELECT @ErrorSeverity = ERROR_SEVERITY();
    SELECT @ErrorState = ERROR_STATE();

    RAISERROR (
              @ErrorMessage, -- Message text.
              @ErrorSeverity, -- Severity.
              @ErrorState -- State.
              );
END CATCH
GO