TRY...CATCH(Transact-SQL)
적용 대상: Microsoft Fabric의 Microsoft Fabric SQL 데이터베이스에 있는 Microsoft Fabric Warehouse의 SQL Server Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System(PDW) SQL 분석 엔드포인트
C# 및 Visual C++ 언어의 예외 처리와 유사한 Transact-SQL에 대한 오류 처리를 구현합니다. Transact-SQL 문 그룹은 블록으로 TRY
묶을 수 있습니다. 블록에서 TRY
오류가 발생하면 컨트롤은 일반적으로 블록으로 묶 CATCH
인 다른 문 그룹에 전달됩니다.
구문
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
인수
sql_statement
Transact-SQL 문입니다.
statement_block
일괄 처리 또는 블록으로 묶 BEGIN...END
인 Transact-SQL 문의 모든 그룹입니다.
설명
구문은 TRY...CATCH
데이터베이스 연결을 닫지 않는 심각도가 10보다 높은 모든 실행 오류를 catch합니다.
TRY
블록 바로 뒤에 연결된 CATCH
블록이 있어야 합니다. 문과 BEGIN CATCH
문 사이에 END TRY
다른 문을 포함하면 구문 오류가 발생합니다.
구문은 TRY...CATCH
여러 일괄 처리에 걸쳐 있지 않습니다. 구문은 TRY...CATCH
Transact-SQL 문의 여러 블록에 걸쳐 있지 않습니다. 예를 들어 구문은 TRY...CATCH
Transact-SQL 문의 두 BEGIN...END
블록에 걸쳐 있지 않으며 구문을 확장 IF...ELSE
할 수 없습니다.
블록에 묶 TRY
인 코드에 오류가 없는 경우 블록의 마지막 문이 TRY
완료되면 연결된 END CATCH
문 바로 다음에 컨트롤이 문으로 전달됩니다.
블록에 묶 TRY
인 코드에 오류가 있으면 컨트롤이 연결된 CATCH
블록의 첫 번째 문으로 전달됩니다. 블록의 코드가 CATCH
완료되면 제어가 문 바로 다음 문으로 END CATCH
전달됩니다.
참고 항목
END CATCH
문이 저장 프로시저 또는 트리거의 마지막 문인 경우 컨트롤은 저장 프로시저를 호출하거나 트리거를 발생시킨 문으로 다시 전달됩니다.
블록에 의해 CATCH
트래핑된 오류는 호출 애플리케이션에 반환되지 않습니다. 오류 정보의 일부를 애플리케이션에 반환해야 하는 경우 블록의 CATCH
코드는 결과 집합 또는 RAISERROR
문과 PRINT
같은 SELECT
메커니즘을 사용하여 반환해야 합니다.
TRY...CATCH
구문을 중첩할 수 있습니다. TRY
블록 또는 블록은 CATCH
중첩된 TRY...CATCH
구문을 포함할 수 있습니다. 예를 들어 블록에는 CATCH
코드에서 발생하는 오류를 처리하는 포함된 TRY...CATCH
구문이 CATCH
포함될 수 있습니다.
블록에서 CATCH
발생한 오류는 다른 곳에서 생성된 오류처럼 처리됩니다. 블록에 CATCH
중첩 구 TRY...CATCH
문이 포함된 경우 중첩된 TRY
블록의 오류는 중첩된 CATCH
블록에 컨트롤을 전달합니다. 중첩된 TRY...CATCH
구문이 없으면 오류가 호출자에게 다시 전달됩니다.
TRY...CATCH
는 블록의 코드 TRY
에 의해 실행되는 저장 프로시저 또는 트리거에서 처리되지 않은 오류를 catch합니다. 또는 저장 프로시저 또는 트리거에 코드에서 생성된 오류를 처리하기 위한 자체 TRY...CATCH
구문을 포함할 수 있습니다. 예를 들어 블록이 TRY
저장 프로시저를 실행하고 저장 프로시저에서 오류가 발생하면 다음과 같은 방법으로 오류를 처리할 수 있습니다.
저장 프로시저에 자체
TRY...CATCH
구문이 없는 경우 오류는 문이 포함된 블록과 연결된 블록에TRY
컨트롤CATCH
을EXECUTE
반환합니다.저장 프로시저에 구문이
TRY...CATCH
포함된 경우 오류는 저장 프로시저의CATCH
블록으로 컨트롤을 전송합니다. 블록 코드가CATCH
완료되면 저장 프로시저를 호출한 문 바로 후에EXECUTE
컨트롤이 문으로 다시 전달됩니다.
GOTO
문을 사용하여 입력 TRY
하거나 CATCH
차단할 수 없습니다. GOTO
문을 사용하여 같은 TRY
레이블 또는 블록 내의 레이블로 이동하거나 CATCH
또는 블록을 떠날 TRY
CATCH
수 있습니다.
사용자 정의 함수에서는 구 TRY...CATCH
문을 사용할 수 없습니다.
오류 정보 검색
블록 범위 CATCH
에서 다음 시스템 함수를 사용하여 블록을 실행한 CATCH
오류에 대한 정보를 가져올 수 있습니다.
함수 | 설명 |
---|---|
ERROR_NUMBER | 오류 수를 반환합니다. |
ERROR_SEVERITY | 심각도를 반환합니다. |
ERROR_STATE | 오류 상태 번호를 반환합니다. |
ERROR_PROCEDURE | 오류가 발생한 저장 프로시저 또는 트리거의 이름을 반환합니다. |
ERROR_LINE | 오류를 발생시킨 루틴 내의 줄 번호를 반환합니다. |
ERROR_MESSAGE | 오류 메시지의 전체 텍스트를 반환합니다. 이 텍스트는 길이, 개체 이름 또는 시간과 같은 대체 가능한 매개 변수에 제공된 값을 포함합니다. |
이러한 함수는 블록 범위 외부에서 호출되는 경우 반환 NULL
됩니다 CATCH
. 오류 정보는 블록 범위 CATCH
내의 어디에서나 이러한 함수를 사용하여 검색할 수 있습니다. 예를 들어 다음 스크립트는 오류 처리 함수를 포함하는 저장 프로시저를 보여 줍니다. CATCH
구문의 TRY...CATCH
블록에서 이 저장 프로시저를 호출하면 오류에 대한 정보가 반환됩니다.
-- Verify that the stored procedure does not already exist.
IF OBJECT_ID('usp_GetErrorInfo', 'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
GO
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1 / 0;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
함수는 ERROR_*
고유하게 컴파일된 저장 프로시저 내의 블록에서도 CATCH
작동합니다.
TRY의 영향을 받지 않는 오류... CATCH 구문
TRY...CATCH
구문은 다음 조건을 트래핑하지 않습니다.
심각도가 10 이하인 경고 또는 정보 메시지
해당 세션에 대한 SQL Server 데이터베이스 엔진 태스크 처리를 중지하게 만드는 심각도 20 이상의 오류. 심각도가 20 이상이고 데이터베이스 연결이 중단
TRY...CATCH
되지 않는 오류가 발생하면 오류를 처리합니다.클라이언트 인터럽트 요청 또는 클라이언트 연결 끊김과 같은 주의
시스템 관리자가 문을 사용하여
KILL
세션을 종료하는 경우
다음 유형의 오류는 구문과 동일한 실행 수준에서 TRY...CATCH
발생하는 경우 블록에서 처리 CATCH
되지 않습니다.
구문 오류와 같이 일괄 처리의 실행을 막는 컴파일 오류
문 수준 다시 컴파일 단계에서 발생한 오류(예: 컴파일 이후에 지연된 이름 확인으로 발생한 개체 이름 확인 오류)
개체 이름 확인 오류
이런 오류는 해당 일괄 처리, 저장 프로시저 또는 트리거를 실행한 수준으로 반환됩니다.
블록 내에서 TRY
더 낮은 실행 수준(예: 실행 sp_executesql
중 또는 사용자 정의 저장 프로시저)에서 컴파일 또는 문 수준 다시 컴파일 중에 오류가 발생하는 경우 오류는 구문보다 TRY...CATCH
낮은 수준에서 발생하며 연결된 CATCH
블록에서 처리됩니다.
다음 예제에서는 문에서 생성한 개체 이름 확인 오류가 구문에 SELECT
의해 TRY...CATCH
catch되지 않고 저장 프로시저 내에서 동일한 SELECT
문이 실행될 때 블록에 의해 CATCH
catch되는 방법을 보여 드립니다.
BEGIN TRY
-- Table does not exist; object name resolution
-- error not caught.
SELECT *
FROM NonexistentTable;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH
오류가 catch되지 않고 컨트롤이 TRY...CATCH
구문에서 다음 상위 수준으로 전달됩니다.
SELECT
저장 프로시저 내에서 문을 실행하면 블록보다 TRY
낮은 수준에서 오류가 발생합니다. 이 오류는 구문에 TRY...CATCH
의해 처리됩니다.
-- Verify that the stored procedure does not exist.
IF OBJECT_ID(N'usp_ExampleProc', N'P') IS NOT NULL
DROP PROCEDURE usp_ExampleProc;
GO
-- Create a stored procedure that will cause an
-- object resolution error.
CREATE PROCEDURE usp_ExampleProc
AS
SELECT *
FROM NonexistentTable;
GO
BEGIN TRY
EXECUTE usp_ExampleProc;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
커밋할 수 없는 트랜잭션 및 XACT_STATE
블록에서 TRY
생성된 오류로 인해 현재 트랜잭션의 상태가 무효화되면 트랜잭션은 커밋할 수 없는 트랜잭션으로 분류됩니다. 일반적으로 블록 외부 TRY
의 트랜잭션을 종료하는 오류로 인해 블록 내에서 TRY
오류가 발생할 때 트랜잭션이 커밋할 수 없는 상태가 됩니다. 커밋할 수 없는 트랜잭션은 읽기 작업 또는 ROLLBACK TRANSACTION
. 트랜잭션은 쓰기 작업 또는 COMMIT TRANSACTION
를 생성하는 Transact-SQL 문을 실행할 수 없습니다. 이 함수는 XACT_STATE
트랜잭션이 커밋할 수 없는 트랜잭션으로 분류된 경우의 -1
값을 반환합니다. 일괄 처리가 완료되면 데이터베이스 엔진은 커밋 불가능 활성 트랜잭션을 모두 롤백합니다. 트랜잭션이 커밋할 수 없는 상태가 될 때 오류 메시지가 전송되지 않은 경우 일괄 처리가 완료되면 클라이언트 애플리케이션에 오류 메시지가 전송됩니다. 이 메시지는 커밋 불가능 트랜잭션이 검색되어 롤백되었음을 보여 줍니다.
커밋할 수 없는 트랜잭션 및 XACT_STATE
함수에 대한 자세한 내용은 XACT_STATE 참조하세요.
예제
A. TRY 사용... 잡기
다음 예에서는 0으로 나누기 오류를 일으키는 SELECT
문을 보여 줍니다. 이 오류로 인해 연결된 CATCH
블록으로 실행이 이동합니다.
BEGIN TRY
-- Generate a divide-by-zero error.
SELECT 1 / 0;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
B. TRY 사용... 트랜잭션의 CATCH
다음 예에서는 트랜잭션 내에서 TRY...CATCH
블록이 작동하는 방법을 보여 줍니다. TRY
블록 내의 문은 제약 조건 위반 오류를 일으킵니다.
BEGIN TRANSACTION;
BEGIN TRY
-- Generate a constraint violation error.
DELETE
FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO
C. TRY 사용... CATCH with XACT_STATE
다음 예에서는 트랜잭션 내부에서 발생하는 오류를 TRY...CATCH
구문을 사용하여 처리하는 방법을 보여 줍니다. 트랜잭션을 커밋해야 하는지 또는 롤백해야 하는지는 XACT_STATE
함수가 결정합니다. 이 예에서 SET XACT_ABORT
는 ON
입니다. 이렇게 하면 제약 조건 위반 오류가 발생할 경우 트랜잭션을 커밋할 수 없습니다.
-- Check to see whether this stored procedure exists.
IF OBJECT_ID(N'usp_GetErrorInfo', N'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_LINE() AS ErrorLine,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_MESSAGE() AS ErrorMessage;
GO
-- SET XACT_ABORT ON will cause the transaction to be uncommittable
-- when the constraint violation occurs.
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
-- A FOREIGN KEY constraint exists on this table. This
-- statement will generate a constraint violation error.
DELETE
FROM Production.Product
WHERE ProductID = 980;
-- If the DELETE statement succeeds, commit the transaction.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
-- Test XACT_STATE:
-- If 1, the transaction is committable.
-- If -1, the transaction is uncommittable and should
-- be rolled back.
-- XACT_STATE = 0 means that there is no transaction and
-- a commit or rollback operation would generate an error.
-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT N'The transaction is in an uncommittable state. Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
-- Test whether the transaction is committable.
-- You may want to commit a transaction in a catch block if you want to commit changes to statements that ran prior to the error.
IF (XACT_STATE()) = 1
BEGIN
PRINT N'The transaction is committable. Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
GO
관련 콘텐츠
- THROW(Transact-SQL)
- 데이터베이스 엔진 오류 심각도
- ERROR_LINE(Transact-SQL)
- ERROR_MESSAGE(Transact-SQL)
- ERROR_NUMBER(Transact-SQL)
- ERROR_PROCEDURE(Transact-SQL)
- ERROR_SEVERITY(Transact-SQL)
- ERROR_STATE(Transact-SQL)
- RAISERROR(Transact-SQL)
- @@ERROR(Transact-SQL)
- GOTO(Transact-SQL)
- BEGIN...END(Transact-SQL)
- XACT_STATE(Transact-SQL)
- SET XACT_ABORT(Transact-SQL)