Programmingデータベース開発者

ストアドプロシージャ(stored procedures)SQLにおける効果的なエラーハンドリングとデバッグ手順をどのように実装しますか?エラー捕捉とログ記録のためにどのようなメカニズムが用意されていますか?異なるDBMSでこれらのアプローチは異なりますか?

Hintsage AIアシスタントで面接を突破

回答。

ストアドプロシージャでは、特別な構文を使用してエラーを処理することが必要です。

SQL Serverでは、主なメカニズムはTRY...CATCHブロックで、TRY内のすべてのエラーが捕捉され、CATCH内で詳細を記録できます。ERROR_NUMBER()ERROR_MESSAGE()のような関数を使用して詳細情報を取得できます。

BEGIN TRY -- リスクのある操作 UPDATE Accounts SET balance = balance - 100 WHERE id = 1; END TRY BEGIN CATCH INSERT INTO ErrorLog( ErrorTime, ErrorNumber, ErrorMessage, UserName ) VALUES ( GETDATE(), ERROR_NUMBER(), ERROR_MESSAGE(), SUSER_SNAME() ); -- 追加の復旧またはROLLBACK END CATCH

Oracleでは、EXCEPTIONブロックがよく使用されます:

BEGIN UPDATE ...; EXCEPTION WHEN OTHERS THEN INSERT INTO error_log VALUES (..., SQLERRM); END;

覚えておくべきポイント:

  • CATCHで処理できないエラーもある、例えば、パースやコンパイルのエラーは、TRYに入る前にトランザクションを中断させます。
  • 情報をログ記録するためには、エラー用の別のテーブルを持つことが重要です。
  • 可能な限り多くの情報を記録するべきです:エラーメッセージ、番号、ユーザー名、操作のパラメーター。
  • 異なるDBMSでは構文や機能が異なります。

トリックの質問。

CATCHブロック内の例外がエラーのコンテキストを失う可能性がありますか?ネストされたエラーハンドリングを実装する方法は?

回答と例: CATCHブロックでエラーが発生した場合(例えば、ErrorLogテーブルへのアクセス不能など)、元のエラーのコンテキストが失われ、エラーの原因に関する情報も欠落する可能性があります。

対策として、ログ記録を独自のTRY...CATCHを持つ別のプロシージャにカプセル化し、常に「エラーハンドラー内のエラー」をキャッチできるようにします。

BEGIN TRY -- メインコード END TRY BEGIN CATCH EXEC LogError @Error = ERROR_MESSAGE(); END CATCH -- LogErrorプロシージャは自身のTRY...CATCHを含む

逸話

プロジェクト:財務報告。 ストアドプロシージャにTRY...CATCHブロックを追加しましたが、エラーが発生した際のパラメーターをログに記録しませんでした。その結果、重大な障害を捕捉する際にバックアップから手動で状況を探さなければならず、根本原因が明確ではありませんでした。


逸話

プロジェクト:文書管理の自動化(Oracle)。 EXCEPTIONブロックでユーザー名をログに記録するのを忘れました。一週間の調査の結果、誰かが意図的に文書を「壊して」いたことが判明しましたが、監査ログの間接的な証拠によってのみ分かりました。


逸話

プロジェクト:E-commerce。 プロシージャが失敗時にErrorLogにエラーを書き込みました。一度、Logテーブルがトランザクションの拡大によりロックされ、ログ記録の試みがネストされたエラーを引き起こし、元の原因が上書きされてエラースタックがクリアされました。重大な障害用の追加テーブルと多層ログ記録を導入して修正しました。