2016-07-19 1 views
1

SQL Server 2014를 사용하고 있으며 ID 및 데이터라는 varchar 열이있는 테이블이있는 간단한 데이터베이스가 있습니다.SP_ExecuteSQL을 사용할 때 트랜잭션이 깨졌습니다.

SET XACT_ABORT ON 
BEGIN TRANSACTION 
    exec sp_executesql N'some nonsense' 
    insert into testTable values ('b') 

COMMIT 

SSMS 내가 sp_executesql 호출에 잘못된 쿼리를 실행하려고하기 때문에 오류가 있음을 보여줍니다 : 나는 다음 문을 실행 몇 가지 이상한 행동이있다. 그러나 1 row(s) affected도 표시됩니다. testTable에서 select 쿼리를 실행하면 값 'b'가 삽입 된 것을 볼 수 있습니다. 나는 TRY/CATCH 블록 모든 일에 문을 포장하는 경우

기대 작품으로, 전체 트랜잭션 작업은 롤백 :

BEGIN TRANSACTION 
BEGIN TRY 
    exec sp_executesql N'some nonsense' 
    insert into testTable values ('b') 

    COMMIT 
END TRY 
BEGIN CATCH 
    SELECT ERROR_MESSAGE() 
    ROLLBACK 
END CATCH 

SET XACT_ABORT ON 뭔가가가는 경우 전체 트랜잭션이 롤백되도록 안 잘못된? 제가 놓친 세팅이 있습니까?

감사

TRY/ CATCH에 싸여 있지 않은 런타임 구문 오류도 ON- XACT_ABORT 세트, 활성 트랜잭션을 중단하지 않기 때문에이 문제가 발생
+2

'어떤 넌센스가 무엇인지에 달려있는 것처럼 보입니다. 컴파일 시간 오류 인 경우 말처럼 행동합니다. 런타임 오류 ('exec sp_executesql N'SELECT 1/0 ''과 같은) 인 경우 원하는 방식으로 동작합니다. –

+0

좋아, 나는 그것이 차이를 만들지 몰랐다. 구문 오류가있어서 설명 할 수 있습니다. 그러나 이것이 왜 그렇게하는지 설명하는 문서가 있습니까? 나는 여전히 전체 트랜잭션이 컴파일 타임 오류 일지라도 롤백 될 것으로 기대합니다. 또는 XACT_ABORT 옵션은 런타임 오류 만 처리합니까? – Pinetree

+0

이전에는이 ​​동작을 알지 못했습니다. 그것이 "설계 상"인지 아닌지 나는 모른다. –

답변

2

. 무엇이 중단되는지, 어떤 상황에서 중단되지 않는지에 대한 정확한 규칙은 전혀 직관적이거나 명확하지 않습니다. Erland Sommarskog는 an excellent write-up on error handling in generalthe rules of what does and doesn't abort in particular입니다.

나는 여기에 모든 것을 재현, 그러나 여기의 필수 요소로 내려 삶은 문제입니다하지 않습니다

SET XACT_ABORT ON -- or OFF, it makes no difference 
BEGIN TRANSACTION 
EXEC ('SELECT')  -- Incorrect syntax near 'SELECT' 
PRINT @@TRANCOUNT -- Prints 1, transaction is still going 
COMMIT 
PRINT @@TRANCOUNT -- Prints 0, transaction succeeded 

XACT_ABORT ON에도 불구하고, 실행이 중지되지 않습니다뿐만 아니라, 거래도 중단되지 않습니다.

SET XACT_ABORT ON 
BEGIN TRANSACTION 
BEGIN TRY 
    EXEC ('SELECT')    -- Incorrect syntax near 'SELECT' 
    PRINT 'After bad statement.' -- Does not print 
    COMMIT 
END TRY 
BEGIN CATCH 
    PRINT @@TRANCOUNT   -- Prints 1, transaction is still going, but it's doomed 
END CATCH 
-- Error here: 
-- 'Uncommittable transaction is detected at the end of the batch. 
-- The transaction is rolled back.' 

지금 트랜잭션이 운명, 그리고 우리가 우리 자신을 롤백하지 않는 경우, SQL 서버 (오류와 함께) 우리를 위해 그것을 않습니다 : 규칙은 TRY/ CATCH를 변경 추가. 이 dooming는 완전히 XACT_ABORT의 예의입니다 다시 한번 수율에게 뭔가 다른 전원을 끈 이유는

SET XACT_ABORT OFF 
BEGIN TRANSACTION 
BEGIN TRY 
    EXEC ('SELECT')    -- Incorrect syntax near 'SELECT' 
    PRINT 'After bad statement.' -- Does not print 
    COMMIT 
END TRY 
BEGIN CATCH 
    PRINT @@TRANCOUNT    -- Prints 1, transaction is still going 
END CATCH 
PRINT @@TRANCOUNT     -- Prints 1, transaction is still going! 
ROLLBACK 

이야기의 교훈은 다음과 T-SQL에서 적절한 오류 처리가 매우 까다 롭습니다. 일반적으로 나를 위해 일하는 것은 평범하지 않은 문에 대해 SET XACT_ABORT ON을 처리하고 클라이언트 코드를 통해 트랜잭션을 시작하고 커밋하거나 SQL Server 외부로 완전히 롤백하는 것입니다. SQL Server가 클라이언트에 다시 전달하는 오류로 인해 결국 롤백이 발생하기 때문에 트랜잭션을 중단 시키거나 중단하지 않는 것을 이해하는 것이 많은 어려움을 피할 수 있습니다. 그러나 물론, 심지어 그것은은 총알이 아닙니다.

관련 문제