TRY...CATCH (Transact-SQL)
Applies to: SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Analytics Platform System (PDW)
Microsoft Fabric の SQL 分析エンドポイント
Microsoft Fabric のウェアハウス
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
[ ; ]
Note
SQL Server 2014 (12.x) 以前のバージョンの Transact-SQL 構文を確認するには、以前のバージョンのドキュメントを参照してください。
引数
sql_statement
Transact-SQL ステートメント。
statement_block
バッチ内または BEGIN...END
ブロックで囲まれた Transact-SQL ステートメントの任意のグループ。
解説
TRY...CATCH
コンストラクトは、データベース接続を閉じない重大度が 10 を超えるすべての実行エラーをキャッチします。
TRY
ブロックの直後に、関連付けられているCATCH
ブロックが続く必要があります。 END TRY
ステートメントと BEGIN CATCH
ステートメントの間に他のステートメントを含めると、構文エラーが発生します。
TRY...CATCH
コンストラクトは複数のバッチにまたがることができます。 TRY...CATCH
コンストラクトは、Transact-SQL ステートメントの複数のブロックにまたがることができます。 たとえば、 TRY...CATCH
コンストラクトは、Transact-SQL ステートメントの 2 つの BEGIN...END
ブロックにまたがることはできません。またがって、 IF...ELSE
コンストラクトにまたがることはありません。
TRY
ブロックで囲まれたコードにエラーがない場合、TRY
ブロック内の最後のステートメントが終了すると、関連付けられている END CATCH
ステートメントの直後にコントロールがステートメントに渡されます。
TRY
ブロックで囲まれたコードにエラーが発生した場合、コントロールは関連付けられたCATCH
ブロック内の最初のステートメントに渡されます。 CATCH
ブロック内のコードが終了すると、END CATCH
ステートメントの直後にコントロールがステートメントに渡されます。
Note
END CATCH
ステートメントがストアド プロシージャまたはトリガーの最後のステートメントである場合は、ストアド プロシージャを呼び出したステートメントまたはトリガーを起動したステートメントに制御が戻されます。
CATCH
ブロックによってトラップされたエラーは、呼び出し元のアプリケーションには返されません。 エラー情報の一部をアプリケーションに返す必要がある場合、 CATCH
ブロック内のコードは、 SELECT
結果セットや RAISERROR
ステートメントや PRINT
ステートメントなどのメカニズムを使用して返す必要があります。
TRY...CATCH
コンストラクトを入れ子にすることができます。 TRY
ブロックまたはCATCH
ブロックには、入れ子になったTRY...CATCH
コンストラクトを含めることができます。 たとえば、CATCH
ブロックには、CATCH
コードで発生したエラーを処理する埋め込みTRY...CATCH
コンストラクトを含めることができます。
CATCH
ブロックで発生したエラーは、他の場所で生成されたエラーと同様に扱われます。 CATCH
ブロックに入れ子になったTRY...CATCH
コンストラクトが含まれている場合、入れ子になったTRY
ブロック内のエラーは、入れ子になったCATCH
ブロックに制御を渡します。 入れ子になった TRY...CATCH
コンストラクトがない場合、エラーは呼び出し元に返されます。
TRY...CATCH
コンストラクトは、 TRY
ブロック内のコードによって実行されるストアド プロシージャまたはトリガーからハンドルされないエラーをキャッチします。 または、ストアド プロシージャまたはトリガーに独自の TRY...CATCH
コンストラクトを含め、コードによって生成されたエラーを処理することもできます。 たとえば、 TRY
ブロックがストアド プロシージャを実行し、ストアド プロシージャでエラーが発生した場合、エラーは次の方法で処理できます。
ストアド プロシージャに独自の
TRY...CATCH
コンストラクトが含まれていない場合、エラーは、EXECUTE
ステートメントを含むTRY
ブロックに関連付けられているCATCH
ブロックに制御を返します。ストアド プロシージャに
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 | エラー メッセージの完全なテキストを返します。 このテキストには、長さ、オブジェクト名、回数など、置き換え可能なパラメーターに提供される値が含まれます。 |
これらの関数は、CATCH
ブロックのスコープ外で呼び出された場合、NULL
を返します。 エラー情報は、 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 以下の警告または情報メッセージ。
重大度が 20 以上で、そのセッションの SQL Server データベース エンジン タスク処理を終了させるエラー。 重大度が 20 以上のエラーが発生し、データベース接続が中断されない場合は、
TRY...CATCH
がエラーを処理します。クライアントの割り込み要求や中断されたクライアント接続などのアテンション。
システム管理者が
KILL
ステートメントを使用してセッションを終了する場合。
次の種類のエラーは、TRY...CATCH
コンストラクトと同じ実行レベルで発生した場合、CATCH
ブロックでは処理されません。
構文エラーなど、バッチの実行を妨げるコンパイル エラー。
ステートメントレベルの再コンパイルで発生するエラー (コンパイル後の名前の遅延解決により発生するオブジェクト名の解決エラーなど)。
オブジェクト名解決エラー
これらのエラーは、バッチ、ストアド プロシージャ、またはトリガーを実行したレベルに返されます。
コンパイル中またはステートメント レベルの再コンパイル中に、TRY
ブロック内のより低い実行レベル (たとえば、sp_executesql
またはユーザー定義ストアド プロシージャの実行時) でエラーが発生した場合、エラーはTRY...CATCH
コンストラクトよりも低いレベルで発生し、関連付けられているCATCH
ブロックによって処理されます。
次の例は、SELECT
ステートメントによって生成されたオブジェクト名解決エラーがTRY...CATCH
コンストラクトによってキャッチされず、ストアド プロシージャ内で同じSELECT
ステートメントが実行されたときに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
エラーはキャッチされず、制御は 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...CATCH を使用する
次の例は、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)