SAVE TRANSACTION(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

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

Remarks

트랜잭션 내에서 저장점을 설정할 수 있습니다. 저장점은 트랜잭션의 일부가 조건부로 취소될 경우 트랜잭션이 반환할 수 있는 일관성 상태를 정의합니다. 트랜잭션이 저장점으로 롤백되는 경우 필요한 경우 더 많은 Transact-SQL 문과 COMMIT TRANSACTION 문을 사용하여 완료를 진행해야 합니다. 그렇지 않으면 트랜잭션을 다시 시작 부분으로 롤백하여 완전히 취소해야 합니다. 전체 트랜잭션을 취소하려면 양식을 ROLLBACK TRANSACTION transaction_name사용합니다. 트랜잭션의 모든 문이나 프로시저의 실행이 취소됩니다.

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

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

비고

데이터베이스 엔진은 독립적으로 관리 가능한 중첩 트랜잭션을 지원하지 않습니다. 내부 트랜잭션의 커밋은 감소 @@TRANCOUNT 하지만 다른 효과는 없습니다. 저장점이 존재하고 문에 지정되지 않는 한 내부 트랜잭션의 롤백은 항상 외부 트랜잭션을 ROLLBACK 롤백합니다.

잠금 동작

ROLLBACK TRANSACTION savepoint_name 지정하는 문은 에스컬레이션 및 변환된 잠금을 제외하고 저장점 외에 획득된 모든 잠금을 해제합니다. 이러한 잠금은 해제되지 않으며 이전 잠금 모드로 다시 변환되지 않습니다.

Permissions

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

Examples

이 글의 코드 샘플은 Azure Data SQL Samples Repository GitHub 저장소에서 다운로드할 수 있는 샘플 AdventureWorksDW2025 데이터베이스를 AdventureWorks2025 사용합니다.

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

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