【Oracle】ORA-04043の原因と解決方法|object does not exist・存在しないオブジェクトを参照した時の確認ポイント

【Oracle】ORA-04043の原因と解決方法|object does not exist・存在しないオブジェクトを参照した時の確認ポイント Oracle

ORA-04043: object does not exist は、Oracleが指定されたオブジェクト名を認識できない時に発生するエラーです。テーブル、ビュー、シーケンス、プロシージャ、ファンクション、パッケージ、パッケージボディなどで発生します。実際に存在しない場合もありますが、スキーマ名の指定漏れ、シノニムの参照先切れ、ダブルクォートで作った小文字名、権限不足によって見えていないだけ、というケースもあります。

この記事では、まずデータディクショナリで存在確認を行い、次にスキーマ、シノニム、権限、無効オブジェクトの順に切り分けます。単に「ない」と決めつけるのではなく、Oracleから見えている名前と実体を確認するのがポイントです。

先に結論
ORA-04043が出たら、まず USER_OBJECTSALL_OBJECTS、必要なら DBA_OBJECTS で対象名を検索します。見つからない場合はスキーマ違い・大文字小文字・ダブルクォート名を確認し、見つかるのに参照できない場合はシノニムや権限を確認します。
スポンサーリンク

ORA-04043とは

Oracle公式のエラー説明では、ORA-04043はシステムが指定されたオブジェクト名を認識できなかった時に発生します。名前の誤りだけでなく、リネームできない種類のオブジェクトをリネームしようとした場合なども原因として示されています。

開発現場では、DESC table_nameDROPALTER、PL/SQLのコンパイル、シノニム経由の参照、別スキーマのオブジェクト参照でよく見ます。コンパイル済みオブジェクトのエラーが絡む場合は ORA-04063PLS-00905 も合わせて確認します。

まず自分のスキーマ内に存在するか確認する

最初に、ログイン中ユーザーのスキーマに対象オブジェクトがあるか確認します。自分のスキーマ内なら USER_OBJECTS で確認できます。

check-user-objects.sql
SELECT object_name,
       object_type,
       status,
       created,
       last_ddl_time
FROM user_objects
WHERE object_name = UPPER('target_object')
ORDER BY object_type, object_name;

ここで見つかれば、少なくとも自分のスキーマには存在しています。見つからない場合は、別スキーマのオブジェクト、ダブルクォート名、シノニム経由の参照を疑います。

全スキーマから見える範囲を確認する

別スキーマにある可能性がある場合は、ALL_OBJECTS で現在ユーザーから見える範囲を確認します。DBA権限がある場合は DBA_OBJECTS で全体を確認できます。

check-all-objects.sql
SELECT owner,
       object_name,
       object_type,
       status,
       last_ddl_time
FROM all_objects
WHERE object_name = UPPER('target_object')
ORDER BY owner, object_type;
check-dba-objects.sql
SELECT owner,
       object_name,
       object_type,
       status,
       last_ddl_time
FROM dba_objects
WHERE object_name = UPPER('target_object')
ORDER BY owner, object_type;

別スキーマに存在しているなら、SQLでは owner.object_name のようにスキーマ修飾して参照します。毎回スキーマ名を付けたくない場合は、シノニムを作成する設計もあります。

schema-qualified-reference.sql
-- スキーマ修飾して参照する
SELECT * FROM app_owner.orders;

-- PL/SQLオブジェクトもスキーマ修飾できる
BEGIN
  app_owner.order_pkg.create_order;
END;
/

アプリケーションやSQLツールで CURRENT_SCHEMA を変更している場合、ログインユーザーと名前解決先のスキーマが異なることがあります。同じSQLでも接続設定によって結果が変わる場合は、現在のスキーマを確認します。

check-current-schema.sql
SELECT USER AS login_user,
       SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS current_schema,
       SYS_CONTEXT('USERENV', 'CURRENT_USER') AS current_user
FROM dual;
set-current-schema.sql
-- セッション内の名前解決先を変更する例
ALTER SESSION SET CURRENT_SCHEMA = app_owner;

-- この後は app_owner.orders を orders として参照できる
SELECT * FROM orders;

シノニムの参照先を確認する

シノニムを使っている場合、シノニム自体は存在していても、参照先オブジェクトが削除・リネームされていることがあります。その場合、シノニム経由の操作でORA-04043や関連エラーが出ます。

check-synonyms.sql
SELECT owner,
       synonym_name,
       table_owner,
       table_name,
       db_link
FROM all_synonyms
WHERE synonym_name = UPPER('target_object')
ORDER BY owner, synonym_name;
check-public-synonyms.sql
SELECT owner,
       synonym_name,
       table_owner,
       table_name,
       db_link
FROM all_synonyms
WHERE owner IN (USER, 'PUBLIC')
  AND synonym_name = UPPER('target_object')
ORDER BY CASE owner WHEN USER THEN 1 WHEN 'PUBLIC' THEN 2 ELSE 3 END;
check-synonym-target.sql
SELECT o.owner,
       o.object_name,
       o.object_type,
       o.status
FROM all_synonyms s
LEFT JOIN all_objects o
  ON o.owner = s.table_owner
 AND o.object_name = s.table_name
WHERE s.synonym_name = UPPER('target_object');

参照先が存在しない場合は、シノニムの再作成、参照先名の修正、DBリンク先の確認が必要です。無効オブジェクトの切り分けは PLS-00905、オブジェクト内のコンパイルエラーは ORA-04063 の記事も参考になります。

DBリンク付きのシノニムでは、ローカルDBではなくリンク先DBに実体があります。リンク先のオブジェクト削除、権限変更、接続先変更でもORA-04043相当の見え方になるため、DB_LINK 列が入っている場合は接続先も確認します。

ダブルクォート名・大文字小文字を確認する

Oracleの通常の識別子は大文字に正規化されます。しかし、ダブルクォートで小文字や混在文字の名前を作ると、参照時にも完全一致のダブルクォートが必要になります。

quoted-name-example.sql
-- ダブルクォートで小文字名の表を作成
CREATE TABLE "orders" (
  id NUMBER
);

-- これは別名 ORDERS として解釈されるため見つからない
DESC orders;

-- 作成時と同じ表記で参照する
DESC "orders";
find-quoted-objects.sql
SELECT owner,
       object_name,
       object_type
FROM all_objects
WHERE LOWER(object_name) = LOWER('target_object')
ORDER BY owner, object_name;

実務では、ダブルクォート名はトラブルの原因になりやすいため、可能なら通常の大文字正規化される名前に統一します。

権限不足との違いを確認する

オブジェクトが存在していても、現在ユーザーに権限がないと見えないことがあります。ただし、操作や文脈によって ORA-00942ORA-01031PLS-00201 など別エラーとして出ることもあります。

check-object-privileges.sql
SELECT owner,
       table_name,
       privilege,
       grantor,
       grantee
FROM all_tab_privs
WHERE table_name = UPPER('target_object')
ORDER BY owner, grantee, privilege;
check-role-privileges.sql
SELECT role,
       owner,
       table_name,
       privilege
FROM role_tab_privs
WHERE table_name = UPPER('target_object')
ORDER BY role, owner, privilege;
grant-example.sql
-- 参照権限を直接付与する例
GRANT SELECT ON app_owner.orders TO app_user;

-- PL/SQLから使う場合はロール経由ではなく直接権限が必要になることがある
GRANT EXECUTE ON app_owner.order_pkg TO app_user;

権限の考え方は ORA-01031ユーザー・権限・ロールユーザー権限の確認方法 の記事も参考になります。

PL/SQLではロール権限だけでは足りないことがある
SQL単体では参照できても、ストアドプロシージャやパッケージ内ではロール経由権限が効かず、直接付与された権限が必要になることがあります。コンパイル時のORA-04043やPLS-00201では、この差を確認します。

PL/SQLコンパイル時に出る場合

パッケージ、プロシージャ、ファンクション、トリガーのコンパイル中にORA-04043が出る場合は、参照先オブジェクト名、シノニム、権限、依存関係を確認します。PL/SQLではロール経由の権限が効かない場面があるため、直接GRANTが必要になることがあります。

check-dependencies.sql
SELECT owner,
       name,
       type,
       referenced_owner,
       referenced_name,
       referenced_type
FROM all_dependencies
WHERE name = UPPER('target_package')
ORDER BY referenced_owner, referenced_name;
show-compile-errors.sql
SELECT name,
       type,
       line,
       position,
       text
FROM user_errors
WHERE name = UPPER('target_package')
ORDER BY sequence;

PL/SQLの未宣言・コンポーネント違いは PLS-00201PLS-00302、トリガー無効化は ORA-04098、実行時にプログラムユニットが見つからない場合は ORA-06508 も確認します。

DROPやALTERで出る場合

DROPALTER でORA-04043が出る場合は、対象オブジェクトの種類と名前を確認します。削除済み、別スキーマ、同名の別オブジェクト、リネームできないオブジェクトを操作している可能性があります。

check-before-drop.sql
SELECT owner,
       object_name,
       object_type,
       status
FROM all_objects
WHERE object_name = UPPER('target_object')
ORDER BY owner, object_type;

DDLがロック待ちになる場合は ORA-04021、テーブルやビューの存在・権限問題は ORA-00942 とも切り分けます。

よくある原因

オブジェクト名の typo

単純なスペルミス、接頭辞・接尾辞の違い、環境ごとの名前違いです。まずディクショナリ検索で確認します。

スキーマ指定漏れ

別スキーマに存在するオブジェクトを、スキーマ修飾なしで参照しているケースです。

シノニムの参照先切れ

シノニムは残っているが、参照先テーブルやパッケージが削除・リネームされているケースです。

ダブルクォート名

小文字や混在文字で作成されたオブジェクトを、通常識別子として参照しているケースです。

権限不足

実体は存在するが、現在ユーザーから見えない、またはPL/SQL内で直接権限が不足しているケースです。

デプロイ順の問題

参照するビュー、パッケージ、シノニムを作る前にコンパイルしているケースです。

関連エラーとの違い

ORA-04043

指定したオブジェクト名をOracleが認識できない時のエラーです。存在確認、スキーマ、シノニム、権限を見ます。

ORA-00942

主にテーブルまたはビューが存在しない、または権限がない時に出ます。SQL実行時の表/ビュー参照でよく見ます。

PLS-00201

PL/SQLで識別子が宣言されていない時のエラーです。権限不足やスキーマ修飾漏れでも出ることがあります。

ORA-04063

オブジェクトは存在するが、ビューやパッケージボディなどにコンパイルエラーがある状態です。

PLS-00905

オブジェクトが無効な状態です。ORA-04043のように存在しないのではなく、存在しているが使えない状態を疑います。

対応手順のまとめ

  1. USER_OBJECTS で自分のスキーマ内に存在するか確認する
  2. ALL_OBJECTS / DBA_OBJECTS で別スキーマに存在するか確認する
  3. CURRENT_SCHEMA が想定どおりか確認する
  4. 別スキーマなら owner.object_name で参照する
  5. ALL_SYNONYMS で通常シノニム、PUBLICシノニム、DBリンク付きシノニムを確認する
  6. ダブルクォート名や大文字小文字の違いを確認する
  7. 権限不足なら直接GRANTやロールの扱いを確認する
  8. PL/SQLコンパイル時は依存関係と USER_ERRORS を確認する

よくある質問

テーブルがあるのにORA-04043になります。なぜですか?

別スキーマにある、シノニム経由で参照している、ダブルクォート名で作成されている、権限がない、などが考えられます。ALL_OBJECTSALL_SYNONYMS で確認します。

ORA-00942との違いは何ですか?

ORA-00942はテーブルやビューの参照でよく出ます。ORA-04043は、より広くオブジェクト名をOracleが認識できない時に出ます。実務では存在確認と権限確認をセットで行います。

権限がない場合もORA-04043になりますか?

文脈によっては、存在しないように見えることがあります。特にPL/SQL内ではロール経由の権限が効かないため、直接GRANTが必要になることがあります。

シノニムを作り直せば解決しますか?

参照先が変わっただけなら有効です。ただし、参照先オブジェクト自体が存在しない、権限がない、DBリンク先に問題がある場合は、シノニムだけでは解決しません。

参考