SQLの産業用ソリューションは、適切なエラー処理のアーキテクチャを必要とします。ロギングや精密な例外処理なしでは、特にストアドプロシージャやバッチスクリプトにおいて、複雑なプロセスをデバッグすることは不可能です。
問題の背景: 標準SQLは最小限のエラー処理を許可しています(例えば、RETURNや処理の中断)。現代的な拡張(T-SQL、PL/pgSQL、PL/SQLなど)は、フル機能のエラー処理構文(TRY/CATCH、EXCEPTION)を提供しています。
問題点: 明示的にエラーを処理しないと、原因を特定するのが難しく、特に大量の変更や外部システムとの連携時に問題が発生します。エラーを別のテーブルにロギングする必要があることが多いです。
解決策: TRY/CATCH(T-SQL)またはEXCEPTION(PL/pgSQL)を使用し、独自のログテーブルを持ちましょう。また、エラーログに診断情報(エラーコード、エラーメッセージ、リクエストパラメータ、日時)を送信することを忘れないでください。
コード例(T-SQL、MS SQL Server):
CREATE TABLE ErrorLog ( ErrorId INT IDENTITY PRIMARY KEY, ErrorTime DATETIME, ProcedureName NVARCHAR(128), ErrorMessage NVARCHAR(MAX), ErrorNumber INT, ErrorState INT, ErrorSeverity INT ); CREATE PROCEDURE usp_ProcessOrders AS BEGIN BEGIN TRY -- ビジネスロジック UPDATE Orders SET Status = 'PROCESSED' WHERE Status = 'NEW'; END TRY BEGIN CATCH INSERT INTO ErrorLog ( ErrorTime, ProcedureName, ErrorMessage, ErrorNumber, ErrorState, ErrorSeverity ) VALUES ( GETDATE(), ERROR_PROCEDURE(), ERROR_MESSAGE(), ERROR_NUMBER(), ERROR_STATE(), ERROR_SEVERITY() ); THROW; END CATCH END
コード例(PL/pgSQL、PostgreSQL):
BEGIN -- あなたのコード EXCEPTION WHEN OTHERS THEN INSERT INTO error_log(ts, proc_name, err_text) VALUES(now(), 'my_proc', SQLERRM); RAISE; END;
主な特徴:
エラーを捕捉して処理を終了するだけで、情報を外に出さなくていいですか?
いいえ。明示的なロギングやエラーの伝播なしでは、障害の原因を捕捉・分析することはできません。エラーをログに詳細に記述するか、少なくとも次の処理に渡す(THROW/RAISE)ことが重要です。
ユーザー定義プロシージャ内のすべてのエラーを特定するために、専用のSQL Server/DBMSログを使用するだけでいいですか?
一部のみ。多くのエラーはサーバーログに記録されないため、アプリケーションやプロシージャ内で"捕獲"して処理する必要があります。ビジネスロジックにおいて、詳細を持つ独自のイベントログを維持することが有用です。
単純なDML操作だけが使用されるプロシージャで、TRY/CATCH(またはEXCEPTION)を使用することが義務ですか?
重要なデータに影響を与え、重要なチェーンに参加し、異常な状況を記録する必要がある場合、必ず必要です。たとえ"安全な"操作でも、外部制約(ユニーク性、FOREIGN KEY、デッドロックなど)によりエラーが発生する可能性があります。
プロジェクトではエラーをロギングせず、ユーザーにのみ表示します。大量にエラーが発生した際に、管理者は"見えない"問題を数時間探し回ります。
利点:
欠点:
すべての重大なエラーは、(日時、プロシージャ、パラメーター、エラーコードなどの詳細とともに)ログテーブルに記録され、システムのチケットに参照されます。
利点:
欠点: