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 済みであるケースです。
-- 自分のスキーマ内のテーブル / ビューを確認 SELECT object_name, object_type, status FROM user_objects WHERE object_name = 'EMPLOYEES'; -- ← 大文字で指定 -- 結果が 0 件 → テーブルが存在しない -- 結果がある → 別の原因(②〜⑥を確認)
CREATE TABLE employees ... で作成しても、内部的には EMPLOYEES(大文字)として格納されます。USER_OBJECTS で検索するときは必ず大文字で指定してください。ダブルクォートで作成した場合(CREATE TABLE "myTable" ...)のみ、そのままの大文字小文字で格納されます。-- テーブル名があやふやな場合、LIKE で部分一致検索 SELECT object_name, object_type FROM user_objects WHERE object_name LIKE '%EMP%' ORDER BY object_name;
原因②:別スキーマのオブジェクトにスキーマ修飾なしでアクセス
Oracle では、他のスキーマ(ユーザー)のテーブルを参照するにはスキーマ名.テーブル名 の形式で指定する必要があります。スキーマ修飾を省略すると、自分のスキーマ内を検索し、見つからなければ ORA-00942 になります。
-- NG: HR スキーマの employees にアクセスしたいが、スキーマ修飾がない SELECT * FROM employees; -- → ORA-00942(自分のスキーマに employees がない場合) -- OK: スキーマ名を明示的に指定 SELECT * FROM hr.employees; -- → OK(HR スキーマの employees を参照)
-- 全スキーマを対象にテーブルを検索 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 は権限がないオブジェクトに対して、セキュリティ上の理由から「存在しない」と同じエラーを返します。
-- 自分に付与されているオブジェクト権限を確認 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 件 → 権限がない
-- 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 が出たら権限不足も必ず疑ってください。
原因④:シノニムが存在しない / 無効
シノニム(別名)経由でアクセスしている場合、シノニムが作成されていない、または参照先のオブジェクトが削除されてシノニムが無効になっていることがあります。
-- 自分のスキーマのプライベートシノニムを確認 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';
-- プライベートシノニムを作成 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 内で発生するケース
-- ビュー定義 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: コンパイル時に 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;
/
静的 SQL で他スキーマのテーブルを参照するには、実行ユーザーに直接の SELECT 権限が必要です。ロール経由の権限は PL/SQL のコンパイル時に認識されません。ロール経由でしか権限がない場合は、直接 GRANT するか動的 SQL を使います。
原因⑥:リサイクルビン / DB Link 参照
リサイクルビン(ゴミ箱)
-- リサイクルビンに 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 参照先のテーブルが存在しない
-- 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’ |
よくある質問
ALL_TAB_PRIVS で権限を確認し、不足していれば GRANT で付与してください。次に多いのはスキーマ修飾の漏れです。別スキーマのテーブルを参照する場合は スキーマ名.テーブル名 で指定してください。①テーブル所有者から直接
GRANT SELECT ON table TO user で付与する②動的 SQL(
EXECUTE IMMEDIATE)を使うDROP TABLE(PURGE なし)で削除したテーブルはリサイクルビンに残ります。FLASHBACK TABLE テーブル名 TO BEFORE DROP で復元できます。ただし DROP TABLE ... PURGE で削除した場合はリサイクルビンに残らず、復元できません。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 |
権限の付与方法は「新規ユーザー作成と権限付与の完全ガイド」、シノニムの管理は「シノニムを確認する方法」、スキーマとクロススキーマアクセスは「スキーマ完全ガイド」も併せて参照してください。
