SQL Server-트랜잭션이 오류로 롤백됩니까?


193

다음과 같은 SQL Server 2005에서 일부 SQL을 실행하는 클라이언트 앱이 있습니다.

BEGIN TRAN;
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
COMMIT TRAN;

하나의 긴 문자열 명령으로 전송됩니다.

삽입 중 하나가 실패하거나 명령의 일부가 실패하면 SQL Server가 트랜잭션을 롤백합니까? 롤백되지 않으면 롤백하기 위해 두 번째 명령을 보내야합니까?

사용중인 API 및 언어에 대한 세부 정보를 제공 할 수 있지만 SQL Server는 모든 언어에 대해 동일하게 응답해야한다고 생각합니다.


답변:


205

set xact_abort on트랜잭션이 발생하면 오류 발생시 SQL이 자동으로 롤백되도록 할 수 있습니다 .


1
이것은 MS SQL 2K 이상에서 작동합니까? 이것은 가장 간단한 해결책 인 것 같습니다.
— jonathanpeppers 2016

1
2000, 2005 및 2008 문서에 표시되므로 예라고 가정합니다. 우리는 2008 년에 그것을 사용하고 있습니다.

8
이 기능을 해제해야합니까, 아니면 세션 당입니까?
— Marc

5
@Marc의 범위 xact_abort는 연결 수준에 있습니다.
— Keith

2
@AlexMcMillan DROP PROCEDURE 문은 데이터와 함께 작동하는 INSERT와 달리 데이터베이스 구조를 수정합니다. 따라서 트랜잭션으로 랩핑 할 수 없습니다. 지나치게 단순화하고 있지만 기본적으로 그 방법입니다.
— eksortso

195

전체 트랜잭션이 롤백 될 것입니다. 명령을 실행하여 롤백해야합니다.

TRY CATCH다음과 같이 이것을 블록으로 감쌀 수 있습니다

BEGIN TRY
    BEGIN TRANSACTION

        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);

    COMMIT TRAN -- Transaction Success!
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN --RollBack in case of Error

    -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception
    RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)
END CATCH

2
나는 DyingCactus의 솔루션을 더 좋아합니다. 그는 1 줄의 코드를 변경합니다. 어떤 이유로 든 더 나은 (또는 더 신뢰할 수있는) 경우 알려주세요.
— jonathanpeppers 2016

14
try catch는 오류를 캡처 (및 수정 가능)하고 필요한 경우 사용자 정의 오류 메시지를 발생시키는 기능을 제공합니다.
— Raj More

11
"캡처 및 수정"보다 "캡처 및 수정"이 더 자주 생각됩니다.
— quillbreaker

24
RAISERROR의 구문은 SQL Server 2008R2 이상에서 올바르지 않습니다. 올바른 구문 은 msdn.microsoft.com/en-us/library/ms178592.aspx 를 참조 하십시오 .
— Eric J.

2
@BornToCode 트랜잭션이 존재하는지 확인합니다. 주어진 조건 ()에서 트랜잭션을 롤백 try했지만 코드가 실패 한다고 가정합니다 . 더 이상 거래가 없지만 여전히로 이동 중 catch입니다.
— 가브리엘 GM

42

다음은 MSSQL Server 2016에서 작동하는 오류 메시지가 나오는 코드입니다.

BEGIN TRY
    BEGIN TRANSACTION 
        -- Do your stuff that might fail here
    COMMIT
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN

        DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE()
        DECLARE @ErrorSeverity INT = ERROR_SEVERITY()
        DECLARE @ErrorState INT = ERROR_STATE()

    -- Use RAISERROR inside the CATCH block to return error  
    -- information about the original error that caused  
    -- execution to jump to the CATCH block.  
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH

1
DECLARE @Var TYPE; SET @Var = ERROR;SQL Server 2005에서 오류 발생에 사용해야 했습니다. 그렇지 않으면 오류를 발생시키는 위의 코드가 이전 DB에서도 작동합니다. 로컬 변수에 기본값을 할당하려고하면 문제가 발생합니다.
— jtlindsey

간단한 THROW를 사용할 수 있습니다. RAISERROR 및 ERROR_ * 선언 대신.
— rodzmkii

21

MDSN 기사에서 트랜잭션 제어 (데이터베이스 엔진) .

제약 조건 위반과 같은 런타임 문 오류가 일괄 처리로 발생하면 데이터베이스 엔진의 기본 동작은 오류를 생성 한 문만 롤백하는 것입니다. SET XACT_ABORT 문을 사용하여이 동작을 변경할 수 있습니다. SET XACT_ABORT ON이 실행 된 후 런타임 명령문 오류로 인해 현재 트랜잭션이 자동 롤백됩니다. 구문 오류와 같은 컴파일 오류는 SET XACT_ABORT의 영향을받지 않습니다. 자세한 내용은 SET XACT_ABORT (Transact-SQL)를 참조하십시오.

귀하의 경우 삽입 중 하나라도 실패하면 전체 트랜잭션을 롤백합니다.


3
구문 오류를 어떻게 처리해야합니까? 또는 컴파일 오류? 그 사람이 전체 트랜잭션을 발생하는 경우 롤백해야
— MonsterMMORPG

컴파일 / 구문 에러 포착은 SSDT 프로젝트의 목적입니다. :-)
— Joe the Coder

10

삽입 중 하나가 실패하거나 명령의 일부가 실패하면 SQL Server가 트랜잭션을 롤백합니까?

아니 그렇지 않아.

롤백되지 않으면 롤백하기 위해 두 번째 명령을 보내야합니까?

물론, ROLLBACK대신 발행해야합니다 COMMIT.

트랜잭션을 커미트 또는 롤백할지 여부를 결정 COMMIT하려면 명령문 에서 문장을 제거 하고 삽입 결과를 점검 한 후 점검 결과에 따라 COMMIT또는 ROLLBACK결과 를 발행 해야합니다.


오류가 발생하면 "기본 키 충돌"이라고 말하고 롤백을 위해 두 번째 전화를 보내야하나요? 나는 그것이 의미가 있다고 생각한다. 매우 오래 실행되는 SQL 문 동안 연결이 끊어지는 등 네트워크 관련 오류가 발생하면 어떻게됩니까?
— jonathanpeppers 2016

2
연결 시간이 초과되면 기본 네트워크 프로토콜 (예 : Named Pipes또는 TCP)이 연결을 끊습니다. 연결이 끊어지면 SQL Server현재 실행중인 모든 명령을 중지하고 트랜잭션을 롤백합니다.
— Quassnoi

1
DyingCactus의 솔루션은 도움을 주셔서 감사합니다.
— jonathanpeppers 2016

당신이에 중단해야하는 경우 어떤 오류, 다음 네, 이것은 최선의 방법입니다.
— Quassnoi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.