2009-11-17 4 views
141

다음과 같은 SQL Server 2005에서 SQL을 실행하는 클라이언트 응용 프로그램이 있습니다.SQL Server - 트랜잭션 롤백시 오류가 있습니까?

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가 동일하게 응답해야한다고 생각합니다.

+0

http://stackoverflow.com/questions/1150032/what-is-the-benefit-of-using-set-을 xact-abort-on-a-stored-procedure – zloctb

답변

157

을 다음과 같이

당신은 당신이 오류가 발생하는 경우 다시 자동으로 확인 SQL 롤을 만들기 위해 거래하기 전에 set xact_abort on을 넣을 수 TRY CATCH 블록이 포장 할 수 있습니다.

+1

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

+1

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

+0

일반적으로 네트워크 시간 초과 또는 네트워크 오류를 롤백하는 옵션이 있습니까? 또는이 옵션이 모두 하나를 처리합니까? – jonathanpeppers

10

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

아니요.

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

물론, COMMIT 대신 ROLLBACK을 발행해야합니다. 커밋 또는 트랜잭션을 롤백 여부를 결정하려면

, 당신은 문 밖으로 COMMIT 문장을 제거 삽입의 결과를 확인하고 검사 결과에 따라 COMMIT 또는 ROLLBACK 중 하나를 실행해야합니다.

+0

오류가 발생하면 "기본 키 충돌"이라고 말하면서 두 번째 롤백 호출을 보내야합니까?나는 그것이 합리적이라고 생각한다. 장기간 실행되는 SQL 문에서 연결이 끊어지는 것과 같은 네트워크 관련 오류가 발생하면 어떻게됩니까? – jonathanpeppers

+2

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

+1

그래서 DyingCactus의 해결책은 내 문제를 해결하는 것처럼 보입니다. 도움을 주셔서 감사합니다. – jonathanpeppers

154

전체 트랜잭션이 롤백된다는 점이 틀림 없습니다. 다시 롤백하려면 명령을 실행해야합니다.

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 
+1

DyingCactus의 솔루션이 더 마음에 드는데, 그의 코드 줄은 바뀌어야합니다. 만약 당신이 어떤 이유로 든 (또는 더 신뢰할 수있는) 나를 알려주십시오. – jonathanpeppers

+9

try catch를 사용하면 오류를 포착 (가능하면 수정)하고 필요할 경우 사용자 정의 오류 메시지를 발생시킬 수 있습니다. –

+0

SQL 내에서 특별히 오류를 처리하지 않으므로 DyingCactus의 솔루션을 사용하고 있다고 생각합니다. – jonathanpeppers

15

MDSN 기사에서 Controlling Transactions (Database Engine).

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

삽입에 실패하면 전체 트랜잭션을 롤백합니다. 여기

+1

구문 오류를 처리하는 데 필요한 것은 무엇입니까? 또는 컴파일 오류? 그들 중 누군가가 발생하면 전체 트랜잭션을 롤백해야합니다. – MonsterMMORPG

7

2016 MSSQL 서버 작업 오류 메시지 점점 코드 :

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, -- Message text. 
       @ErrorSeverity, -- Severity. 
       @ErrorState -- State. 
       ); 
END CATCH 
+1

DECLARE @Var TYPE; SET @Var = ERROR;'SQL Server 2005에서 raise 오류가 발생합니다. 그렇지 않으면 위의 오류 발생 코드가 이전 DB에서도 작동합니다. 로컬 변수에 기본값을 할당하려고하면 문제가 발생합니다. – jtlindsey

관련 문제