【完全ガイド】ORA-01031: insufficient privileges の原因と解決方法|GRANT・ROLE・PL/SQL の罠まで徹底解説

【完全ガイド】ORA-01031: insufficient privileges の原因と解決方法|GRANT・ROLE・PL/SQL の罠まで徹底解説

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 を根本から解決できるようになります。


目次

結論:まず現状の権限を確認

時間がない方向けに、最速の対処を先に示します。

現在の権限確認クエリ

-- 自分のシステム権限
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 TABLEGRANT CREATE TABLE TO user;
オブジェクト権限SELECT ON tGRANT SELECT ON t TO user;
ロールDBA, CONNECTGRANT DBA TO user;

5つの解決策

#手法使う場面
オブジェクト権限 GRANT特定テーブル/ビュー
システム権限 GRANTCREATE 系
ロール作成 + 付与複数権限をまとめて
AUTHID CURRENT_USERPL/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 公式


まとめ

ORA-01031: insufficient privileges の要点を再整理します。

権限の3種類

種類GRANT
システム権限CREATE TABLEGRANT CREATE TABLE TO user;
オブジェクト権限SELECT ON tGRANT SELECT ON t TO user;
ロールDBAGRANT 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 ViewCREATE 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

項目DEFINERINVOKER
実行時の権限定義者実行者
ロール権限無効有効
セキュリティ

予防のベストプラクティス

  • 最小権限の原則
  • ロールの活用
  • 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)もあわせてご確認ください。