【完全版】ORA-00942: 表またはビューが存在しません エラーの原因と対処法
- 作成日 2026.06.16
- 更新日 2026.06.17
- Oracle Database
Oracle Databaseでクエリを実行した時、以下のエラーで弾かれた経験はありませんか?
ORA-00942: table or view does not exist
ORA-00942: 表またはビューが存在しません
「表が存在しません」とシンプルなメッセージですが、実際の原因は多岐にわたり、**「テーブルは確かに存在するのにエラーが出る」**ケースが頻発します。
- 別のユーザーで実行したら成功するのに、自分のユーザーでは失敗する
- SQL*Plusでは成功するのに、PL/SQLプロシージャ内では失敗する
- 大文字小文字を変えただけで成功した
ALL_TABLESでは見えているのにSELECTできない- 「
HR.EMPLOYEES」と書けば成功するが「EMPLOYEES」だと失敗する - 昨日まで動いていたバッチが今朝突然失敗する
本記事では、ORA-00942エラーのすべての原因と対処法を、現場で即使えるトラブルシューティング手順として整理します。スペルミス・大文字小文字問題、スキーマ指定、権限・ロール、シノニム、PL/SQL固有の挙動、CDB/PDB、リサイクルビンまで完全網羅。この1本でORA-00942の悩みが全て解決します。
- 1. 結論:今すぐ試すべき3ステップ
- 2. まず押さえる:ORA-00942が出る本当の意味
- 3. ORA-00942の原因カテゴリ
- 4. 【原因①】テーブル名のスペルミス・大文字小文字問題(最頻出)
- 5. 【原因②】スキーマ指定漏れ(別ユーザーのテーブル)
- 6. 【原因③】そもそも権限がない
- 7. 【原因④】PL/SQL内でロール経由の権限が無効化されている(要注意)
- 8. 【原因⑤】シノニムの問題
- 9. 【原因⑥】テーブルが本当に存在しない(削除済み・リサイクルビン)
- 10. 【原因⑦】CDB/PDB環境の接続コンテナ違い
- 11. 【原因⑧】CURRENT_SCHEMA が変更されている
- 12. 【原因⑨】ビューやマテリアライズドビューが INVALID
- 13. データディクショナリビュー(DBA_*)へのアクセスでORA-00942
- 14. プログラム言語別 ORA-00942 対処
- 15. 効率的な切り分けクエリ集
- 16. 関連エラーと違い
- 17. トラブルシューティング・チェックリスト
- 18. よくある質問(FAQ)
- 18.1. Q1. ALL_TABLESに表示されているのにSELECTすると ORA-00942 になります
- 18.2. Q2. SQL*Plusでは成功するのに、PL/SQLプロシージャ内で失敗します
- 18.3. Q3. 「HR.EMPLOYEES」と書けば成功するのに「EMPLOYEES」だと失敗します
- 18.4. Q4. 削除した覚えがないテーブルが消えています
- 18.5. Q5. 開発環境では成功するクエリが本番でORA-00942
- 18.6. Q6. データディクショナリのDBA_TABLES等にアクセスできません
- 18.7. Q7. テーブル名にハイフンを使ったらアクセスできません
- 18.8. Q8. ロールで権限を付けたのに認識されません
- 18.9. Q9. ORA-00942 と ORA-00904 の違いは?
- 18.10. Q10. CREATE TABLEは成功したのに、その直後のSELECTで ORA-00942
- 19. 参考リンク・関連資料
- 20. まとめ
結論:今すぐ試すべき3ステップ
時間がない方向けに、まず試すべき手順を示します。
ステップ1:テーブル名と大文字小文字を確認
-- 自分がアクセスできるテーブルを検索
SELECT OWNER, TABLE_NAME
FROM ALL_TABLES
WHERE UPPER(TABLE_NAME) LIKE '%EMP%';
ステップ2:スキーマを明示して試す
SELECT * FROM HR.EMPLOYEES;
ステップ3:権限の付与確認
-- 自分が持つテーブル権限
SELECT * FROM USER_TAB_PRIVS WHERE TABLE_NAME = 'EMPLOYEES';
それでも解決しない場合は、以下の詳細な原因分析へ進んでください。
まず押さえる:ORA-00942が出る本当の意味
Oracleにとって「表またはビューが存在しません」は、正確には以下のいずれかを意味します。
| 状況 | Oracleの判定 |
|---|---|
| 該当オブジェクトが本当に存在しない | ORA-00942 |
| オブジェクトはあるが、自分から見えない(権限なし) | ORA-00942 |
| オブジェクトはあるが、現在のスキーマでは未到達 | ORA-00942 |
| オブジェクトはあるが、シノニムが壊れている | ORA-00942 |
| PL/SQL内でロール経由の権限が機能していない | ORA-00942 |
重要なポイントは、Oracleはセキュリティ上の理由から「権限がない」と「存在しない」を区別せず、両方を「存在しません」として扱うことです。つまり**「ORA-00942」のメッセージだけでは原因を特定できない**のが厄介な点です。
ORA-00942の原因カテゴリ
| カテゴリ | 原因例 | 頻度 |
|---|---|---|
| スペル・大小文字系 | テーブル名タイプミス、引用符付きで作成 | 最多 |
| スキーマ系 | 別ユーザーのテーブルをスキーマ指定なしで参照 | 多 |
| 権限系 | SELECT/その他権限が付与されていない | 多 |
| シノニム系 | シノニム未作成、シノニムの参照先が消えている | 中 |
| PL/SQL固有 | ロール経由権限がパッケージ内で無効 | 中 |
| オブジェクト系 | 実際にテーブルが削除されている、リサイクルビンに移動 | 中 |
| CDB/PDB系 | 別コンテナに接続している | 中 |
| CURRENT_SCHEMA系 | セッションのデフォルトスキーマ変更 | 少 |
これらを順番にチェックすると効率的です。
【原因①】テーブル名のスペルミス・大文字小文字問題(最頻出)
最も多いケースです。Oracleの大小文字ルールを理解していないと、何度確認しても気付かないことがあります。
Oracleの大小文字ルール
| 作成方法 | データディクショナリ上の名前 | 参照時の指定 |
|---|---|---|
CREATE TABLE employees ... | EMPLOYEES(大文字に変換) | employees、EMPLOYEES、Employees すべて可 |
CREATE TABLE "employees" ... | employees(小文字のまま) | "employees" のみ可(引用符必須) |
CREATE TABLE "EmpData" ... | EmpData(混在のまま) | "EmpData" のみ可 |
ポイント: 二重引用符 "で囲んで作成された場合のみ、大小文字が保持されます。
確認方法:実際の名前を見る
-- 大小文字も含めて正確な名前を確認
SELECT OWNER, TABLE_NAME
FROM ALL_TABLES
WHERE UPPER(TABLE_NAME) = 'EMPLOYEES';
実行結果例:
OWNER TABLE_NAME
-------- ------------
HR EMPLOYEES ← 通常作成
APP Employees ← 引用符付きで作成(小文字混在)
引用符が必要な場合の対処
-- 小文字含みのテーブルにアクセス
SELECT * FROM APP."Employees";
引用符付きテーブルを作らない方が無難
トラブル防止のため、テーブル作成時は二重引用符を使わないことを推奨します。引用符付きはツール経由で意図せず作成されることもあるので、開発標準として禁止する企業も多いです。
ありがちなタイプミス
| 入力 | 想定 | 原因 |
|---|---|---|
EMPLOYE | EMPLOYEE | 末尾切れ |
EMPLOYESS | EMPLOYEES | 文字並べ替えミス |
EMP1OYEE | EMPLOYEE | l(L)と1混同 |
EMPLOYEE | EMPLOYEE | 全角文字混入 |
EMPLOYEE | EMPLOYEE | 末尾に空白 |
エディタやechoで文字列に余計な空白・改行・全角がないか確認してください。
【原因②】スキーマ指定漏れ(別ユーザーのテーブル)
Oracleでは、テーブルは**スキーマ(≒ユーザー)**に所属します。スキーマ指定なしでアクセスすると、現在ログインしているユーザーのスキーマ内だけが検索対象になります。
確認方法
-- 自分自身のスキーマ内のテーブル
SELECT TABLE_NAME FROM USER_TABLES;
-- アクセス可能な全テーブル(他スキーマ含む)
SELECT OWNER, TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME = 'EMPLOYEES';
対処:スキーマを明示する
-- 別スキーマ HR のテーブルを参照
SELECT * FROM HR.EMPLOYEES;
現在の自分のスキーマを確認
SELECT USER FROM DUAL;
-- 結果: SCOTT
SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') FROM DUAL;
-- 結果: SCOTT (デフォルトはUSERと同じ)
よくあるパターン
「SCOTTでログインしているのに、HRスキーマのテーブルにアクセスしたい場合スキーマ名を付ける必要があります。
-- ❌ NG(SCOTT.EMPLOYEESを探しに行く)
SELECT * FROM EMPLOYEES;
-- ✅ OK
SELECT * FROM HR.EMPLOYEES;
スキーマ指定なしで使いたい場合は後述のシノニム作成またはCURRENT_SCHEMA変更で対応します。
【原因③】そもそも権限がない
ALL_TABLESにすら表示されない場合は、SELECT権限が付与されていません。
自分が持っている権限を確認
-- テーブル権限
SELECT * FROM USER_TAB_PRIVS WHERE TABLE_NAME = 'EMPLOYEES';
-- ロール経由の権限
SELECT * FROM USER_ROLE_PRIVS;
-- 該当ロールに含まれる権限
SELECT * FROM ROLE_TAB_PRIVS WHERE ROLE = 'MY_ROLE';
対処:権限の付与
オブジェクト所有者またはDBAで実行:
-- 個別ユーザーへの付与
GRANT SELECT ON HR.EMPLOYEES TO scott;
-- ロール経由
GRANT SELECT ON HR.EMPLOYEES TO READONLY_ROLE;
GRANT READONLY_ROLE TO scott;
-- PUBLIC(全ユーザー)への付与
GRANT SELECT ON HR.EMPLOYEES TO PUBLIC;
⚠️ PUBLICへの付与はセキュリティリスクが高いため、業務要件と慎重に照らし合わせてください。
権限を付与した直後に試す
-- アクセス可能になったか確認
SELECT * FROM ALL_TABLES WHERE TABLE_NAME = 'EMPLOYEES';
-- 実際にクエリ
SELECT * FROM HR.EMPLOYEES;
権限を付与しても現在のセッションでは反映されない場合があります。一度ログアウト・再ログインすると確実です。
【原因④】PL/SQL内でロール経由の権限が無効化されている(要注意)
これはOracleの仕様で多くの開発者がハマるポイントです。
問題の再現
-- ユーザーSCOTTにロール経由でEMPLOYEES参照権限を付与
GRANT SELECT ON HR.EMPLOYEES TO READONLY_ROLE;
GRANT READONLY_ROLE TO scott;
-- SCOTTで実行
-- 直接クエリ:成功
SELECT * FROM HR.EMPLOYEES; -- ✅ OK
-- PL/SQLブロック内:ORA-00942!
CREATE OR REPLACE PROCEDURE get_emp_count IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM HR.EMPLOYEES; -- ❌ ORA-00942
END;
/
原因:DEFINER権限モードのPL/SQL
Oracleのストアド・プロシージャ/関数/パッケージは、デフォルトで**DEFINER権限モード(定義者権限)**で実行されます。このモードでは:
- 「ロール経由で付与された権限」は無効
- 「直接付与された権限」のみ有効
対処法1:権限を直接付与する(推奨)
-- ロール経由ではなく直接付与
GRANT SELECT ON HR.EMPLOYEES TO scott;
これでPL/SQL内でも参照可能になります。
対処法2:INVOKER権限モードに変更
PL/SQLを「呼び出し元の権限」で動かす場合:
CREATE OR REPLACE PROCEDURE get_emp_count
AUTHID CURRENT_USER -- ← INVOKER権限モード
IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM HR.EMPLOYEES;
END;
/
ただしINVOKERモードはセキュリティ・パフォーマンスへの影響もあるため、設計時に検討が必要です。
この罠の見抜き方
ORA-00942が出るが、直接SQL*Plusで実行すれば成功する → ロール経由の権限疑い
-- これで違いを確認
SELECT * FROM HR.EMPLOYEES; -- 成功
EXEC get_emp_count; -- ORA-00942
成功と失敗が分かれたら、この原因で確定です。
【原因⑤】シノニムの問題
シノニムは「テーブルへの別名」です。シノニム経由でアクセスしている場合、シノニム自体や参照先に問題があるとORA-00942になります。
シノニムの種類
| 種類 | 範囲 | 作成権限 |
|---|---|---|
| プライベートシノニム | 作成者のスキーマ内 | 通常ユーザーで可能 |
| パブリックシノニム | 全ユーザーから参照可能 | CREATE PUBLIC SYNONYM権限が必要 |
シノニムの確認
-- 自分のプライベートシノニム
SELECT SYNONYM_NAME, TABLE_OWNER, TABLE_NAME
FROM USER_SYNONYMS;
-- 全シノニム(パブリック含む)
SELECT * FROM ALL_SYNONYMS WHERE SYNONYM_NAME = 'EMPLOYEES';
-- DBA権限がある場合
SELECT * FROM DBA_SYNONYMS WHERE SYNONYM_NAME = 'EMPLOYEES';
シノニムを作る
-- 自分専用(プライベート)
CREATE SYNONYM employees FOR HR.EMPLOYEES;
-- 全員用(パブリック)DBA権限必要
CREATE PUBLIC SYNONYM employees FOR HR.EMPLOYEES;
シノニムが壊れている場合
シノニムが指す参照先テーブルが削除されると、シノニム自体は残りますが使えません:
SELECT * FROM employees;
-- ORA-00980: synonym translation is no longer valid
-- または ORA-00942
シノニムの状態確認
-- シノニムが指す先と状態
SELECT
s.SYNONYM_NAME,
s.TABLE_OWNER,
s.TABLE_NAME,
CASE WHEN o.OBJECT_NAME IS NULL THEN 'BROKEN' ELSE 'OK' END AS STATUS
FROM ALL_SYNONYMS s
LEFT JOIN ALL_OBJECTS o
ON s.TABLE_OWNER = o.OWNER
AND s.TABLE_NAME = o.OBJECT_NAME
WHERE s.SYNONYM_NAME = 'EMPLOYEES';
修復方法
-- 壊れたシノニムを再作成
CREATE OR REPLACE SYNONYM employees FOR HR.EMPLOYEES;
-- 削除して作り直し
DROP SYNONYM employees;
CREATE SYNONYM employees FOR HR.EMPLOYEES;
【原因⑥】テーブルが本当に存在しない(削除済み・リサイクルビン)
テーブルがDROP TABLEで削除された場合に発生します。
削除されたかどうかの確認
-- リサイクルビンを確認
SELECT * FROM USER_RECYCLEBIN;
10g以降、削除されたテーブルはリサイクルビンに入ります。完全削除されていなければ復元可能です。
リサイクルビンからの復元
-- 元の名前で復元
FLASHBACK TABLE employees TO BEFORE DROP;
-- 別名で復元
FLASHBACK TABLE employees TO BEFORE DROP RENAME TO emp_recovered;
完全削除されているか
DROP TABLE ... PURGEで削除された場合はリサイクルビンにも残らず、フラッシュバック・テクノロジーの範囲外なら復元不可能です。バックアップからのリストアが必要です。
ALL_OBJECTSで存在確認
-- 削除済みでもないか含めて全オブジェクトから検索
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM ALL_OBJECTS
WHERE OBJECT_NAME = 'EMPLOYEES';
無効化状態(STATUS = 'INVALID')のビュー・シノニムも検出できます。
【原因⑦】CDB/PDB環境の接続コンテナ違い
12c以降のマルチテナント環境では、接続しているコンテナを間違えるとORA-00942が出ます。
現在の接続先を確認
SHOW CON_NAME
-- または
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL;
PDB別のテーブル存在確認
-- 全PDBを横断確認(CDBルートから・DBA権限)
SELECT CON_ID, OWNER, TABLE_NAME
FROM CDB_TABLES
WHERE TABLE_NAME = 'EMPLOYEES';
PDB切り替え
-- 別PDBに切り替え
ALTER SESSION SET CONTAINER = ORCLPDB1;
-- 確認
SHOW CON_NAME;
-- テーブルアクセス
SELECT * FROM HR.EMPLOYEES;
よくあるパターン
開発環境ではPDBが1つだが、本番環境では複数PDBが存在し、別のPDBに接続して「テーブルがない」になるケースが多発します。Oracle環境管理の際はサービス名でPDBを明示する運用がおすすめです。
詳しいCDB/PDBの操作は[Oracleバージョン確認の記事]内のマルチテナントセクションを参照してください。
【原因⑧】CURRENT_SCHEMA が変更されている
セッションのデフォルトスキーマを変更している場合、意図しないスキーマを参照します。
CURRENT_SCHEMA の確認
SELECT
USER AS SESSION_USER,
SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS CURRENT_SCHEMA
FROM DUAL;
USERとCURRENT_SCHEMAが異なる場合、CURRENT_SCHEMAが優先されます。
CURRENT_SCHEMA の変更・リセット
-- 一時的に別スキーマで作業
ALTER SESSION SET CURRENT_SCHEMA = HR;
-- 元に戻す
ALTER SESSION SET CURRENT_SCHEMA = SCOTT;
ログイントリガで自動設定されているケースもあるため、想定外の動作の場合は確認してください:
SELECT TRIGGER_NAME, TRIGGERING_EVENT, TRIGGER_BODY
FROM DBA_TRIGGERS
WHERE TRIGGERING_EVENT LIKE '%LOGON%';
【原因⑨】ビューやマテリアライズドビューが INVALID
参照先のテーブル変更によりビューが無効化された場合、SELECTするとORA-00942(または別の関連エラー)が出ます。
INVALID なオブジェクトを確認
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM ALL_OBJECTS
WHERE STATUS = 'INVALID'
ORDER BY OWNER, OBJECT_TYPE;
再コンパイル
-- 単一ビューの再コンパイル
ALTER VIEW HR.EMP_VIEW COMPILE;
-- スキーマ全体のINVALID対象を一括再コンパイル
EXEC DBMS_UTILITY.COMPILE_SCHEMA('HR');
依存関係の調査
-- そのビューが依存しているオブジェクト
SELECT * FROM ALL_DEPENDENCIES
WHERE OWNER = 'HR' AND NAME = 'EMP_VIEW';
データディクショナリビュー(DBA_*)へのアクセスでORA-00942
DBA_TABLES、DBA_USERS等にアクセスするにはDBA権限または専用ロールが必要です。
確認
-- 自分の持つロール
SELECT * FROM USER_ROLE_PRIVS;
対処
DBA権限のあるユーザーが付与:
-- カタログ参照ロール付与
GRANT SELECT_CATALOG_ROLE TO scott;
-- またはSELECT ANY DICTIONARY権限
GRANT SELECT ANY DICTIONARY TO scott;
権限がない時の代替手段
DBA_TABLESの代わりに、ほぼ同等の情報を返すALL_TABLESを使ってください:
-- これは権限不要
SELECT * FROM ALL_TABLES;
プログラム言語別 ORA-00942 対処
Python(python-oracledb)
import oracledb
try:
conn = oracledb.connect(user="scott", password="tiger", dsn="//host:1521/ORCL")
cursor = conn.cursor()
cursor.execute("SELECT * FROM EMPLOYEES")
except oracledb.DatabaseError as e:
error, = e.args
if error.code == 942:
print("ORA-00942: テーブルが見つかりません")
print("以下を確認してください:")
print("- スペル・大文字小文字")
print("- スキーマ指定(例: HR.EMPLOYEES)")
print("- 権限の有無")
# トラブルシュート用にALL_TABLESを検索
cursor.execute("""
SELECT OWNER, TABLE_NAME FROM ALL_TABLES
WHERE UPPER(TABLE_NAME) LIKE :name
""", name='%EMPLOYEES%')
print("\n類似テーブル:")
for row in cursor:
print(f" {row[0]}.{row[1]}")
Java(JDBC)
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEES")) {
// ...
} catch (SQLException e) {
if (e.getErrorCode() == 942) {
System.err.println("ORA-00942: テーブルが存在しません");
System.err.println("確認事項:");
System.err.println("- テーブル名のスペル");
System.err.println("- スキーマ.テーブル名 形式での指定");
System.err.println("- SELECT権限の付与状況");
}
}
Node.js(node-oracledb)
try {
const result = await conn.execute('SELECT * FROM EMPLOYEES');
} catch (err) {
if (err.errorNum === 942) {
console.error('ORA-00942: テーブル/ビュー未発見');
// 類似テーブル検索
const r = await conn.execute(
`SELECT OWNER, TABLE_NAME FROM ALL_TABLES
WHERE UPPER(TABLE_NAME) LIKE '%EMPLOYEES%'`
);
console.log('類似テーブル:', r.rows);
}
}
効率的な切り分けクエリ集
ORA-00942のトラブルシューティングで頻用するSQL集です。
①テーブルがどこかに存在するか調査
-- スキーマ無視で全DBから検索(DBA権限)
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM DBA_OBJECTS
WHERE OBJECT_NAME = 'EMPLOYEES';
-- 部分一致版
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE
FROM DBA_OBJECTS
WHERE UPPER(OBJECT_NAME) LIKE '%EMP%'
AND OBJECT_TYPE IN ('TABLE', 'VIEW', 'SYNONYM');
②自分のアクセス可能オブジェクト
-- アクセス可能なテーブル+ビュー
SELECT OWNER, OBJECT_NAME, OBJECT_TYPE
FROM ALL_OBJECTS
WHERE OBJECT_NAME = 'EMPLOYEES';
③自分の権限ですべて見える
SELECT TABLE_NAME, OWNER FROM ALL_TAB_PRIVS WHERE GRANTEE = USER;
SELECT TABLE_NAME, OWNER FROM ALL_TAB_PRIVS_RECD;
④シノニム経由かどうか
SELECT * FROM ALL_SYNONYMS WHERE SYNONYM_NAME = 'EMPLOYEES';
⑤実行中のSQLでどのオブジェクトを参照しているか
EXPLAIN PLAN を取れば、エラー原因の特定に役立ちます:
EXPLAIN PLAN FOR SELECT * FROM HR.EMPLOYEES;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
関連エラーと違い
ORA-00980: synonym translation is no longer valid
シノニムが指す参照先テーブルが存在しなくなった時に出る、ORA-00942の親戚です。
-- シノニム名は存在するが参照先テーブルがない
SELECT * FROM my_emp_syn;
対処: シノニムを再作成、または参照先テーブルを復元。
ORA-04063: package body has errors
PL/SQLパッケージのコンパイルエラー。中身を見るとORA-00942が原因のこともあります。
-- エラー詳細
SHOW ERRORS;
-- または
SELECT * FROM USER_ERRORS WHERE NAME = 'YOUR_PACKAGE';
ORA-01031: insufficient privileges
権限不足ですが、操作によってはORA-00942の代わりにこちらが出ることがあります。SELECTで出るのは稀ですが、INSERT/UPDATE/DELETE時に発生しがちです。
トラブルシューティング・チェックリスト
ORA-00942が出た時に上から順にチェックする手順です。
- テーブル名のスペル・大小文字確認
ALL_TABLESまたはALL_OBJECTSでアクセス可能か検索- スキーマを明示(
HR.EMPLOYEES形式)して再実行 USER_TAB_PRIVSで自分の権限確認- PL/SQL内ならロール経由権限を疑う → 直接付与に変更
- シノニムの状態確認 → 必要なら再作成
- CDB/PDB接続コンテナ確認 →
SHOW CON_NAME - CURRENT_SCHEMA設定確認
- オブジェクトのINVALID状態確認 → 再コンパイル
- リサイクルビン確認 → 必要なら復元
よくある質問(FAQ)
Q1. ALL_TABLESに表示されているのにSELECTすると ORA-00942 になります
可能性として:
- テーブル名に小文字や記号が含まれている(引用符付き作成) →
SELECT * FROM HR."MyTable"; - スキーマ指定が必要な状態 →
HR.テーブル名形式 - 権限がSELECTではなく別のものだけ → INSERT権限はあるがSELECT権限がない
-- 持っている権限を詳しく確認
SELECT * FROM ALL_TAB_PRIVS
WHERE TABLE_NAME = 'EMPLOYEES' AND GRANTEE = USER;
Q2. SQL*Plusでは成功するのに、PL/SQLプロシージャ内で失敗します
ロール経由の権限がDEFINER権限モードでは無効になるOracle仕様が原因です。本記事の原因④を参照し、権限を直接付与してください。
Q3. 「HR.EMPLOYEES」と書けば成功するのに「EMPLOYEES」だと失敗します
スキーマ指定なしでアクセスしたい場合は、以下のいずれか:
-- シノニム作成
CREATE SYNONYM employees FOR HR.EMPLOYEES;
-- CURRENT_SCHEMA変更
ALTER SESSION SET CURRENT_SCHEMA = HR;
シノニムが推奨です(セッション横断で使えるため)。
Q4. 削除した覚えがないテーブルが消えています
考えられる原因:
- 他のDBAユーザーが削除した → 監査ログ確認
- バッチプロセスが定期削除している → アプリログ確認
- リサイクルビンを確認 → 復元可能なら
FLASHBACK TABLE
-- リサイクルビン確認
SELECT * FROM USER_RECYCLEBIN;
-- DBA権限なら
SELECT * FROM DBA_RECYCLEBIN;
Q5. 開発環境では成功するクエリが本番でORA-00942
ありがちな原因:
- 本番にはテーブルが配置されていない(マイグレーション漏れ)
- 権限付与スクリプトが本番に未適用
- CDB/PDBが本番だけ複数あり、別PDBに接続している
- シノニムが本番で作成されていない
環境差分の確認が最優先です。
Q6. データディクショナリのDBA_TABLES等にアクセスできません
DBA権限のあるユーザーから:
GRANT SELECT_CATALOG_ROLE TO scott;
または個別のビューへ:
GRANT SELECT ON DBA_TABLES TO scott;
ただし通常開発者には付与しません。ALL_TABLESで代替してください。
Q7. テーブル名にハイフンを使ったらアクセスできません
ハイフン-は識別子として無効なため、引用符必須です:
-- 作成時から引用符
CREATE TABLE "my-table" (id NUMBER);
-- アクセス時も引用符
SELECT * FROM "my-table";
引用符付きはトラブルの元なので、テーブル名にハイフンを使うのは避けるのが無難です。アンダースコア_を使ってください。
Q8. ロールで権限を付けたのに認識されません
DEFINER権限モードのPL/SQL以外でも、以下のケースで起きます:
- ロールがデフォルトで有効化されていない
- セッションで
SET ROLEしていない
-- ロールの状態確認
SELECT * FROM SESSION_ROLES;
-- 明示的にロールを有効化
SET ROLE my_role;
-- またはパスワード付き
SET ROLE my_role IDENTIFIED BY mypassword;
Q9. ORA-00942 と ORA-00904 の違いは?
| エラー | 意味 |
|---|---|
| ORA-00942 | テーブル/ビューが存在しない |
| ORA-00904 | 列が存在しない |
SELECT 存在しない列 FROM 存在するテーブル → ORA-00904 SELECT 列名 FROM 存在しないテーブル → ORA-00942
両方ともセキュリティ理由で「権限なし」と「存在なし」を区別しません。
Q10. CREATE TABLEは成功したのに、その直後のSELECTで ORA-00942
考えられる原因:
- トランザクションが別 (新しいセッションでアクセスしている)
- CREATE文と異なるスキーマで実行している
- CREATE文がエラーで実際は作成されていない(戻り値を確認)
- 同名のシノニムが既存で混乱
直接 SELECT * FROM USER_TABLES; で確認してください。
参考リンク・関連資料
Oracle公式ドキュメント
- Oracle Database Error Messages – ORA-00942 – 公式エラー解説
- Oracle Database Concepts – Schema Objects – スキーマオブジェクト概念
- Oracle Database SQL Language Reference – GRANT – 権限付与
- Oracle Database PL/SQL Language Reference – DEFINER and INVOKER – PL/SQL権限モード
データディクショナリビュー
- Oracle Database Reference – ALL_TABLES
- Oracle Database Reference – USER_TAB_PRIVS
- Oracle Database Reference – DBA_OBJECTS
フラッシュバック・テクノロジー
関連エラー記事(本サイト)
- ORA-01017: invalid username/password エラー対処 – 認証エラー
- ORA-12541: TNS no listener エラー対処 – リスナー接続エラー
- ORA-12154: TNS could not resolve エラー対処 – 接続識別子エラー
- ORA-01555: snapshot too old エラー対処(準備中)
- ORA-00060: deadlock detected エラー対処(準備中)
関連Oracle記事(本サイト)
- [Oracleテーブル一覧の取得方法] – ALL_TABLES/DBA_TABLES詳細
- [Oracleユーザー一覧の取得方法] – 権限管理
- [Oracleバージョン確認の方法]
- [Oracle directoryの確認方法]
まとめ
ORA-00942は単純なエラーメッセージとは裏腹に、8種類以上の原因があります。要点を再整理します。
- 「存在しない」≠「本当に無い」: 権限がないだけでも同じエラーになる
- 大小文字に注意: 引用符付きで作成されたテーブルは厳密一致が必要
- スキーマ指定の習慣: 業務上は
スキーマ.テーブル形式が安全 - PL/SQL内のロール権限の罠: 直接付与に切り替える
- シノニム経由は壊れることもある: 定期的な健全性チェック
- CDB/PDBコンテナ確認: マルチテナント環境では必須
- トラブルシュートには
ALL_OBJECTS: 自分のアクセス範囲を俯瞰
これらの知識は、開発・保守・障害対応・運用引き継ぎなど、Oracleを扱うあらゆる場面で必須です。本記事をブックマークしておけば、ORA-00942に遭遇した時の対応が大幅に効率化されます。
本記事は2026年6月時点の情報をもとに、Oracle Database 19c / 21c / 23ai / 26ai での動作確認・公式ドキュメントに基づき作成しています。バージョンによっては挙動が異なる場合があるため、最新の情報はOracle公式ドキュメントもあわせてご確認ください。
-
前の記事
【完全版】ORA-01555: snapshot too old エラーの原因と対処法 2026.06.16
-
次の記事
ORA-00060: deadlock detected エラーの原因と対処法|Oracleデッドロックの仕組み 2026.06.16
コメントを書く