【完全ガイド】ORA-01031: insufficient privileges の原因と解決方法|GRANT・ROLE・PL/SQL の罠まで徹底解説
- 作成日 2026.07.23
- Oracle Database
Oracle DB を利用する上で必ず遭遇する権限エラー:
SELECT * FROM hr.employees;
-- ORA-01031: insufficient privileges
CREATE TABLE my_table (id NUMBER);
-- ORA-01031: insufficient privileges
BEGIN my_procedure; END;
/
-- ORA-01031: insufficient privileges
**「権限が不十分」**というシンプルなメッセージ。しかし、実際に対処しようとすると:
- どの権限が必要か分からない
- DBA に依頼するが、範囲が広すぎる/狭すぎる
- GRANT したのに動かない(!?)
- PL/SQL 内で発生(外では動く)(謎)
- Materialized View 作成で発生
- CDB / PDB 環境での権限
- DB Link 経由での権限
さらに、Oracle 開発者・DBA が驚くほどよくハマる罠があります:
-- 直接 SQL では動く
SELECT * FROM another_schema.table1; -- OK
-- しかし PL/SQL に入れると失敗
CREATE PROCEDURE my_proc IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM another_schema.table1;
END;
/
-- ORA-01031(謎の失敗)
理由: ロール経由の権限は、DEFINER Rights の PL/SQL 内では効かない。この Oracle 特有の複雑な権限モデルは、日本語圏で本質的な解説がほぼありません。
さらに、以下のような場合にも:
EXECUTE IMMEDIATEで動的 SQL 実行時CREATE MATERIALIZED VIEWで隠れたCREATE TABLE権限- CDB/PDB でのユーザーモデル(12c+)
- AUTHID CURRENT_USER の仕組み
- Oracle 23ai の新機能
など、深い理解が必要です。
本記事では、ORA-01031: insufficient privileges の完全な原因と解決方法を、リファレンスとして実用的に整理します。Oracle 権限体系の全体像、8大発生パターン、5つの解決策、PL/SQL の DEFINER/INVOKER Rights の罠、CDB/PDB 対応、Rails/Java/Python 対応、実践シナリオ、予防のベストプラクティス、FAQまで完全網羅。この1本で ORA-01031 を根本から解決できるようになります。
- 1. 結論:まず現状の権限を確認
- 2. まず理解する:Oracle 権限体系
- 3. 現状の権限確認
- 4. 【原因①】オブジェクトへのアクセス権不足
- 5. 【原因②】DDL 権限不足
- 6. 【原因③】システム管理系権限
- 7. 【原因④】PL/SQL 内での DEFINER Rights の罠
- 8. 【原因⑤】Materialized View での隠れ権限
- 9. 【原因⑥】ロール継承の落とし穴
- 10. 【原因⑦】CDB/PDB での権限
- 11. 【原因⑧】DB Link 経由
- 12. 5つの解決策 完全リファレンス
- 13. Rails / Java / Python 対応
- 14. 実践シナリオ
- 15. 予防のベストプラクティス
- 16. トラブルシューティング
- 17. よくある質問(FAQ)
- 17.1. Q1. DBA ロールを付与すれば全て解決?
- 17.2. Q2. CONNECT / RESOURCE の権限内容
- 17.3. Q3. PUBLIC への GRANT
- 17.4. Q4. GRANT SELECT ANY TABLE
- 17.5. Q5. AUTHID CURRENT_USER の副作用
- 17.6. Q6. SYSDBA と DBA の違い
- 17.7. Q7. Rails での対応
- 17.8. Q8. Autonomous DB での権限
- 17.9. Q9. AWS RDS Oracle
- 17.10. Q10. 一時的な権限昇格
- 17.11. Q11. Cross-Schema での PL/SQL
- 17.12. Q12. 権限のカスケード削除
- 18. 参考リンク
- 19. まとめ
結論:まず現状の権限を確認
時間がない方向けに、最速の対処を先に示します。
現在の権限確認クエリ
-- 自分のシステム権限
SELECT * FROM user_sys_privs;
-- 自分のオブジェクト権限
SELECT * FROM user_tab_privs;
-- 自分に付与されているロール
SELECT * FROM user_role_privs;
-- ロール経由の権限
SELECT * FROM role_sys_privs;
-- 現在有効なセッション権限
SELECT * FROM session_privs;
SELECT * FROM session_roles;
権限の3種類
| 種類 | 例 | GRANT 構文 |
|---|---|---|
| システム権限 | CREATE TABLE | GRANT CREATE TABLE TO user; |
| オブジェクト権限 | SELECT ON t | GRANT SELECT ON t TO user; |
| ロール | DBA, CONNECT | GRANT DBA TO user; |
5つの解決策
| # | 手法 | 使う場面 |
|---|---|---|
| ① | オブジェクト権限 GRANT | 特定テーブル/ビュー |
| ② | システム権限 GRANT | CREATE 系 |
| ③ | ロール作成 + 付与 | 複数権限をまとめて |
| ④ | AUTHID CURRENT_USER | PL/SQL でロール権限使用 |
| ⑤ | VIEW 経由でアクセス制御 | 細かい権限 |
PL/SQL の罠(重要)
-- ❌ ロール経由の権限は DEFINER Rights PL/SQL 内で無効
CREATE PROCEDURE my_proc IS ... -- デフォルト = DEFINER Rights
-- ✅ 対策1: AUTHID CURRENT_USER
CREATE PROCEDURE my_proc AUTHID CURRENT_USER IS ...
-- ✅ 対策2: 直接 GRANT(ロール経由でなく)
GRANT SELECT ON t TO user; -- ロールではなくユーザーに直接
詳細は以下で解説します。
まず理解する:Oracle 権限体系
権限の3種類
Oracle には3種類の権限があります:
システム権限(System Privileges)
データベース全体への操作権限:
-- 例
CREATE SESSION -- ログイン権限
CREATE TABLE -- テーブル作成
CREATE PROCEDURE -- ストアド作成
UNLIMITED TABLESPACE -- 全 tablespace 使用
SYSDBA -- DB管理者
オブジェクト権限(Object Privileges)
特定オブジェクトへの操作権限:
-- 例
SELECT ON hr.employees -- 参照
INSERT ON hr.employees -- 挿入
UPDATE ON hr.employees -- 更新
DELETE ON hr.employees -- 削除
EXECUTE ON hr.my_proc -- 実行
ロール(Roles)
権限の集まり、まとめて付与:
-- 事前定義ロール
CONNECT -- 基本接続
RESOURCE -- 基本オブジェクト作成
DBA -- 管理者
SELECT_CATALOG_ROLE -- カタログ参照
-- カスタムロール
CREATE ROLE developer;
GRANT CREATE TABLE, CREATE VIEW TO developer;
GRANT developer TO scott;
GRANT / REVOKE の構文
-- 付与
GRANT <privilege> TO <user_or_role> [WITH ADMIN OPTION];
GRANT <object_priv> ON <object> TO <user_or_role> [WITH GRANT OPTION];
-- 剥奪
REVOKE <privilege> FROM <user_or_role>;
WITH ADMIN OPTION / WITH GRANT OPTION
-- WITH ADMIN OPTION: 受け取ったユーザーが他に GRANT できる
GRANT CREATE TABLE TO user1 WITH ADMIN OPTION;
-- WITH GRANT OPTION: オブジェクト権限を他にGRANTできる
GRANT SELECT ON t TO user1 WITH GRANT OPTION;
現状の権限確認
決定版クエリ集
自分のシステム権限
SELECT * FROM user_sys_privs;
-- または
SELECT privilege FROM user_sys_privs ORDER BY 1;
自分のオブジェクト権限
SELECT owner, table_name, privilege, grantable
FROM user_tab_privs
ORDER BY owner, table_name, privilege;
自分のロール
SELECT granted_role, admin_option, default_role
FROM user_role_privs;
ロール経由の権限
-- システム権限
SELECT role, privilege
FROM role_sys_privs
WHERE role IN (SELECT granted_role FROM user_role_privs);
-- オブジェクト権限
SELECT role, owner, table_name, privilege
FROM role_tab_privs
WHERE role IN (SELECT granted_role FROM user_role_privs);
現在有効な権限
-- セッションで有効な権限
SELECT * FROM session_privs;
-- セッションで有効なロール
SELECT * FROM session_roles;
注意: role_sys_privs / role_tab_privs は現在有効なロールのみを含む。
DBA 用のクエリ
-- 全ユーザーのシステム権限
SELECT grantee, privilege, admin_option
FROM dba_sys_privs
WHERE grantee = 'SCOTT';
-- 全ユーザーのオブジェクト権限
SELECT grantee, owner, table_name, privilege
FROM dba_tab_privs
WHERE grantee = 'SCOTT';
-- ロール階層
SELECT * FROM dba_role_privs WHERE grantee = 'SCOTT';
権限確認関連の他のクエリは Oracle パラメータ確認(V$PARAMETER)の記事、ユーザー一覧確認は Oracle user_list の記事も参照してください。
【原因①】オブジェクトへのアクセス権不足
症状(最頻出)
-- SCOTT ユーザーが HR スキーマの表を参照
SELECT * FROM hr.employees;
-- ORA-01031: insufficient privileges
解決
DBA / HR ユーザーが GRANT:
GRANT SELECT ON hr.employees TO scott;
複数権限を一度に
GRANT SELECT, INSERT, UPDATE, DELETE ON hr.employees TO scott;
-- ALL で全て
GRANT ALL ON hr.employees TO scott;
PUBLIC への GRANT(要注意)
GRANT SELECT ON hr.employees TO PUBLIC;
-- 全ユーザーがアクセス可能に
セキュリティ上、慎重に。
GRANT OPTION
-- receiver が他ユーザーに再 GRANT できる
GRANT SELECT ON t TO scott WITH GRANT OPTION;
-- scott が更に GRANT
GRANT SELECT ON hr.t TO another_user;
チェーンを作れるが、管理が複雑になる。
【原因②】DDL 権限不足
症状
CREATE TABLE my_table (id NUMBER);
-- ORA-01031
必要な権限
-- 自スキーマにテーブル作成
CREATE TABLE
-- 別スキーマに作成
CREATE ANY TABLE
-- Tablespace 使用
UNLIMITED TABLESPACE
-- または
ALTER USER scott QUOTA UNLIMITED ON users;
解決
GRANT CREATE TABLE TO scott;
GRANT UNLIMITED TABLESPACE TO scott;
-- または quota
ALTER USER scott QUOTA UNLIMITED ON users;
CREATE SESSION(ログイン権限)
-- 新規ユーザーはログインすらできない
CREATE USER newuser IDENTIFIED BY pw;
-- newuser でログイン → ORA-01017 (invalid username/password)?
-- 実は ORA-01045: user has no CREATE SESSION privilege
-- 必要
GRANT CREATE SESSION TO newuser;
認証系の詳細は ORA-01017: invalid username/password の記事、接続系エラーは ORA-12154 / ORA-12541 の記事も参照してください。
CONNECT / RESOURCE ロール(伝統的)
-- 開発者向け(最小限)
GRANT CONNECT, RESOURCE TO developer;
-- Oracle 10gR2 以前: CONNECT に多くの権限
-- 現代: CONNECT = CREATE SESSION のみ
-- RESOURCE = CREATE TABLE, CREATE PROCEDURE 等
現代の CONNECT ロールは制限的。個別 GRANT 推奨。
【原因③】システム管理系権限
症状
ALTER SYSTEM SET open_cursors = 500;
-- ORA-01031
CREATE USER newuser IDENTIFIED BY pw;
-- ORA-01031
FLUSH SHARED_POOL;
-- ORA-01031
必要な権限
- ALTER SYSTEM: SYSDBA or ALTER SYSTEM 権限
- CREATE USER: CREATE USER 権限
- FLUSH: ALTER SYSTEM 権限
解決
GRANT ALTER SYSTEM TO scott;
GRANT CREATE USER TO scott;
システム管理系の詳細は Oracle パラメータ確認(V$PARAMETER)の記事、メモリ関連は ORA-04031: shared memory の記事も参照してください。
【原因④】PL/SQL 内での DEFINER Rights の罠
症状(超厄介)
-- 直接 SQL では動く
SELECT COUNT(*) FROM hr.employees; -- OK
-- ストアドプロシージャに入れると失敗
CREATE OR REPLACE PROCEDURE count_emp IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM hr.employees;
END;
/
BEGIN count_emp; END;
/
-- ORA-01031(謎の失敗)
原因:DEFINER Rights と ロール
PL/SQL のデフォルトは DEFINER Rights(定義者権限):
実行時に「作成者の権限」で動作
しかし、ロール経由の権限は無視される
→ 「作成者はロールで SELECT 権限あり」
→ 「でも PL/SQL 内では効かない」
→ ORA-01031
解決A: 直接 GRANT(推奨、シンプル)
-- ロールではなくユーザーに直接 GRANT
GRANT SELECT ON hr.employees TO scott;
-- ↑ 直接付与なので DEFINER Rights PL/SQL 内でも有効
解決B: AUTHID CURRENT_USER(INVOKER Rights)
CREATE OR REPLACE PROCEDURE count_emp
AUTHID CURRENT_USER IS
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM hr.employees;
END;
/
動作:
- 実行時に「実行者の権限」で動作
- ロール経由の権限も有効
DEFINER vs INVOKER Rights 比較
| 項目 | DEFINER (デフォルト) | INVOKER (AUTHID CURRENT_USER) |
|---|---|---|
| 実行時の権限 | 定義者 | 実行者 |
| ロール権限 | 無効 | 有効 |
| オブジェクト解決 | 定義者スキーマ | 実行者スキーマ |
| セキュリティ | 高(実行者は権限不要) | 実行者に権限必要 |
使い分け
DEFINER Rights:
- 実行者は権限なくても実行できる(API 的な用途)
- セキュリティ上安全
INVOKER Rights:
- 実行者の権限で動作
- ロール権限が効く
- 汎用ライブラリ的な用途
PL/SQL の呼び出しでロールが効かない理由
Oracle の設計:
- PL/SQL コンパイル時に権限チェック
- ロールは動的(session 単位)
- コンパイル時に「ロール経由の権限は保証されない」
→ 直接 GRANT を要求
【原因⑤】Materialized View での隠れ権限
症状(謎の失敗)
CREATE OR REPLACE PROCEDURE create_mv IS
BEGIN
EXECUTE IMMEDIATE 'CREATE MATERIALIZED VIEW mv_test AS SELECT * FROM t';
END;
/
BEGIN create_mv; END;
/
-- ORA-01031(謎)
原因
CREATE MATERIALIZED VIEW は内部的に CREATE TABLE と CREATE MVIEW の両方が必要:
- 直接 SQL: 自分のロール
RESOURCEにあるCREATE TABLE権限が有効 - PL/SQL 内(DEFINER): ロール経由の権限は無効 → 失敗
解決
-- 直接 GRANT
GRANT CREATE TABLE TO scott;
GRANT CREATE MATERIALIZED VIEW TO scott;
Materialized View 関連の詳細は Oracle MERGE 文 使い方の記事、集計最適化は Oracle ROWNUM vs ROW_NUMBER の記事も参照してください。
【原因⑥】ロール継承の落とし穴
症状
-- SCOTT に MY_ROLE 付与
GRANT my_role TO scott;
-- MY_ROLE に CREATE TABLE 付与
GRANT CREATE TABLE TO my_role;
-- SCOTT でログイン
SELECT * FROM session_roles;
-- MY_ROLE 表示
-- しかし、PL/SQL 内で
CREATE OR REPLACE PROCEDURE create_test IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE t (id NUMBER)';
END;
/
BEGIN create_test; END;
/
-- ORA-01031
原因
ロール経由の権限は PL/SQL DEFINER Rights 内で無効。
解決
-- SCOTT に直接 GRANT
GRANT CREATE TABLE TO scott;
-- または AUTHID CURRENT_USER
CREATE OR REPLACE PROCEDURE create_test
AUTHID CURRENT_USER IS ...
【原因⑦】CDB/PDB での権限
症状
Oracle 12c+ の Multitenant 環境:
-- CDB$ROOT で操作
SELECT * FROM cdb_data_files;
-- ORA-01031(PDB ユーザー)
対処
PDB ユーザーは CDB リソースを参照不可。
-- PDB に切り替え
ALTER SESSION SET CONTAINER = PDB1;
-- 該当スコープで操作
SELECT * FROM dba_data_files;
共通ユーザー vs ローカルユーザー
- 共通ユーザー(C##で始まる): CDB全体で存在
- ローカルユーザー: 特定 PDB のみ
-- 共通ユーザー作成(CDB$ROOT で)
CREATE USER c##admin IDENTIFIED BY pw CONTAINER = ALL;
GRANT CREATE SESSION TO c##admin CONTAINER = ALL;
-- ローカルユーザー(PDB で)
ALTER SESSION SET CONTAINER = PDB1;
CREATE USER local_user IDENTIFIED BY pw;
【原因⑧】DB Link 経由
症状
SELECT * FROM t@remote_db;
-- ORA-01031(リモート DB 側で権限不足)
原因
DB Link 経由でもリモート DB のユーザー権限が必要。
解決
リモート DB 側で GRANT:
-- リモート DB で
GRANT SELECT ON t TO scott;
DB Link 認証情報を確認:
SELECT db_link, username FROM user_db_links;
5つの解決策 完全リファレンス
解決策① オブジェクト権限 GRANT
GRANT SELECT ON hr.employees TO scott;
GRANT SELECT, INSERT, UPDATE, DELETE ON hr.employees TO scott;
GRANT ALL ON hr.employees TO scott;
解決策② システム権限 GRANT
GRANT CREATE TABLE TO scott;
GRANT CREATE PROCEDURE TO scott;
GRANT CREATE VIEW TO scott;
GRANT UNLIMITED TABLESPACE TO scott;
解決策③ ロール作成 + 付与
-- カスタムロール
CREATE ROLE app_dev;
GRANT CREATE TABLE, CREATE VIEW, CREATE PROCEDURE TO app_dev;
GRANT SELECT ON hr.employees TO app_dev;
-- ユーザーに付与
GRANT app_dev TO scott;
解決策④ AUTHID CURRENT_USER
CREATE OR REPLACE PROCEDURE my_proc
AUTHID CURRENT_USER IS
BEGIN
-- 実行者の権限で動作
-- ロール権限も有効
END;
/
解決策⑤ VIEW 経由でアクセス制御
-- 自スキーマに VIEW 作成
CREATE VIEW my_emp_view AS
SELECT id, name FROM hr.employees -- 制限された列
WHERE department_id = 10; -- 制限された行
-- 別ユーザーに VIEW への SELECT 権限
GRANT SELECT ON my_emp_view TO scott;
細かい行/列アクセス制御が可能。
Rails / Java / Python 対応
Rails ActiveRecord
# アプリユーザーは最小権限
# 事前に DBA が GRANT
# config/database.yml
production:
adapter: oracle_enhanced
username: rails_app
password: <%= ENV['DB_PASSWORD'] %>
database: prod_db
# Rails マイグレーションでは CREATE TABLE 権限必要
Rails 8 系の詳細は Rails 8 アップグレードガイドの記事、rails db:migrate 使い方の記事、Solid Queue 使い方の記事も参照してください。
Java (JDBC)
// アプリユーザーで接続
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@//host:1521/service",
"app_user", "password");
// ORA-01031 のキャッチ
try {
stmt.executeUpdate("...");
} catch (SQLException e) {
if (e.getErrorCode() == 1031) {
// 権限不足の対処
logger.error("Insufficient privileges: " + e.getMessage());
}
}
Python (oracledb)
import oracledb
try:
connection = oracledb.connect(
user="app_user", password="pw",
dsn="//host:1521/service"
)
cursor = connection.cursor()
cursor.execute("...")
except oracledb.DatabaseError as e:
error_obj, = e.args
if error_obj.code == 1031:
print("Insufficient privileges")
実践シナリオ
シナリオ1:新規開発者ユーザー作成
-- DBA として
CREATE USER dev1 IDENTIFIED BY temp_password;
-- 基本権限
GRANT CREATE SESSION TO dev1;
GRANT CREATE TABLE TO dev1;
GRANT CREATE VIEW TO dev1;
GRANT CREATE PROCEDURE TO dev1;
GRANT CREATE SEQUENCE TO dev1;
GRANT CREATE TRIGGER TO dev1;
-- Tablespace
ALTER USER dev1 QUOTA UNLIMITED ON users;
-- 一時 tablespace
ALTER USER dev1 TEMPORARY TABLESPACE temp;
-- パスワード変更を強制
ALTER USER dev1 PASSWORD EXPIRE;
シナリオ2:本番アプリユーザー(最小権限)
-- 最小限のシステム権限
GRANT CREATE SESSION TO app_prod;
-- 特定オブジェクトのみ
GRANT SELECT, INSERT, UPDATE, DELETE ON app.customers TO app_prod;
GRANT SELECT, INSERT ON app.orders TO app_prod;
GRANT SELECT ON app.products TO app_prod;
-- 特定 PROCEDURE の実行
GRANT EXECUTE ON app.pkg_business TO app_prod;
最小権限の原則(Least Privilege)。
シナリオ3:ロール設計
-- 読み取り専用ロール
CREATE ROLE app_reader;
GRANT SELECT ON app.customers TO app_reader;
GRANT SELECT ON app.orders TO app_reader;
GRANT SELECT ON app.products TO app_reader;
-- 更新ロール
CREATE ROLE app_writer;
GRANT app_reader TO app_writer; -- 継承
GRANT INSERT, UPDATE, DELETE ON app.customers TO app_writer;
GRANT INSERT, UPDATE ON app.orders TO app_writer;
-- 管理者ロール
CREATE ROLE app_admin;
GRANT app_writer TO app_admin;
GRANT DELETE ON app.orders TO app_admin;
GRANT CREATE TABLE, ALTER TABLE ON app.* TO app_admin;
-- ユーザーへ付与
GRANT app_reader TO analyst;
GRANT app_writer TO app_prod;
GRANT app_admin TO super_admin;
シナリオ4:PL/SQL パッケージの汎用化
-- INVOKER Rights で作成
CREATE OR REPLACE PACKAGE utils
AUTHID CURRENT_USER
AS
PROCEDURE process_data(p_table_name VARCHAR2);
END;
/
-- 各ユーザーが自分の権限で実行
BEGIN utils.process_data('MY_TABLE'); END;
/
シナリオ5:Docker Oracle での初期設定
docker exec -it oracle-xe sqlplus system/pw <<EOF
CREATE USER app IDENTIFIED BY app_pw;
GRANT CONNECT, RESOURCE TO app;
GRANT UNLIMITED TABLESPACE TO app;
EOF
Docker 関連は docker daemon 接続エラーの記事、Docker no space left on device の記事も参照してください。
シナリオ6:Kamal デプロイでのDB権限
# デプロイ環境の権限セットアップ
# 事前に DBA がユーザー作成
env:
clear:
DB_USER: rails_app
Kamal 2 デプロイの詳細は Kamal 2 デプロイの記事を参照してください。
シナリオ7:CDB/PDB での運用
-- CDB$ROOT で共通管理者
ALTER SESSION SET CONTAINER = CDB$ROOT;
CREATE USER c##global_admin IDENTIFIED BY pw CONTAINER = ALL;
GRANT DBA TO c##global_admin CONTAINER = ALL;
-- PDB で個別ユーザー
ALTER SESSION SET CONTAINER = PDB1;
CREATE USER pdb1_user IDENTIFIED BY pw;
GRANT CONNECT, RESOURCE TO pdb1_user;
シナリオ8:監査ログ
-- 権限変更を監査
AUDIT GRANT ANY PRIVILEGE;
AUDIT ROLE;
AUDIT ALTER USER;
-- 監査ログ確認
SELECT * FROM dba_audit_trail
WHERE action_name LIKE 'GRANT%'
ORDER BY timestamp DESC;
シナリオ9:権限の定期監査
-- 過剰権限ユーザー検出
SELECT grantee, granted_role
FROM dba_role_privs
WHERE granted_role IN ('DBA', 'IMP_FULL_DATABASE', 'EXP_FULL_DATABASE')
AND grantee NOT IN ('SYS', 'SYSTEM');
-- 未使用ユーザー
SELECT username, last_login
FROM dba_users
WHERE last_login < SYSDATE - 90
AND account_status = 'OPEN';
シナリオ10:Data Pump での権限
-- Data Pump 用ユーザー
CREATE USER dp_user IDENTIFIED BY pw;
GRANT CONNECT TO dp_user;
GRANT DATAPUMP_EXP_FULL_DATABASE TO dp_user;
GRANT DATAPUMP_IMP_FULL_DATABASE TO dp_user;
GRANT READ, WRITE ON DIRECTORY dp_dir TO dp_user;
Data Pump の詳細は Oracle Data Pump 使い方の記事を参照してください。
予防のベストプラクティス
1. 最小権限の原則
必要な権限のみを GRANT:
-- ❌ 過剰
GRANT DBA TO app_user;
-- ✅ 必要最小限
GRANT SELECT, INSERT, UPDATE ON app.customers TO app_user;
2. ロールの活用
類似ユーザーはロールでまとめる:
CREATE ROLE readonly;
CREATE ROLE readwrite;
GRANT SELECT ON schema.* TO readonly;
GRANT SELECT, INSERT, UPDATE, DELETE ON schema.* TO readwrite;
3. PL/SQL の権限モデル理解
- DEFINER: セキュリティ高、ロール権限使えない
- INVOKER (AUTHID CURRENT_USER): 汎用、ロール権限有効
4. 直接 GRANT vs ロール
PL/SQL 使用時は直接 GRANT も検討。
5. 定期的な権限監査
-- 月次監査
SELECT grantee, granted_role FROM dba_role_privs
WHERE granted_role IN ('DBA', ...);
6. AUDIT 有効化
AUDIT GRANT ANY PRIVILEGE;
AUDIT ROLE;
7. パスワードプロファイル
CREATE PROFILE strict_profile LIMIT
FAILED_LOGIN_ATTEMPTS 5
PASSWORD_LIFE_TIME 90
PASSWORD_REUSE_TIME 365;
ALTER USER scott PROFILE strict_profile;
8. 未使用ユーザーの管理
-- 90日以上未ログインをロック
ALTER USER old_user ACCOUNT LOCK;
9. 権限変更履歴の記録
-- カスタムトリガーで記録
CREATE TRIGGER audit_grant
AFTER GRANT ON DATABASE
...
10. ドキュメント化
- ユーザー権限マトリクス
- ロール定義
- 変更手順
トラブルシューティング
GRANT したのに動かない
ロール経由 + PL/SQL DEFINER の可能性:
-- 現在有効なロール確認
SELECT * FROM session_roles;
-- 直接 GRANT に変更
GRANT SELECT ON t TO user; -- ロールではなく直接
AUTHID の指定確認
SELECT object_name, authid
FROM user_procedures
WHERE object_name = 'MY_PROC';
ロールがデフォルト無効
-- デフォルトで有効にする
ALTER USER scott DEFAULT ROLE ALL;
-- または明示的にセット
SET ROLE my_role;
CDB/PDB の混乱
-- 現在のコンテナ確認
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL;
-- 切り替え
ALTER SESSION SET CONTAINER = PDB1;
DB Link での権限
-- リモート DB でも GRANT 必要
権限剥奪の連鎖
-- REVOKE で連鎖的に権限が消える
REVOKE SELECT ON t FROM user1;
-- user1 が WITH GRANT OPTION で付与した権限も消える
よくある質問(FAQ)
Q1. DBA ロールを付与すれば全て解決?
動くが危険。最小権限の原則違反。本番では絶対避ける。
Q2. CONNECT / RESOURCE の権限内容
- CONNECT: CREATE SESSION のみ(Oracle 10gR2+)
- RESOURCE: CREATE TABLE, PROCEDURE, TRIGGER 等(UNLIMITED TABLESPACE は含まない)
Q3. PUBLIC への GRANT
全ユーザーに付与。慎重に使う。
Q4. GRANT SELECT ANY TABLE
全スキーマの全テーブルを SELECT 可能。DBA 級の権限、慎重に。
Q5. AUTHID CURRENT_USER の副作用
- 実行者の権限で動作
- セキュリティ低下の可能性(実行者に権限必要)
Q6. SYSDBA と DBA の違い
- SYSDBA: OS 認証、DB 起動/停止可能、最強
- DBA: DB 内での管理者権限
Q7. Rails での対応
アプリユーザーに最小権限:
GRANT SELECT, INSERT, UPDATE, DELETE ON schema.* TO rails_app;
Q8. Autonomous DB での権限
多くの管理系権限は制限。ADMIN ユーザーで操作。
Q9. AWS RDS Oracle
マスターユーザーが最上位。SYSDBA は不可、限定的な DBA 権限。
Q10. 一時的な権限昇格
-- 一時的に強い権限
GRANT DBA TO scott;
-- 作業
REVOKE DBA FROM scott;
変更履歴を記録して。
Q11. Cross-Schema での PL/SQL
-- HR スキーマの PROCEDURE を SCOTT が実行
GRANT EXECUTE ON hr.my_proc TO scott;
-- + PROCEDURE 内での参照テーブルへの権限
Q12. 権限のカスケード削除
REVOKE SELECT ON t FROM user1 CASCADE CONSTRAINTS;
参考リンク
Oracle 公式
- Oracle Database Error Messages: ORA-01031
- Database Security Guide
- GRANT Statement
- Managing System Privileges
まとめ
ORA-01031: insufficient privileges の要点を再整理します。
権限の3種類
| 種類 | 例 | GRANT |
|---|---|---|
| システム権限 | CREATE TABLE | GRANT CREATE TABLE TO user; |
| オブジェクト権限 | SELECT ON t | GRANT SELECT ON t TO user; |
| ロール | DBA | GRANT DBA TO user; |
現状確認クエリ
-- 自分のシステム権限
SELECT * FROM user_sys_privs;
-- 自分のオブジェクト権限
SELECT * FROM user_tab_privs;
-- 自分のロール
SELECT * FROM user_role_privs;
-- 現在有効
SELECT * FROM session_privs;
SELECT * FROM session_roles;
8大発生パターン
| # | パターン | 対処 |
|---|---|---|
| ① | オブジェクトアクセス | GRANT SELECT ON t |
| ② | DDL 権限 | GRANT CREATE TABLE |
| ③ | システム管理系 | SYSDBA or 個別 GRANT |
| ④ | PL/SQL DEFINER の罠 | AUTHID CURRENT_USER or 直接 GRANT |
| ⑤ | Materialized View | CREATE TABLE + CREATE MV |
| ⑥ | ロール継承 | 直接 GRANT |
| ⑦ | CDB/PDB | 適切なコンテナ |
| ⑧ | DB Link | リモート側で GRANT |
PL/SQL の罠(重要)
-- ❌ DEFINER Rights + ロール経由 → 効かない
CREATE PROCEDURE p IS BEGIN ... END;
-- ✅ 対策
-- ① 直接 GRANT
GRANT SELECT ON t TO user;
-- ② AUTHID CURRENT_USER
CREATE PROCEDURE p AUTHID CURRENT_USER IS BEGIN ... END;
5つの解決策
-- ① オブジェクト権限
GRANT SELECT ON t TO user;
-- ② システム権限
GRANT CREATE TABLE TO user;
-- ③ ロール
CREATE ROLE r;
GRANT ... TO r;
GRANT r TO user;
-- ④ AUTHID CURRENT_USER
CREATE PROCEDURE p AUTHID CURRENT_USER IS ...
-- ⑤ VIEW でアクセス制御
CREATE VIEW v AS SELECT ... FROM t WHERE ...;
GRANT SELECT ON v TO user;
DEFINER vs INVOKER Rights
| 項目 | DEFINER | INVOKER |
|---|---|---|
| 実行時の権限 | 定義者 | 実行者 |
| ロール権限 | 無効 | 有効 |
| セキュリティ | 高 | 中 |
予防のベストプラクティス
- 最小権限の原則
- ロールの活用
- PL/SQL の権限モデル理解
- 定期的な権限監査
- AUDIT 有効化
- パスワードプロファイル
- 未使用ユーザー管理
- ドキュメント化
事故防止
- DBA ロールを気軽に付与しない
- ロール経由の権限は PL/SQL で効かない
- PUBLIC への GRANT は慎重に
- 本番と開発で権限モデル統一
- 変更履歴を記録
これらの知識は、Oracle での日常運用・セキュリティ管理・アプリ開発・Rails / Java / Python 開発・監査対応など、あらゆる場面で活用できます。本記事をブックマークしておけば、ORA-01031 に出会っても迷わず的確に対処できるようになります。
本記事は2026年6月時点の情報をもとに、Oracle Database 19c〜23ai での動作確認・公式ドキュメントに基づき作成しています。Oracle のバージョンにより挙動が異なる場合があるため、最新の情報は Oracle 公式ドキュメント(docs.oracle.com)もあわせてご確認ください。
-
前の記事
【完全ガイド】ORA-01858: a non-numeric character was found where a numeric was expected の原因と解決方法|TO_DATE の罠・NLS_DATE_FORMAT まで徹底解説 2026.07.22
-
次の記事
【完全ガイド】ORA-00600: internal error code の原因と解決方法|引数の読み方・MOS 検索・AHF/TFA まで徹底解説 2026.07.24
コメントを書く