【Oracle】ORA-00604の原因と解決方法|error occurred at recursive SQL level 1・再帰SQLエラーの調べ方

【Oracle】ORA-00604の原因と解決方法|error occurred at recursive SQL level 1・再帰SQLエラーの調べ方 Oracle

ORA-00604: error occurred at recursive SQL level 1 は、Oracleが内部的に実行する再帰SQLの処理中に別のエラーが発生したことを示すメッセージです。ログオン時、DDL実行時、トリガー実行時、データディクショナリ参照時などに出ることがあります。

重要なのは、ORA-00604 だけを見ても原因を特定できない点です。Oracle公式の説明でも、後続のエラーを確認して根本原因を直すことが案内されています。この記事では、後続エラーの読み方、ログオン/DDLトリガー、権限不足、無効オブジェクト、NLSや環境差分の切り分けを整理します。名前が似ている ORA-00600 は内部エラーであり、ORA-00604とは調査の入口が違います。

この記事で分かること

  • ORA-00604が何を示しているか
  • 直後に出るORAエラーを読む手順
  • ログオントリガー、DDLトリガー、システムトリガーの確認SQL
  • ORA-04088、ORA-06512、ORA-01031などが併発する場合の見方
  • 一時回避と恒久対応の考え方
スポンサーリンク

この記事で扱う範囲

この記事では、ORA-00604 が出た時にエラースタックを読み、ログオン/DDLトリガー、権限不足、無効オブジェクト、PL/SQL行番号を順に確認する流れを扱います。トリガーそのものの作り方や種類は別記事に任せ、ここでは障害調査で必要な確認SQLと判断ポイントに絞ります。

最初に結論:ORA-00604の次の行が本当の原因

ORA-00604は、単独の原因名ではなく「再帰SQL中に何かが失敗した」という入口です。本当に直すべき対象は、エラースタックの次の行以降に出る ORA-04088ORA-01031ORA-06512ORA-06502 などです。

エラー全体を読むORA-00604の1行だけで判断せず、直後に出るORAエラーと行番号を確認します。
いつ出るかを見るログオン時、CREATE/ALTER/DROP時、SELECT時、アプリ接続時のどれで出るかを分けます。
トリガーを疑うログオントリガー、DDLトリガー、SERVERERRORトリガーが失敗するとORA-00604につながります。
権限と無効オブジェクトを見るトリガー内SQLの権限不足、無効なプロシージャ、存在しない表参照を確認します。

PL/SQLの行番号付きエラーは ORA-06512の原因と読み方、権限不足は ORA-01031完全ガイド、数値や文字列変換のPL/SQLエラーは ORA-06502の原因と解決方法 も参考にしてください。

エラーメッセージの読み方

典型的には、ORA-00604の後に別のORAエラーが続きます。次の例では、ログオントリガー実行中にトリガー内でエラーが起きています。

ora-00604-stack.txt
ORA-00604: error occurred at recursive SQL level 1
ORA-04088: error during execution of trigger 'SYS.LOGON_AUDIT_TRG'
ORA-06512: at line 8

この場合、調査対象はORA-00604そのものではなく、SYS.LOGON_AUDIT_TRG というトリガーと、その8行目です。トリガー実行時エラーの考え方は PL/SQLトリガー完全ガイド と関連します。

よくある発生パターン

ログオン時に出るAFTER LOGON ON DATABASE/SCHEMAトリガー内のSQL、権限、無効オブジェクトを確認します。
DDL実行時に出るBEFORE/AFTER CREATE、ALTER、DROPなどのDDLトリガーを確認します。
特定ユーザーだけ出るユーザー固有のスキーマトリガー、権限、プロファイル、環境変数、NLS設定を疑います。
アプリ接続だけ出る接続直後に実行される初期化SQL、ログオン処理、監査トリガーを確認します。

確認SQL

ログオン/DDLトリガーを確認する

まず、DATABASEまたはSCHEMAに作成されたシステムトリガーを確認します。Oracleのシステムトリガーは、ログオン、DDL、SERVERERRORなどのイベントで自動実行されます。

system-trigger-check.sql
SELECT owner,
       trigger_name,
       trigger_type,
       triggering_event,
       table_owner,
       status
FROM dba_triggers
WHERE triggering_event LIKE '%LOGON%'
   OR triggering_event LIKE '%CREATE%'
   OR triggering_event LIKE '%ALTER%'
   OR triggering_event LIKE '%DROP%'
   OR triggering_event LIKE '%SERVERERROR%'
ORDER BY owner, trigger_name;

DBA_TRIGGERS が参照できない場合は、権限のあるユーザーで確認するか、ALL_TRIGGERS / USER_TRIGGERS を使います。

トリガー本文を確認する

エラーにトリガー名が出ている場合は、該当トリガーの本文を確認します。参照している表、プロシージャ、パッケージ、権限が原因になっていることがあります。

trigger-body-check.sql
SELECT owner,
       name,
       type,
       line,
       text
FROM dba_source
WHERE owner = 'SYS'
  AND name = 'LOGON_AUDIT_TRG'
ORDER BY line;

コンパイルエラーを確認する

無効なトリガーや依存オブジェクトがある場合、実行時にORA-00604の後続エラーとして現れることがあります。コンパイルエラーは DBA_ERRORS で確認します。

trigger-compile-errors.sql
SELECT owner,
       name,
       type,
       line,
       position,
       text
FROM dba_errors
WHERE owner = 'SYS'
  AND name = 'LOGON_AUDIT_TRG'
ORDER BY sequence;

無効オブジェクトを確認する

トリガーが呼び出すプロシージャやパッケージがINVALIDになっている場合もあります。関連スキーマの無効オブジェクトを確認します。

invalid-objects-check.sql
SELECT owner,
       object_name,
       object_type,
       status
FROM dba_objects
WHERE status = 'INVALID'
  AND owner IN ('SYS', 'APP')
ORDER BY owner, object_type, object_name;

後続エラー別の見方

ORA-04088が続く場合

ORA-04088 は、トリガー実行中にランタイムエラーが発生したことを示します。エラーに出ているトリガー名を確認し、トリガー内SQL、呼び出し先プロシージャ、例外処理を見直します。

ora-04088-example.txt
ORA-00604: error occurred at recursive SQL level 1
ORA-04088: error during execution of trigger 'APP.DDL_AUDIT_TRG'
ORA-06512: at line 15

ORA-01031が続く場合

ORA-01031 が続く場合、トリガー内で実行しているSQLに必要な権限が不足している可能性があります。PL/SQL内ではロール経由の権限が効かない場面があるため、直接付与された権限を確認します。

privilege-check.sql
SELECT grantee,
       owner,
       table_name,
       privilege
FROM dba_tab_privs
WHERE grantee = 'APP'
  AND owner = 'SYS'
ORDER BY table_name, privilege;

権限不足の切り分けは ORA-01031完全ガイド を確認してください。

ORA-06512が続く場合

ORA-06512 はPL/SQLのエラー発生行を示します。ORA-00604と一緒に出る場合も、ORA-06512の行番号からトリガーやプロシージャのどこで失敗したかを追います。

行番号の読み方は ORA-06512の原因と読み方 に詳しくまとめています。

ログオンできない場合の一時回避

ログオントリガーが失敗して一般ユーザーが接続できない場合は、DBA権限を持つユーザーで接続し、原因トリガーを確認します。一般ユーザーだけが失敗するのか、特定スキーマだけが失敗するのか、DBAユーザーでは接続できるのかを分けると、トリガーの範囲を絞り込みやすくなります。本番では、無効化する前に影響範囲、監査要件、復旧手順を確認します。

  • DBAまたは管理用ユーザーで接続できるか確認する
  • 別ユーザーでは発生しないか確認する
  • エラーに出ているトリガー名を控える
  • 無効化する場合は、再有効化コマンドと戻し担当を決める
  • 監査・セキュリティ要件に影響しないか確認する
disable-logon-trigger.sql
-- 原因が明確で、緊急回避が必要な場合の例
ALTER TRIGGER sys.logon_audit_trg DISABLE;

-- 修正後に再有効化
ALTER TRIGGER sys.logon_audit_trg ENABLE;

トリガー無効化は強い操作です。監査、セキュリティ、運用ルールに関係する場合があるため、原因調査と復旧計画をセットで行います。

やってはいけない対応

ORA-00604だけで検索して設定を変える本当の原因は後続エラーです。エラースタック全体を読まずに変更すると遠回りになります。
SYS/SYSTEMのトリガーを不用意に無効化する監査やセキュリティ制御を止める可能性があります。緊急時でも影響を確認します。
ロール付与だけで権限不足を直そうとするPL/SQL内では直接権限が必要なケースがあります。GRANT先と実行者を確認します。
ORA-00600と混同するORA-00604は再帰SQL中のエラー、ORA-00600は内部エラーです。対応方針が異なります。

内部エラーとの違いは ORA-00600完全ガイド も参考になります。

本番対応チェックリスト

  • ORA-00604の後続エラーをすべて控えた
  • ログオン時、DDL時、特定SQL実行時のどれで出るか確認した
  • エラーに出ているトリガー名と行番号を確認した
  • DBA_TRIGGERSでLOGON/DDL/SERVERERRORトリガーを確認した
  • DBA_SOURCEでトリガー本文を確認した
  • DBA_ERRORSとDBA_OBJECTSで無効オブジェクトを確認した
  • ORA-01031がある場合は直接権限を確認した
  • トリガー無効化が必要な場合は影響範囲と戻し手順を決めた

再発防止

ORA-00604の再発防止では、ログオン/DDLトリガーを複雑にしすぎないことが重要です。トリガー内で外部状態に依存する処理、失敗しやすい監査テーブルINSERT、権限が曖昧なSQL、例外を握りつぶす処理は、障害時に原因を追いにくくします。

safe-trigger-pattern.sql
CREATE OR REPLACE TRIGGER app.logon_audit_trg
AFTER LOGON ON DATABASE
BEGIN
  -- 失敗してもログオン全体を壊さない設計にするか、
  -- 壊してよい要件なのかを事前に決める
  INSERT INTO app.logon_audit(user_name, logon_time)
  VALUES (SYS_CONTEXT('USERENV', 'SESSION_USER'), SYSDATE);
EXCEPTION
  WHEN OTHERS THEN
    -- 本番要件に応じて、記録だけして再送出しない/再送出するを決める
    NULL;
END;
/

例外をすべて握りつぶす設計が常に正しいわけではありません。監査を必須にするのか、ログオン可用性を優先するのかを業務要件として決めます。

まとめ

ORA-00604は、Oracleの再帰SQL処理中に別のエラーが起きたことを示す入口です。まずORA-00604の次に出るエラーを読み、ログオン/DDLトリガー、権限不足、無効オブジェクト、PL/SQL行番号を確認します。

特にログオン時に発生する場合は、システムトリガーが原因になっていることがあります。本番では、原因トリガーを特定し、必要なら一時無効化、修正、再有効化、監視見直しまで行いましょう。