다음을 통해 공유


SAVE TRANSACTION(Transact-SQL)

트랜잭션 내에서 저장점을 설정합니다.

항목 링크 아이콘Transact-SQL 구문 표기 규칙

구문

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

인수

  • savepoint_name
    저장점에 할당된 이름입니다. 저장점 이름은 식별자에 적용되는 규칙을 준수해야 하지만 길이는 32자로 제한됩니다.

  • **@**savepoint_variable
    유효한 저장점 이름이 포함된 사용자 정의 변수의 이름입니다. 변수는 char, varchar, nchar 또는 nvarchar 데이터 형식으로 선언해야 합니다. 변수에 32자 이상 전달할 수 있지만 전달된 문자의 처음부터 32자까지만 사용됩니다.

주의

사용자가 트랜잭션 내에서 저장점 또는 표식을 설정할 수 있습니다. 저장점은 트랜잭션의 일부가 조건에 따라 취소될 경우에 트랜잭션이 되돌아갈 수 있는 위치를 정의합니다. 트랜잭션이 저장점으로 롤백되면 완료될 때까지 계속 실행되거나(필요할 경우 더 많은 Transact-SQL 문과 COMMIT TRANSACTION 문 사용) 트랜잭션을 시작 부분으로 롤백하여 모두 함께 취소되어야 합니다. 전체 트랜잭션을 취소하려면 ROLLBACK TRANSACTION transaction_name의 형식을 사용하십시오. 트랜잭션의 모든 문이나 프로시저의 실행이 취소됩니다.

중복된 저장점 이름을 트랜잭션에서 사용할 수 있지만 저장점 이름을 지정하는 ROLLBACK TRANSACTION 문은 해당 이름을 사용하는 최신 SAVE TRANSACTION으로만 트랜잭션을 롤백합니다.

BEGIN DISTRIBUTED TRANSACTION으로 명시적으로 시작되거나 로컬 트랜잭션에서 에스컬레이션된 분산 트랜잭션에서는 SAVE TRANSACTION이 지원되지 않습니다.

중요 정보중요

트랜잭션이 시작되면 트랜잭션 중 사용되는 리소스가 트랜잭션 완료 시점까지 유지됩니다. 즉, 리소스가 잠깁니다. 트랜잭션의 일부가 저장점으로 롤백되어도 리소스는 트랜잭션이 완료될 때까지 또는 전체 트랜잭션이 롤백될 때까지 계속 유지됩니다.

사용 권한

public 역할의 멤버 자격이 필요합니다.

다음 예에서는 저장 프로시저가 실행되기 전에 활성 트랜잭션이 시작되는 경우 트랜잭션 저장점을 사용하여 저장 프로시저에서 수정된 내용만 롤백하는 방법을 보여 줍니다.

USE AdventureWorks;
GO
IF EXISTS (SELECT name FROM sys.objects
           WHERE name = N'SaveTranExample')
    DROP PROCEDURE SaveTranExample;
GO
CREATE PROCEDURE SaveTranExample
    @InputCandidateID INT
AS
    -- Detect if 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, echo 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