【Oracle】ORA-06592の原因と解決方法|CASE not found while executing CASE statement の直し方

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の CASEELSE があるか確認します。何もしないのが正しいなら 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_FOUNDORA-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_statusA でも I でもない場合に、どの分岐にも一致せずORA-06592になります。

ora06592-case-no-else.sql
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

テストデータでは AI しか来なかったとしても、本番で未知のコードやNULLが来ると落ちます。CASE文には「想定外をどう扱うか」を明示しておくのが安全です。

ELSE NULLで何もしない

想定外の値では何も処理しないのが正しいなら、ELSE NULL; を書きます。PL/SQLでは NULL; は何もしない文として使えます。

ora06592-else-null.sql
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のままでは、どの値が想定外だったのか分かりにくいためです。

ora06592-raise-application-error.sql
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
sql-case-expression-null.sql
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 を使う方が分かりやすいです。

ora06592-null-not-matched.sql
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になり得る
ora06592-null-safe-searched-case.sql
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を入れて処理方針を明示する方が読みやすいです。

case-not-found-exception.sql
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 を使います。

ora06592-error-stack.txt
ORA-06592: CASE not found while executing CASE statement
ORA-06512: at "APP.PKG_ORDER", line 42
ORA-06512: at line 1
check-user-source-ora06592.sql
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 で回避するだけでなく、どの値が来た時に想定外だったのかをログに残すと再発防止につながります。

ora06592-log-unknown-value.sql
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

CASE Expressions – Oracle Database SQL Language Reference