【Oracle】ORA-00942 の原因と解決方法完全ガイド|存在確認・権限・シノニム・スキーマ修飾・診断手順まで解説

【Oracle】ORA-00942 の原因と解決方法完全ガイド|存在確認・権限・シノニム・スキーマ修飾・診断手順まで解説 Oracle

Oracle データベースで SQL を実行したとき、次のエラーが表示されることがあります。

エラーメッセージ
ORA-00942: table or view does not exist
(テーブルまたはビューが存在しません)

このエラーは「指定したテーブルやビューが見つからない」という意味ですが、実際にはテーブルが存在しているのに発生することも多く、権限不足スキーマ修飾の漏れシノニムの未設定など原因は多岐にわたります。

本記事では、ORA-00942 の原因を6 つのパターンに分類し、それぞれの確認 SQL と対処法、そして診断チェックリストまで体系的に解説します。

この記事でわかること
・ORA-00942 の原因 6 パターンとその見分け方
・各パターン別の確認 SQL と対処法
・「テーブルが存在するのに ORA-00942 が出る」ケースの診断手順
・PL/SQL コンパイル時と実行時での発生の違い
・DDL(CREATE VIEW / TRIGGER)内で発生するケース
・リサイクルビン・DB Link 参照での発生ケース
スポンサーリンク

ORA-00942 の原因 6 パターン

# 原因 頻度 典型的な状況
テーブル / ビューが本当に存在しない テーブル名のスペルミス・大文字小文字の間違い・DROP 済み
別スキーマのオブジェクトにスキーマ修飾なしでアクセス 他ユーザーのテーブルを「テーブル名」だけで参照
オブジェクトへの権限が不足 SELECT 権限がないテーブルを参照
シノニムが存在しない / 無効 PUBLIC SYNONYM が未作成 / 参照先が消えた
DDL / PL/SQL 内での参照先が存在しない CREATE VIEW の SELECT 先が DROP された
リサイクルビン / DB Link 参照の問題 DROP TABLE 後のゴミ箱・DB Link 先のテーブルが消えた

原因①:テーブル / ビューが本当に存在しない

よくある原因

最も基本的な原因です。テーブル名のスペルミス、大文字小文字の間違い、テーブルがまだ作成されていない、または DROP 済みであるケースです。

SQL(オブジェクトの存在を確認)
-- 自分のスキーマ内のテーブル / ビューを確認
SELECT object_name, object_type, status
FROM user_objects
WHERE object_name = 'EMPLOYEES';   -- ← 大文字で指定

-- 結果が 0 件 → テーブルが存在しない
-- 結果がある → 別の原因(②〜⑥を確認)
Oracle はオブジェクト名を大文字で格納する
CREATE TABLE employees ... で作成しても、内部的には EMPLOYEES(大文字)として格納されます。USER_OBJECTS で検索するときは必ず大文字で指定してください。ダブルクォートで作成した場合(CREATE TABLE "myTable" ...)のみ、そのままの大文字小文字で格納されます。
SQL(あいまい検索でスペルミスを発見)
-- テーブル名があやふやな場合、LIKE で部分一致検索
SELECT object_name, object_type FROM user_objects
WHERE object_name LIKE '%EMP%'
ORDER BY object_name;

原因②:別スキーマのオブジェクトにスキーマ修飾なしでアクセス

Oracle では、他のスキーマ(ユーザー)のテーブルを参照するにはスキーマ名.テーブル名 の形式で指定する必要があります。スキーマ修飾を省略すると、自分のスキーマ内を検索し、見つからなければ ORA-00942 になります。

SQL(スキーマ修飾の有無による違い)
-- NG: HR スキーマの employees にアクセスしたいが、スキーマ修飾がない
SELECT * FROM employees;  -- → ORA-00942(自分のスキーマに employees がない場合)

-- OK: スキーマ名を明示的に指定
SELECT * FROM hr.employees;  -- → OK(HR スキーマの employees を参照)
SQL(オブジェクトがどのスキーマにあるか確認)
-- 全スキーマを対象にテーブルを検索
SELECT owner, object_name, object_type
FROM all_objects
WHERE object_name = 'EMPLOYEES'
ORDER BY owner;

-- 結果例:
-- OWNER=HR, OBJECT_NAME=EMPLOYEES, OBJECT_TYPE=TABLE
-- → HR スキーマにあることが判明 → hr.employees で参照
スキーマ修飾を省略したい場合
毎回 hr.employees と書くのが面倒な場合は、以下の方法があります。
シノニムを作成する(後述の原因④参照)
ALTER SESSION SET CURRENT_SCHEMA で現在のスキーマを変更する
詳細は「スキーマとは何か・作成から活用まで完全ガイド」を参照してください。

原因③:オブジェクトへの権限が不足

テーブルが存在しスキーマ修飾も正しいのに ORA-00942 が出る場合、SELECT 権限(またはその他のオブジェクト権限)が付与されていないことが原因です。Oracle は権限がないオブジェクトに対して、セキュリティ上の理由から「存在しない」と同じエラーを返します。

SQL(権限の確認)
-- 自分に付与されているオブジェクト権限を確認
SELECT grantor, privilege, table_name, grantable
FROM user_tab_privs
WHERE table_name = 'EMPLOYEES';

-- ロール経由も含めて確認
SELECT * FROM all_tab_privs
WHERE table_name = 'EMPLOYEES'
  AND grantee IN (USER, 'PUBLIC');

-- 結果が 0 件 → 権限がない
SQL(権限の付与: DBA またはオブジェクト所有者が実行)
-- SELECT 権限を付与
GRANT SELECT ON hr.employees TO app_user;

-- SELECT / INSERT / UPDATE / DELETE をまとめて付与
GRANT SELECT, INSERT, UPDATE, DELETE ON hr.employees TO app_user;

-- 全ユーザーに付与(PUBLIC)
GRANT SELECT ON hr.employees TO PUBLIC;

権限管理の詳細は「新規ユーザー作成と権限付与の完全ガイド」を参照してください。

権限不足でも「存在しない」と表示される理由
Oracle はセキュリティ上、権限がないオブジェクトの存在自体を隠します。「テーブルは存在するが権限がない」場合でも、エラーメッセージは「テーブルまたはビューが存在しません」と表示されます。このため、ORA-00942 が出たら権限不足も必ず疑ってください

原因④:シノニムが存在しない / 無効

シノニム(別名)経由でアクセスしている場合、シノニムが作成されていない、または参照先のオブジェクトが削除されてシノニムが無効になっていることがあります。

SQL(シノニムの確認)
-- 自分のスキーマのプライベートシノニムを確認
SELECT synonym_name, table_owner, table_name, db_link
FROM user_synonyms
WHERE synonym_name = 'EMPLOYEES';

-- PUBLIC シノニムも含めて確認
SELECT owner, synonym_name, table_owner, table_name
FROM all_synonyms
WHERE synonym_name = 'EMPLOYEES';
SQL(シノニムの作成)
-- プライベートシノニムを作成
CREATE SYNONYM employees FOR hr.employees;

-- PUBLIC シノニムを作成(DBA 権限が必要)
CREATE PUBLIC SYNONYM employees FOR hr.employees;

-- これで「SELECT * FROM employees」でアクセス可能になる

シノニムの確認・作成・削除の詳細は「シノニムを確認する方法」を参照してください。

原因⑤:DDL / PL/SQL 内での参照先が存在しない

CREATE VIEW / CREATE TRIGGER 内で発生するケース

SQL(ビューの参照先テーブルが削除された例)
-- ビュー定義
CREATE VIEW emp_view AS SELECT * FROM employees;  -- employees が存在すれば OK

-- 後日 employees を DROP
DROP TABLE employees;

-- ビューを参照すると ORA-00942
SELECT * FROM emp_view;  -- ORA-00942

-- ビューのステータスを確認
SELECT object_name, status FROM user_objects WHERE object_name = 'EMP_VIEW';
-- STATUS = INVALID

PL/SQL で発生するケース

PL/SQL では、コンパイル時実行時で ORA-00942 の発生タイミングが異なります。

SQL の種類 検証タイミング 説明
静的 SQL(直接記述) コンパイル時 パッケージ / プロシージャの作成時にテーブルの存在が検証される。テーブルがなければコンパイルエラー
動的 SQL(EXECUTE IMMEDIATE) 実行時 SQL 文字列は実行時に解析される。テーブルがなければ実行時エラー
SQL(PL/SQL での発生例)
-- 静的 SQL: コンパイル時に ORA-00942
CREATE OR REPLACE PROCEDURE test_proc IS
    v_count NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_count FROM nonexistent_table;  -- コンパイルエラー
END;
/
-- Warning: Procedure created with compilation errors.

-- 動的 SQL: 実行時に ORA-00942
CREATE OR REPLACE PROCEDURE test_proc_dynamic IS
    v_count NUMBER;
BEGIN
    EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM nonexistent_table' INTO v_count;
    -- コンパイルは成功するが、実行時に ORA-00942
END;
/
PL/SQL で他スキーマのテーブルを参照する場合の注意
静的 SQL で他スキーマのテーブルを参照するには、実行ユーザーに直接の SELECT 権限が必要です。ロール経由の権限は PL/SQL のコンパイル時に認識されません。ロール経由でしか権限がない場合は、直接 GRANT するか動的 SQL を使います。

原因⑥:リサイクルビン / DB Link 参照

リサイクルビン(ゴミ箱)

SQL(リサイクルビンの確認と復元)
-- リサイクルビンに DROP されたテーブルがあるか確認
SELECT object_name, original_name, type, droptime
FROM recyclebin
WHERE original_name = 'EMPLOYEES';

-- テーブルを復元(FLASHBACK TABLE)
FLASHBACK TABLE employees TO BEFORE DROP;

-- リサイクルビンを経由せず完全削除された場合(PURGE)は復元不可
-- DROP TABLE employees PURGE; → リサイクルビンに残らない

DB Link 参照先のテーブルが存在しない

SQL(DB Link 参照の確認)
-- DB Link 経由でリモートテーブルにアクセスして ORA-00942 が出る場合
SELECT * FROM orders@remote_db;  -- ORA-00942

-- リモート側でテーブルの存在を確認
SELECT * FROM all_tables@remote_db WHERE table_name = 'ORDERS';

-- リモート側の権限を確認
SELECT * FROM all_tab_privs@remote_db WHERE table_name = 'ORDERS';

ORA-00942 診断チェックリスト

ORA-00942 が発生したときに、上から順に確認していく手順です。

手順 確認内容 確認 SQL
1 テーブル名のスペル・大文字小文字は正しいか SELECT object_name FROM user_objects WHERE object_name LIKE ‘%テーブル名%’
2 自分のスキーマにテーブルがあるか SELECT * FROM user_tables WHERE table_name = ‘TABLE_NAME’
3 別スキーマにテーブルがあるか SELECT owner, table_name FROM all_tables WHERE table_name = ‘TABLE_NAME’
4 SELECT 権限があるか SELECT * FROM all_tab_privs WHERE table_name = ‘TABLE_NAME’ AND grantee IN (USER, ‘PUBLIC’)
5 シノニムが正しく設定されているか SELECT * FROM all_synonyms WHERE synonym_name = ‘TABLE_NAME’
6 リサイクルビンにないか SELECT * FROM recyclebin WHERE original_name = ‘TABLE_NAME’

よくある質問

Qテーブルが存在するのに ORA-00942 が出ます
A最も多い原因は権限不足です。Oracle は権限がないオブジェクトの存在を隠すため、「存在しない」と表示されます。ALL_TAB_PRIVS で権限を確認し、不足していれば GRANT で付与してください。次に多いのはスキーマ修飾の漏れです。別スキーマのテーブルを参照する場合は スキーマ名.テーブル名 で指定してください。
QINSERT 文や UPDATE 文でも ORA-00942 が出ますか?
Aはい。ORA-00942 は SELECT だけでなく、INSERT / UPDATE / DELETE / MERGE でも発生します。参照先テーブルの存在確認と権限確認は同じ手順で行えます。
Qロール経由で権限を付与していますが PL/SQL で ORA-00942 が出ます
APL/SQL の静的 SQL(直接記述)では、ロール経由の権限はコンパイル時に認識されません。対処法は 2 つあります。
①テーブル所有者から直接 GRANT SELECT ON table TO user で付与する
②動的 SQL(EXECUTE IMMEDIATE)を使う
QCREATE VIEW で ORA-00942 が出ます
Aビュー内で参照しているテーブルが存在しないか、権限が不足しています。ビューの作成には参照テーブルへの直接の SELECT 権限が必要です(ロール経由は不可)。また、ビューの参照先テーブルを DROP すると、ビュー自体は INVALID 状態になります。
QDROP したテーブルを元に戻せますか?
ADROP TABLE(PURGE なし)で削除したテーブルはリサイクルビンに残ります。FLASHBACK TABLE テーブル名 TO BEFORE DROP で復元できます。ただし DROP TABLE ... PURGE で削除した場合はリサイクルビンに残らず、復元できません。
QORA-00942 と ORA-01031 の違いは何ですか?
AORA-00942 は「テーブルが存在しない(または権限がない)」で、SELECT / DML で発生します。
ORA-01031(権限が不足しています)は、DDL(CREATE TABLE, ALTER TABLE 等)やシステム権限が不足している場合に発生します。
ORA-00942 は「オブジェクトレベルの権限」、ORA-01031 は「システムレベルの権限」に関するエラーです。

まとめ

ORA-00942 の原因と対処法をまとめます。

原因 確認方法 対処法
テーブルが存在しない USER_OBJECTS で検索 テーブル名のスペル確認 / テーブルを作成
スキーマ修飾がない ALL_OBJECTS で owner を確認 スキーマ名.テーブル名 で指定
権限が不足 ALL_TAB_PRIVS で確認 GRANT SELECT ON … TO …
シノニムが未設定 ALL_SYNONYMS で確認 CREATE [PUBLIC] SYNONYM …
DDL/PL/SQL 内の参照先不在 USER_OBJECTS で STATUS=INVALID を確認 参照先テーブルを再作成 / 権限を直接付与
リサイクルビンに入っている RECYCLEBIN で確認 FLASHBACK TABLE … TO BEFORE DROP

権限の付与方法は「新規ユーザー作成と権限付与の完全ガイド」、シノニムの管理は「シノニムを確認する方法」、スキーマとクロススキーマアクセスは「スキーマ完全ガイド」も併せて参照してください。