本節では、埋め込みSQLプログラムにおいて、例外条件や警告をどのように扱うことができるかについて説明します。このために、共に使用できる2つの機能があります。WHENEVERコマンドを使用して、警告条件、エラー条件を扱うようにコールバックを設定することができます。エラーまたは警告に関する詳細情報はsqlca変数から入手することができます。コールバックの設定エラーや警告を受け取る簡単な手法の1つは、特定の条件が発生する度に特定の動作を実行するように設定することです。一般的には以下のようになります。action;conditionは以下のいずれかを取ることができます。SQLERRORSQL文の実行中にエラーが発生する度に、指定した動作が呼び出されます。SQLWARNINGSQL文の実行中に警告が発生する度に、指定した動作が呼び出されます。FOUNDSQL文が0行を受け取る、もしくは0行に影響する時、指定した動作が呼び出されます。(この条件はエラーではありませんが、これを特別に扱いたい場合があります。)actionは以下のいずれかを取ることができます。CONTINUEこれは、実際のところ、その条件が無視されることを意味します。これがデフォルトです。(Cのgoto文を使用します)。SQLPRINT標準エラーにメッセージを出力します。これは、単純なプログラムやプロトタイプ作成時に役に立ちます。メッセージの詳細は設定できません。STOPプログラムを終了させるexit(1)を呼び出します。BREAKCのbreak文を実行します。これはループ内、もしくはswitch文内でのみ使用しなければなりません。CONTINUECのcontinue文を実行します。これはループ文の中でのみ実行すべきものです。実行した場合、制御の流れがループの先頭に戻ります。(args)指定した引数で、指定したC関数を呼び出します。(この使用法は通常のPostgreSQL構文でのCALLおよびDOとは意味が異なります。TO)のみを提供しています。簡単なプログラムで使用してみたくなるような例を以下に示します。警告が発生した場合に簡単なメッセージを表示し、エラーが発生した場合にプログラムを中断します。WHENEVER文はCの構文ではなく、SQLプリプロセッサのディレクティブです。WHENEVERと条件を発生させたSQL文の間で、同一条件に異なる動作が設定されない限り、ハンドラを設定した箇所より後にある、すべての埋め込みSQL文に適用されます。Cプログラムの制御フローは関係しません。以下の2つのCプログラムの抜粋はどちらも望み通りの動作を行いません。sqlcaより強力にエラーを扱うために、埋め込みSQLインタフェースは以下の構造体を持つsqlca(SQL通信領域)という名前のグローバル変数を提供します。sqlca;(マルチスレッド化されたプログラムでは、各スレッドは自動的にsqlcaのコピーを独自に持ちます。これは標準Cのerrnoグローバル変数の扱いと同様に動作します。)sqlcaは警告とエラーの両方を対象としています。1つのSQL文の実行時に複数の警告やエラーが発生した場合、sqlcaは最後のものに関した情報のみを含みます。直前のSQL文でエラーがなければ、sqlca.sqlcodeは0に、sqlca.sqlstateは"00000"になります。警告やエラーが発生した場合は、sqlca.sqlcodeは負の値に、sqlca.sqlstateは"00000"以外になります。正のsqlca.sqlcodeは、直前の問い合わせが0行を返したなどの無害な条件を示します。sqlca.sqlcodeとsqlca.sqlstateは2つの異なるエラーコードスキームです。後で詳細に説明します。直前のSQL文が成功すると、sqlca.sqlerrd[1]は処理された行のOIDが、もしあれば、格納されます。そのコマンドで適切ならば、sqlca.sqlerrd[2]は処理された、もしくは返された行数が格納されます。エラーもしくは警告の場合、sqlca.sqlerrm.sqlerrmcには、そのエラーを説明する文字列が格納されます。(strlen()の結果です。Cプログラマは必要としないでしょう)。一部のメッセージは固定長のsqlerrmc配列には長過ぎることに注意してください。この場合は切り詰められます。(他のすべての場合では、これはW以外の何かに設定されます)。sqlca.sqlwarn[1]がWに設定された場合、ホスト変数に代入する際に値が切り詰められています。他の要素が警告を示すように設定された場合、sqlca.sqlwarn[0]はWに設定されます。今のところ、sqlcaid、sqlabc、sqlerrpならびにsqlerrdとsqlwarnの上記以外の要素は有用な情報を持ちません。sqlcaは標準SQLでは定義されていません。複数の他のSQLデータベースシステムで実装されています。その定義は基本部分は似ていますが、移植性を持つアプリケーションを作成する場合は実装の違いを注意して調査しなければなりません。ここでWHENEVERとsqlcaを組み合わせて使用して、エラーが発生した時にsqlcaの内容を表示する、1つの例を示します。これはおそらく、より「ユーザ向け」のエラー処理を組み込む前の、アプリケーションのデバッグまたはプロトタイプで有用です。"===============\n");}結果は以下のようになります(ここでのエラーはテーブル名の誤記述によるものです。SQLSTATE対SQLCODEsqlca.sqlstateとsqlca.sqlcodeはエラーコードを提供する異なる2つの機構です。共に標準SQLから派生されたものですが、SQLCODEはSQL-92版では廃れたものとされ、以降の版から削除されました。したがって、新規アプリケーションではSQLSTATEを使用することを強く勧めます。SQLSTATEは5要素の文字配列です。この5文字は、各種のエラー条件、警告条件のコードを表現する数字、大文字から構成されます。SQLSTATEは階層を持った機構です。最初の2文字は条件を汎化したクラスを示し、残り3文字は汎化クラスの副クラスを示します。成功状態は00000というコードで示されます。SQLSTATEコードのほとんどは標準SQLで定義されています。PostgreSQLサーバは本質的にSQLSTATEエラーコードをサポートしています。したがって、すべてのアプリケーションでこのエラーコードを使用することで、高度な一貫性を達成することができます。詳細については付録Aを参照してください。廃止されたエラーコードの機構であるSQLCODEは単なる整数です。0という値は成功を意味し、正の値は追加情報を持った成功を、負の値はエラーを示します。標準SQLでは、直前のコマンドが0行を返す、もしくは0行に影響したことを示す+100という正の値のみを定義しています。負の値は規定されていません。したがって、この機構では低い移植性しか達成できず、また、コード体系も階層を持っていません。歴史的に、PostgreSQLの埋め込みSQLプロセッサには、いくつかの特殊なSQLCODEの値が専用に割り当てられていました。以下に、その数値とそのシンボル名の一覧を示します。これらは他のSQL実装への移植性がないことを忘れないでください。アプリケーションのSQLSTATE機構への移行を簡易化するために、対応するSQLSTATEも示しています。(実際は多対多です)。場合ごとに付録Aに示したグローバルな各SQLSTATEを参照しなければなりません。以下は割り当て済みのSQLCODEです。(ECPG_NO_ERROR)エラーがないことを示す。(ECPG_NOT_FOUND)これは、最後に実行したコマンドが取り出した、または、処理した行がゼロ行であったこと、あるいは、カーソルの最後であることを示す、害のない条件です。02000)以下のように、カーソルをループ内で処理する時、ループを中断する時を検知する方法として、このコードを使用することができます。BREAKはこれを内部で効率的に行います。このため、通常、外部で明示的に記述する利点はありません。(ECPG_OUT_OF_MEMORY)仮想メモリ不足を示します。この数値は-ENOMEMとして定義します。(ECPG_UNSUPPORTED)ライブラリが把握していない何かをプリプロセッサが生成したことを示します。互換性がないプリプロセッサとライブラリのバージョンを使用しています。(ECPG_TOO_MANY_ARGUMENTS)コマンドの想定より多くのホスト変数が指定されたことを意味します。(ECPG_TOO_FEW_ARGUMENTS)コマンドの想定よりも少ないホスト変数が指定されたことを意味します。(例えば、指定された変数が配列ではなかった)。(ECPG_INT_FORMAT)ホスト変数の型がintですが、データベース内のデータ型が異なり、その値をintとして解釈させることができませんでした。ライブラリはこの変換にstrtol()を使用します。intとして解釈させることができませんでした。ライブラリはこの変換にstrtoul()を使用します。(ECPG_FLOAT_FORMAT)ホスト変数の型がfloatですが、データベース内のデータ型が異なり、その値をfloatとして解釈させることができませんでした。ライブラリはこの変換にstrtod()を使用します。(ECPG_NUMERIC_FORMAT)ホスト変数の型がnumericですが、データベース内のデータ型が異なり、その値をnumericとして解釈させることができませんでした。(ECPG_INTERVAL_FORMAT)ホスト変数の型がintervalであり、データベース内のデータが他の型であり、interval値として解釈することができない値を含みます。(ECPG_DATE_FORMAT)ホスト変数の型がdateであり、データベース内のデータが他の型であり、date値として解釈することができない値を含みます。(ECPG_TIMESTAMP_FORMAT)ホスト変数の型がtimestampであり、データベース内のデータが他の型であり、timestamp値として解釈することができない値を含みます。(ECPG_CONVERT_BOOL)これは、ホスト変数の型がboolですが、データベース内のデータが't'でも'f'でもなかったことを意味します。(通常埋め込みSQLプログラムでは発生しません。これは内部エラーを示しているかもしれません)。(ECPG_MISSING_INDICATOR)NULL値が返されましたが、NULL用の指示子変数が与えられていませんでした。(ECPG_NO_ARRAY)配列が必要な箇所に普通の変数が使用されていました。(ECPG_DATA_NOT_ARRAY)配列値が必要な箇所にデータベースが普通の変数を返しました。(ECPG_ARRAY_INSERT)値を配列に挿入できません。(ECPG_NO_CONN)存在しない接続にプログラムがアクセスしようとしました。(これは内部エラーです)。(ECPG_INVALID_STMT)使用しようとしたSQL文がプリペアされていませんでした。(Informix互換モード)。(ECPG_UNKNOWN_DESCRIPTOR)指定した記述子が見つかりませんでした。使用しようとしたSQL文はプリペアされていませんでした。(ECPG_INVALID_DESCRIPTOR_INDEX)記述子のインデックスが範囲外でした。(ECPG_UNKNOWN_DESCRIPTOR_ITEM)無効な記述子項目が要求されました。(これは内部エラーです。(ECPG_VAR_NOT_NUMERIC)動的なSQL文の実行時にデータベースが数値を返しましたが、ホスト変数が数値でありませんでした。(ECPG_VAR_NOT_CHAR)動的なSQL文の実行時にデータベースが数値以外を返しましたが、ホスト変数が数値でした。(ECPG_INFORMIX_SUBSELECT_NOT_ONE)副問い合わせの結果が単一行ではありません(Informix互換モード)。(ECPG_PGSQL)PostgreSQLサーバで何らかのエラーが発生しました。このメッセージはPostgreSQLサーバからのエラーメッセージを含みます。(ECPG_TRANS)PostgreSQLサーバがトランザクションのコミットやロールバックを始めることができないことを通知しました。(ECPG_CONNECT)データベースへの接続試行に失敗しました。(ECPG_SUBSELECT_NOT_ONE)副問い合わせの結果が単一行ではありません。(ECPG_WARNING_UNKNOWN_PORTAL)無効なカーソル名が指定されました。(ECPG_WARNING_IN_TRANSACTION)トランザクションが進行中です。(ECPG_WARNING_NO_TRANSACTION)活動中(進行中)のトランザクションがありません。(ECPG_WARNING_PORTAL_EXISTS)既存のカーソル名が指定されました。