【Oracle】ORA-01031 完全ガイド|insufficient privileges(権限不足)の原因・ロールと PL/SQL の落とし穴・対処法まで解説

Oracle で SQL を実行したとき、ORA-01031: insufficient privileges(権限が不十分です)が発生することがあります。このエラーは「操作に必要な権限がユーザーに付与されていない」ことを示しますが、原因は単純な権限未付与だけでなく、ロール経由の権限が PL/SQL 内で有効にならないという Oracle 特有の仕様が絡む場合があります。

この記事でわかること

  • ORA-01031 が発生する主な原因パターン
  • 現在の権限を USER_SYS_PRIVS / USER_TAB_PRIVS / SESSION_PRIVS で確認する方法
  • ロール経由の権限が DEFINER RIGHTS の PL/SQL で無効になる理由と対処法
  • GRANT 文でシステム権限・オブジェクト権限を付与する手順
  • EXECUTE IMMEDIATE・動的 SQL での ORA-01031 のパターン
スポンサーリンク

ORA-01031 が発生する主なパターン

パターン 典型的なケース 対処法
オブジェクト権限の未付与 他スキーマのテーブルへの SELECT・INSERT・UPDATE・DELETE・EXECUTE GRANT SELECT ON owner.table_name TO user
システム権限の未付与 CREATE TABLE・CREATE VIEW・ALTER SYSTEM など GRANT CREATE TABLE TO user
PL/SQL でのロール権限無効 ロール経由で付与された権限が DEFINER RIGHTS の PL/SQL 内で使えない 権限を直接 GRANT する
ビュー・シノニムの参照エラー ビューの基底テーブルや参照先スキーマへの権限がない 基底テーブルへの権限を付与する
DDL の実行権限不足 ALTER TABLE / DROP TABLE / TRUNCATE TABLE など DBA または対象オブジェクトの所有者に依頼する

現在の権限を確認する

現在のユーザーの権限を確認する
-- 現在ログイン中のユーザーを確認する
SELECT USER FROM DUAL;

-- システム権限(CREATE TABLE・CONNECT など)を確認する
SELECT privilege, admin_option
FROM   USER_SYS_PRIVS
ORDER  BY privilege;

-- オブジェクト権限(特定テーブルへの SELECT・INSERT など)を確認する
SELECT owner, table_name, privilege, grantable
FROM   USER_TAB_PRIVS
WHERE  grantee = USER
ORDER  BY owner, table_name, privilege;

-- 現在のセッションで有効な権限(ロール経由を含む)を確認する
-- SESSION_PRIVS: ロール経由の権限も含めて現在セッションで有効な権限
SELECT privilege FROM SESSION_PRIVS ORDER BY privilege;

-- 付与されているロールを確認する
SELECT granted_role, default_role
FROM   USER_ROLE_PRIVS
ORDER  BY granted_role;

-- ロール経由で付与されているオブジェクト権限を確認する(DBA 権限が必要)
SELECT r.granted_role, tp.owner, tp.table_name, tp.privilege
FROM   USER_ROLE_PRIVS r
JOIN   ROLE_TAB_PRIVS tp ON r.granted_role = tp.role
ORDER  BY r.granted_role, tp.owner, tp.table_name;

最重要: ロール経由の権限が PL/SQL 内で有効にならない

Oracle の PL/SQL はデフォルトで DEFINER RIGHTS(定義者権限)で動作します。この場合、プロシージャ内ではロール経由で付与された権限が無効になり、直接 GRANT された権限のみが有効です。

具体的には: ユーザー A に DBA ロールが付与されていても、ユーザー A が所有するプロシージャ内で SELECT * FROM dba_objects などを実行するとORA-01031 が発生します。DBA ロールではなく、直接 SELECT ANY TABLE などが必要です。

ロール権限が PL/SQL で無効になるパターンと対処法
-- ユーザー APP_USER に CONNECT・RESOURCE ロールが付与されている
-- RESOURCE ロールには CREATE TABLE などの権限が含まれる

-- NG: ロール経由の権限でプロシージャ内の DDL は実行できない
CREATE OR REPLACE PROCEDURE create_temp_table AS
BEGIN
    EXECUTE IMMEDIATE 'CREATE TABLE work_temp (id NUMBER)';
    -- ORA-01031 が発生する(RESOURCE ロール経由の CREATE TABLE は無効)
END;
/

-- 対処: CREATE TABLE 権限を直接 GRANT する
-- ※DBA がコマンドを実行する
GRANT CREATE TABLE TO app_user;  -- ロール経由ではなく直接付与する

-- 確認: USER_SYS_PRIVS に CREATE TABLE が直接付与されているかどうか確認
SELECT privilege FROM USER_SYS_PRIVS WHERE privilege = 'CREATE TABLE';

-- 別テーブルを参照する場合もロール権限は無効
CREATE OR REPLACE PROCEDURE read_other_schema AS
    v_count NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_count FROM other_schema.some_table;
    -- ORA-01031 が発生する(ロール経由の SELECT 権限は DEFINER RIGHTS では無効)
END;
/

-- 対処: 直接権限を付与する(DBA または所有者が実行)
GRANT SELECT ON other_schema.some_table TO app_user;

-- AUTHID CURRENT_USER (INVOKER RIGHTS) にすれば呼び出し元の権限で動く
CREATE OR REPLACE PROCEDURE read_other_schema
AUTHID CURRENT_USER   -- ← 呼び出しユーザーの権限(ロール含む)で実行される
AS
    v_count NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_count FROM other_schema.some_table;
    -- 呼び出しユーザーが other_schema.some_table の SELECT 権限を持っていれば成功する
END;
/

GRANT 文で権限を付与する

オブジェクト権限とシステム権限の GRANT
-- オブジェクト権限の付与(DBA または所有者が実行)
GRANT SELECT ON hr.employees TO app_user;                       -- 1テーブルへの SELECT
GRANT SELECT, INSERT, UPDATE ON hr.orders TO app_user;          -- 複数権限の一括付与
GRANT SELECT ON hr.employees TO app_user WITH GRANT OPTION;     -- 再付与権限付き
GRANT SELECT ANY TABLE TO app_user;                             -- 任意テーブルの SELECT(強力)
GRANT EXECUTE ON hr.process_pkg TO app_user;                    -- パッケージの実行権限

-- スキーマ内の全テーブルへの SELECT を一括付与する(PL/SQL ループ)
BEGIN
    FOR t IN (SELECT table_name FROM dba_tables WHERE owner = 'HR') LOOP
        EXECUTE IMMEDIATE 'GRANT SELECT ON HR.' || t.table_name || ' TO APP_USER';
    END LOOP;
END;
/

-- システム権限の付与
GRANT CREATE SESSION TO app_user;      -- ログイン権限
GRANT CREATE TABLE   TO app_user;      -- テーブル作成
GRANT CREATE VIEW    TO app_user;      -- ビュー作成
GRANT CREATE PROCEDURE TO app_user;    -- プロシージャ・関数・パッケージ作成
GRANT CREATE SEQUENCE  TO app_user;    -- シーケンス作成
GRANT CREATE TRIGGER   TO app_user;    -- トリガー作成

-- 権限の剥奪
REVOKE SELECT ON hr.employees FROM app_user;
REVOKE CREATE TABLE FROM app_user;

-- 付与した権限を確認する(DBA 権限が必要)
SELECT grantee, owner, table_name, privilege, grantable
FROM   DBA_TAB_PRIVS
WHERE  owner = 'HR'
ORDER  BY grantee, table_name;

まとめ

  • ORA-01031 の主な原因:オブジェクト権限(SELECT・EXECUTE など)またはシステム権限(CREATE TABLE など)が未付与。または PL/SQL でのロール権限の制限
  • 権限確認:USER_SYS_PRIVS(直接付与のシステム権限)・USER_TAB_PRIVS(オブジェクト権限)・SESSION_PRIVS(ロール経由も含む有効な権限)で確認する
  • DEFINER RIGHTS(デフォルト):PL/SQL はロール経由の権限が無効。直接 GRANT が必要。ロールを使いたい場合は AUTHID CURRENT_USER(INVOKER RIGHTS)に変更する
  • GRANT の対象:特定テーブルへの権限は所有者または DBA が GRANT する。SELECT ANY TABLE などのシステム権限は DBA のみが付与できる
  • ビュー・シノニム:アクセス先がビューやシノニムの場合、基底テーブルへの権限も必要な場合がある

権限管理全般については Oracle VPD(Virtual Private Database)完全ガイドも参照してください。PL/SQL の AUTHID(定義者権限と呼び出し者権限)の詳細は Oracle パッケージ完全ガイドも参照してください。