ORA-06592: CASE not found while executing CASE statement は、PL/SQLの CASE文 で、どの WHEN にも一致せず、ELSE もないまま実行された時に発生するエラーです。事前定義例外名では CASE_NOT_FOUND として扱えます。
SQLの CASE式 では、ELSEがない場合に NULL を返す場面があります。しかしPL/SQLの CASE文 は処理分岐なので、実行する文が見つからないと例外になります。この違いを混同すると、ORA-06592でつまずきやすくなります。
ORA-06592が出たら、まずPL/SQLの
CASE に ELSE があるか確認します。何もしないのが正しいなら ELSE NULL;、不正値として止めたいなら ELSE RAISE_APPLICATION_ERROR(...) を入れます。発生行は ORA-06512 で追い、CASEの基本は OracleのCASE式ガイド も参考にしてください。ORA-06592とは
ORA-06592は、PL/SQLのCASE文が実行する分岐を見つけられなかったことを示します。Oracle公式のCASE文ドキュメントでも、simple CASE statementやsearched CASE statementが条件に応じて文を実行する仕組みとして説明されています。どの条件にも該当せず、ELSEもなければ、実行する文が存在しません。
またOracleの事前定義例外一覧では、CASE_NOT_FOUND が ORA-06592 に対応する例外として定義されています。そのため、例外処理では WHEN CASE_NOT_FOUND THEN として捕捉できます。
| 種類 | 使う場所 | ELSEなしで一致しない場合 |
|---|---|---|
SQLのCASE式 |
SELECT、ORDER BY、UPDATEなど | NULL になり得る |
PL/SQLのCASE文 |
BEGIN-END内の処理分岐 | ORA-06592 / CASE_NOT_FOUND |
IF文 |
PL/SQLの条件分岐 | 該当しない分岐は単に実行されない |
CASE_NOT_FOUND |
PL/SQL例外 | ORA-06592に対応する事前定義例外 |
ELSEなしの基本例
次の例では、p_status が A でも I でもない場合に、どの分岐にも一致せずORA-06592になります。
DECLARE
l_status VARCHAR2(1) := 'X';
BEGIN
CASE l_status
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN 'I' THEN
DBMS_OUTPUT.PUT_LINE('無効');
END CASE;
END;
/
-- ORA-06592: CASE not found while executing CASE statement
テストデータでは A と I しか来なかったとしても、本番で未知のコードやNULLが来ると落ちます。CASE文には「想定外をどう扱うか」を明示しておくのが安全です。
ELSE NULLで何もしない
想定外の値では何も処理しないのが正しいなら、ELSE NULL; を書きます。PL/SQLでは NULL; は何もしない文として使えます。
DECLARE
l_status VARCHAR2(1) := 'X';
BEGIN
CASE l_status
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN 'I' THEN
DBMS_OUTPUT.PUT_LINE('無効');
ELSE
NULL;
END CASE;
END;
/
ただし、ELSE NULL はエラーを隠す実装にもなります。未知の値が本来あり得ないなら、黙って無視するより明示的にエラーにする方が調査しやすいです。
RAISE_APPLICATION_ERRORで不正値を示す
業務コードや状態値が想定外なら、RAISE_APPLICATION_ERROR で原因が分かるメッセージを返す方法が向いています。ORA-06592のままでは、どの値が想定外だったのか分かりにくいためです。
DECLARE
l_status VARCHAR2(1) := 'X';
BEGIN
CASE l_status
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN 'I' THEN
DBMS_OUTPUT.PUT_LINE('無効');
ELSE
RAISE_APPLICATION_ERROR(-20001, '未知のステータスです: ' || l_status);
END CASE;
END;
/
例外処理の基本や RAISE_APPLICATION_ERROR の使い方は PL/SQL例外処理ガイド にまとめています。未知値を業務エラーにするか、無視するかは仕様として決めておきます。
CASE文とCASE式の違い
ORA-06592で特に混乱しやすいのが、PL/SQLのCASE文とSQLのCASE式の違いです。どちらも CASE と書きますが、目的が違います。
| 比較 | CASE文 | CASE式 |
|---|---|---|
| 目的 | 処理を分岐する | 値を返す |
| 主な場所 | PL/SQLブロック内 | SELECT、WHERE、ORDER BYなど |
| THENの中身 | 実行する文 | 返す値 |
| 一致なし | ELSEなしならORA-06592 | ELSEなしならNULLになり得る |
| 代表例 | CASE v WHEN ... THEN DBMS_OUTPUT... |
CASE WHEN ... THEN 'A' END |
SELECT employee_id,
CASE department_id
WHEN 10 THEN 'Sales'
WHEN 20 THEN 'Admin'
END AS dept_label
FROM employees;
-- SQLのCASE式では、一致しない行の dept_label はNULLになり得る
SQLのCASE式とDECODEの違いは CASE式とDECODE関数の違い、SQL全般のCASE WHENは SQL CASE WHENガイド も参考になります。
NULLが一致しない落とし穴
simple CASE文では、セレクタが NULL の場合、WHEN NULL と書いても期待通りに一致しません。NULLを扱うなら、searched CASE文で IS NULL を使う方が分かりやすいです。
DECLARE
l_status VARCHAR2(1) := NULL;
BEGIN
CASE l_status
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN NULL THEN
DBMS_OUTPUT.PUT_LINE('未設定');
END CASE;
END;
/
-- NULLは = NULL で一致しないため、ELSEなしならORA-06592になり得る
DECLARE
l_status VARCHAR2(1) := NULL;
BEGIN
CASE
WHEN l_status = 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN l_status IS NULL THEN
DBMS_OUTPUT.PUT_LINE('未設定');
ELSE
DBMS_OUTPUT.PUT_LINE('不明');
END CASE;
END;
/
NULLの扱いはPL/SQLの条件分岐全体で重要です。IF文でのNULL判定は PL/SQL IF文ガイド も参考になります。
CASE_NOT_FOUND例外として捕捉する
ORA-06592は、PL/SQLでは CASE_NOT_FOUND という事前定義例外として捕捉できます。ただし、捕捉して握りつぶすより、基本はCASE文にELSEを入れて処理方針を明示する方が読みやすいです。
DECLARE
l_status VARCHAR2(1) := 'X';
BEGIN
CASE l_status
WHEN 'A' THEN
DBMS_OUTPUT.PUT_LINE('有効');
WHEN 'I' THEN
DBMS_OUTPUT.PUT_LINE('無効');
END CASE;
EXCEPTION
WHEN CASE_NOT_FOUND THEN
DBMS_OUTPUT.PUT_LINE('未定義のステータスです: ' || l_status);
END;
/
例外としてまとめて処理したい場合はこの形でも構いませんが、通常はCASE文の近くに ELSE を置いた方が、どの値を想定しているか読み取りやすくなります。
ORA-06512から発生行を追う
ORA-06592は、エラースタックに ORA-06512 が続くことがあります。行番号から該当するCASE文を探し、ELSEがないか、未知の値やNULLが入っていないかを確認します。ソース確認には USER_SOURCE を使います。
ORA-06592: CASE not found while executing CASE statement ORA-06512: at "APP.PKG_ORDER", line 42 ORA-06512: at line 1
SELECT line,
text
FROM user_source
WHERE name = 'PKG_ORDER'
AND type = 'PACKAGE BODY'
AND line BETWEEN 35 AND 50
ORDER BY line;
行番号の読み方は ORA-06512の原因と読み方 を参照してください。コンパイル時の構文エラーではなく実行時に特定の値で落ちるため、再現データの確認も大切です。
トリガーやAPEXで出る場合
ORA-06592は、通常のPL/SQLブロックだけでなく、トリガー、APEXのプロセス、フォーム処理、バッチ処理でも発生します。画面操作やデータ更新をきっかけに発生する場合は、裏側で実行されるPL/SQLのCASE文を確認します。
| 発生場所 | 見るポイント | 対処 |
|---|---|---|
| トリガー | 更新前後の値が想定外ではないか | ELSEで未知値の扱いを決める |
| APEXプロセス | 画面アイテムの値がNULLや未定義ではないか | 入力値の正規化とELSE追加 |
| バッチ | マスタ追加後の新コードに未対応ではないか | コード表とCASE分岐を同期する |
| パッケージAPI | 呼び出し元から未知ステータスが来ていないか | API入口でバリデーションする |
トリガー内の処理で落ちる場合は、トリガーの基本も確認しておくと切り分けやすいです。関連する無効化やコンパイルエラーがある場合は ORA-06550 も確認します。
修正方針の選び方
| 状況 | おすすめ | 理由 |
|---|---|---|
| 何もしないのが正常 | ELSE NULL; |
ORA-06592を防ぎつつ処理を明示できる |
| 未知値は業務エラー | RAISE_APPLICATION_ERROR |
値と原因をログに残しやすい |
| NULLを個別扱いしたい | searched CASEでIS NULL |
NULL比較の落とし穴を避けられる |
| 分岐が増え続ける | コード表やマスタ参照に寄せる | CASE文の保守漏れを減らせる |
| 呼び出し元でまとめて処理 | CASE_NOT_FOUNDを捕捉 |
共通例外処理に寄せられる |
再発防止のログとテスト
ORA-06592は、開発時には見えなかった未知コードやNULLが本番で流れてきた時に発生しやすいエラーです。単に ELSE NULL で回避するだけでなく、どの値が来た時に想定外だったのかをログに残すと再発防止につながります。
CASE l_status
WHEN 'A' THEN
process_active;
WHEN 'I' THEN
process_inactive;
ELSE
log_unknown_status(l_status);
RAISE_APPLICATION_ERROR(-20001, '未定義のステータスです: ' || NVL(l_status, '<NULL>'));
END CASE;
| テスト値 | 確認すること | 例 |
|---|---|---|
| 通常値 | 既存分岐に入る | 'A'、'I' |
| 未知コード | ELSEで想定通り処理される | 'X' |
| NULL | IS NULL分岐またはELSEで扱える | NULL |
| 小文字・空白付き | 正規化が必要か判断する | 'a'、' A ' |
| マスタ追加後の新コード | CASE分岐またはマスタ参照が追従する | 'S' |
状態コードが増え続ける場合は、CASE文に分岐を足し続けるより、コードマスタを参照する設計に寄せる方が保守しやすいこともあります。CASE文で扱う値を限定するなら、入力時点で大文字化、trim、NULL変換などの正規化を行うと事故を減らせます。
チェックリスト
| 項目 | OKの状態 |
|---|---|
| CASE文にELSEがある | 未知値でも実行経路が決まっている |
| NULL入力を考慮している | IS NULL または事前変換がある |
| CASE式とCASE文を混同していない | 値を返す式か、文を実行する分岐かが明確 |
| ORA-06512の行番号を確認した | 該当CASE文が特定できている |
| 未知コードの扱いが仕様化されている | 無視するかエラーにするか決まっている |
| テストに想定外値を含めた | NULLや新コードでも落ち方を確認済み |
よくある質問
SQLのCASE式でもORA-06592になりますか?
ORA-06592は主にPL/SQLのCASE文で、実行する分岐が見つからない時に発生します。SQLのCASE式は値を返す式なので、混同しないようにします。
ELSE NULLは安全ですか?
何もしないことが仕様なら安全です。ただし、未知値を見逃す実装にもなるため、本来エラーにすべき値ならRAISE_APPLICATION_ERRORを使います。
WHEN NULLを書いたのに一致しません
NULLは通常の等価比較で一致しません。NULLを扱う場合はsearched CASEで WHEN value IS NULL THEN と書きます。
CASE_NOT_FOUNDを捕捉すればよいですか?
捕捉はできますが、まずCASE文にELSEを入れて想定外値の扱いを明示する方が保守しやすいです。
まとめ
ORA-06592は、PL/SQLのCASE文で一致するWHENがなく、ELSEもない時に発生します。SQLのCASE式とは挙動が異なり、CASE文では実行する文が見つからないと CASE_NOT_FOUND 例外になります。
対処では、CASE文に ELSE を追加し、何もしないなら ELSE NULL;、不正値なら RAISE_APPLICATION_ERROR を使います。NULLや未知コードをテストに含め、ORA-06512 の行番号から該当CASE文を確認すると、原因を絞り込みやすくなります。
参考
ORA-06592 – Oracle Database Error Help
CASE Statement – Oracle Database PL/SQL Language Reference
Predefined Exceptions – Oracle Database PL/SQL Language Reference
