PLS-00201: identifier 'xxx' must be declared は、PL/SQLが参照した識別子を解決できない時に発生するコンパイルエラーです。識別子とは、変数名、定数名、パッケージ名、プロシージャ名、ファンクション名、型名、表名、列名、シノニム名などを指します。
単なるスペルミスだけでなく、宣言位置がスコープ外、別スキーマのオブジェクトをスキーマ修飾していない、必要な EXECUTE / SELECT 権限が直接付与されていない、シノニムがない、パッケージ仕様部に公開されていない、という理由でも発生します。
PLS-00201が出たら、まずエラー行の識別子が「変数」「パッケージ」「型」「表・列」「シノニム」のどれかを分けます。変数なら宣言位置とスコープ、パッケージや型なら
ALL_OBJECTS と ALL_TAB_PRIVS、表やビューなら存在・スキーマ名・直接権限を確認します。PL/SQLではロール経由の権限が効かない場面があるため、権限不足も必ず疑ってください。- PLS-00201とは
- まず確認する順番
- USER_ERRORSでエラー位置を確認する
- 変数や定数が未宣言のケース
- スコープ外の変数を参照しているケース
- パッケージやプロシージャが見えないケース
- ユーザー定義TYPEが見えないケース
- %TYPEや%ROWTYPEで別スキーマを参照するケース
- AUTHID DEFINER / CURRENT_USERと権限の違い
- パッケージ仕様部に公開されていないケース
- 表やビューが見えないケース
- シノニムで解決できていないケース
- DBMS_OUTPUTでPLS-00201になるケース
- ORA-06550と一緒に出る場合
- よくある原因と対処一覧
- 本番障害時の調査SQLセット
- PLS-00201と関連エラーの違い
- 修正チェックリスト
- よくある質問
- まとめ
- 参考
PLS-00201とは
Oracle公式の説明では、PLS-00201は「参照された識別子を宣言する必要がある」ことを示すエラーです。また、識別子を参照するには権限が必要であり、ストアドオブジェクトではロールではなく直接付与された権限が必要になる場合があります。
よくある表示は次のような形です。
| 表示例 | よくある意味 | 最初に見る場所 |
|---|---|---|
PLS-00201: identifier 'V_NAME' must be declared |
変数や定数が未宣言、またはスコープ外 | DECLARE部、ブロック範囲 |
PLS-00201: identifier 'PKG_ORDER.SYNC' must be declared |
パッケージ名・サブプログラム名・権限の問題 | ALL_OBJECTS / ALL_ARGUMENTS |
PLS-00201: identifier 'MASTER_SCHEMA.UTIL_PKG' must be declared |
別スキーマのパッケージが見えない | GRANT EXECUTE / シノニム |
PLS-00201 + ORA-06550 |
PL/SQLブロック内の識別子解決失敗 | 後続のPLS-00201行 |
PLS-00201でオブジェクトが見えない場合、権限不足なら ORA-01031の原因と対処、表やビューが見えない場合は ORA-00942の原因と解決方法 も近い内容です。
まず確認する順番
PLS-00201は原因の幅が広いため、エラーになった識別子の種類を先に分けると早いです。次の順番で確認します。
| 順番 | 確認すること | 使うもの |
|---|---|---|
| 1 | エラー行と列番号 | USER_ERRORS.LINE / POSITION |
| 2 | 識別子の種類 | 変数、パッケージ、型、表、列、シノニム |
| 3 | ローカル宣言の有無 | DECLARE部、パッケージ仕様部 |
| 4 | スコープ外ではないか | 内側/外側ブロック、ラベル |
| 5 | オブジェクトが存在するか | ALL_OBJECTS / ALL_TABLES |
| 6 | 直接権限があるか | ALL_TAB_PRIVS / USER_TAB_PRIVS |
| 7 | シノニムやスキーマ修飾が必要か | ALL_SYNONYMS |
USER_ERRORSでエラー位置を確認する
ストアドプロシージャやパッケージのコンパイル時に出た場合は、まず USER_ERRORS で行番号と列番号を確認します。複数エラーがある場合は、先頭のPLS-00201が後続エラーの原因になっていることがあります。
SELECT name,
type,
sequence,
line,
position,
text
FROM user_errors
WHERE text LIKE '%PLS-00201%'
ORDER BY name, type, sequence;
コンパイルエラー全般の読み方は PL/SQLコンパイル時エラーとUSER_ERRORSの使い方 も参考になります。
変数や定数が未宣言のケース
最も単純な原因は、変数や定数を宣言していない、または宣言名と参照名が違うケースです。PL/SQLでは、利用する変数は DECLARE 部やブロック内で先に宣言しておく必要があります。
-- NG: v_nameを宣言していない BEGIN DBMS_OUTPUT.PUT_LINE(v_name); END; / -- PLS-00201: identifier 'V_NAME' must be declared -- OK: DECLARE部で宣言する DECLARE v_name VARCHAR2(100) := 'Alice'; BEGIN DBMS_OUTPUT.PUT_LINE(v_name); END; /
DBMS_OUTPUT の使い方や SET SERVEROUTPUT ON については DBMS_OUTPUTの使い方 も確認してください。
スコープ外の変数を参照しているケース
宣言しているのにPLS-00201になる場合は、スコープ外から参照している可能性があります。内側ブロックで宣言した変数は、外側ブロックからは見えません。
DECLARE
v_outer NUMBER := 10;
BEGIN
DECLARE
v_inner NUMBER := 20;
BEGIN
DBMS_OUTPUT.PUT_LINE(v_outer + v_inner); -- OK
END;
DBMS_OUTPUT.PUT_LINE(v_inner); -- NG: ここでは見えない
END;
/
-- PLS-00201: identifier 'V_INNER' must be declared
同名変数が内側と外側にある場合は、内側の宣言が優先されます。外側を明示したい場合はブロックラベルを使う方法もあります。
パッケージやプロシージャが見えないケース
別スキーマのパッケージやプロシージャを呼ぶ時は、スキーマ修飾、存在確認、EXECUTE権限を確認します。名前が正しくても、実行ユーザーから見えなければPLS-00201になります。
-- 呼び出し先が見えるか確認 SELECT owner, object_name, object_type, status FROM all_objects WHERE object_name = 'UTIL_PKG' ORDER BY owner, object_type; -- EXECUTE権限があるか確認 SELECT owner, table_name, privilege, grantee FROM all_tab_privs WHERE table_name = 'UTIL_PKG' ORDER BY owner, grantee, privilege; -- 付与する例(所有者側で実行) GRANT EXECUTE ON master_schema.util_pkg TO app_schema;
呼び出し元がストアドプロシージャやパッケージの場合、ロール経由の権限ではなく直接付与された権限が必要になることがあります。SQL Developerで手動実行できるのに、パッケージのコンパイルではPLS-00201になる典型パターンです。
ユーザー定義TYPEが見えないケース
オブジェクト型、コレクション型、パッケージ内の型を引数や変数で使う時にもPLS-00201が出ます。特に別スキーマで定義されたTYPEを使う場合は、型そのものへの EXECUTE 権限と、正しいスキーマ修飾が必要です。
-- 型が存在するか確認
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_name IN ('ORDER_REC_TYPE', 'ORDER_TAB_TYPE')
AND object_type IN ('TYPE', 'TYPE BODY')
ORDER BY owner, object_type, object_name;
-- TYPEへのEXECUTE権限を確認
SELECT owner, table_name, privilege, grantee
FROM all_tab_privs
WHERE table_name IN ('ORDER_REC_TYPE', 'ORDER_TAB_TYPE')
ORDER BY owner, table_name, grantee;
-- 付与例
GRANT EXECUTE ON master_schema.order_rec_type TO app_schema;
GRANT EXECUTE ON master_schema.order_tab_type TO app_schema;
パッケージ仕様部の引数に別スキーマのTYPEを使っている場合、呼び出し側にもそのTYPEが見えている必要があります。パッケージ本体だけでなく、公開インターフェースで使う型の権限も確認してください。
%TYPEや%ROWTYPEで別スキーマを参照するケース
プロシージャ引数や変数宣言で table.column%TYPE や table%ROWTYPE を使う場合、その表や列をコンパイル時に解決できないとPLS-00201になります。別スキーマの表を参照するなら、スキーマ修飾と直接SELECT権限が必要です。
-- NGになりやすい例: 表が見えない、または列名が違う CREATE OR REPLACE PROCEDURE p_sync_customer( p_customer_id IN master_schema.customers.customer_id%TYPE ) AS BEGIN NULL; END; / -- 確認: 表と列が見えるか SELECT owner, table_name, column_name, data_type FROM all_tab_columns WHERE owner = 'MASTER_SCHEMA' AND table_name = 'CUSTOMERS' AND column_name = 'CUSTOMER_ID'; -- 権限付与例 GRANT SELECT ON master_schema.customers TO app_schema;
%TYPE は便利ですが、参照先の表や列が変更されるとコンパイルエラーになります。列名が違う場合は ORA-00904、表や権限が問題なら ORA-00942 の観点でも確認します。
AUTHID DEFINER / CURRENT_USERと権限の違い
PL/SQLの権限問題では、AUTHID DEFINER と AUTHID CURRENT_USER の違いも重要です。デフォルトのDefiner Rightsでは、定義者の権限で名前解決・実行され、ロール権限が効かない場面があります。Invoker Rightsでは、実行者側の権限や名前解決の影響を受けます。
| 方式 | 権限の見え方 | PLS-00201で見ること |
|---|---|---|
AUTHID DEFINER |
定義者の直接権限が中心 | 所有者に直接GRANTされているか |
AUTHID CURRENT_USER |
実行者の権限・名前解決が影響 | 実行ユーザーで対象が見えるか |
| ロール経由権限 | 手動SQLでは見えることがある | ストアドオブジェクトのコンパイルでは不足することがある |
-- Invoker Rightsの例
CREATE OR REPLACE PROCEDURE p_list_customers
AUTHID CURRENT_USER
AS
BEGIN
FOR r IN (SELECT customer_id FROM customers) LOOP
NULL;
END LOOP;
END;
/
-- 実行ユーザーごとに customers の解決先や権限が変わる点に注意
権限設計が絡む場合は、手動実行できるかだけでなく、どのユーザーでコンパイル・実行しているかを分けて確認します。
パッケージ仕様部に公開されていないケース
パッケージ本体の中にプロシージャが存在していても、仕様部に宣言されていなければ外部から呼び出せません。外部公開したいサブプログラムは、PACKAGE 仕様部に宣言します。
-- 仕様部: sync_orderだけ公開
CREATE OR REPLACE PACKAGE pkg_order AS
PROCEDURE sync_order;
END pkg_order;
/
-- 本体: private_helperは本体内だけで使える
CREATE OR REPLACE PACKAGE BODY pkg_order AS
PROCEDURE private_helper IS
BEGIN
NULL;
END;
PROCEDURE sync_order IS
BEGIN
private_helper;
END;
END pkg_order;
/
-- 外部から pkg_order.private_helper は呼べない
-- PLS-00201 になる
表やビューが見えないケース
PL/SQL内で別スキーマの表やビューを参照していてPLS-00201になることもあります。この場合は、スキーマ修飾、存在確認、直接SELECT権限を見ます。
-- 表やビューが見えるか確認
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_name = 'CUSTOMERS'
AND object_type IN ('TABLE', 'VIEW')
ORDER BY owner, object_type;
-- 権限付与例
GRANT SELECT ON master_schema.customers TO app_schema;
-- PL/SQL内ではスキーマ修飾して参照
SELECT customer_name
INTO v_name
FROM master_schema.customers
WHERE customer_id = p_customer_id;
列名ミスなら ORA-00904、表やビューの存在・権限問題なら ORA-00942 の切り分けも参考になります。
シノニムで解決できていないケース
シノニムを使う設計では、シノニムが存在しない、違う実体を向いている、実体への権限がない、という理由でPLS-00201になることがあります。シノニムは名前解決を助けますが、権限付与の代わりにはなりません。
SELECT owner,
synonym_name,
table_owner,
table_name,
db_link
FROM all_synonyms
WHERE synonym_name IN ('UTIL_PKG', 'CUSTOMERS')
ORDER BY owner, synonym_name;
-- シノニムを作成する例
CREATE SYNONYM app_schema.util_pkg FOR master_schema.util_pkg;
-- ただしEXECUTE権限も必要
GRANT EXECUTE ON master_schema.util_pkg TO app_schema;
DBMS_OUTPUTでPLS-00201になるケース
DBMS_OUTPUT.PUT_LINE でPLS-00201になる場合、単純なスペルミス、実行ユーザーの権限、または環境差で DBMS_OUTPUT パッケージが参照できない可能性があります。通常の環境ではPUBLICにEXECUTE権限がありますが、制限された環境では確認が必要です。
-- スペル確認: DBMS_OUTPUT.PUT_LINE が正しい
BEGIN
DBMS_OUTPUT.PUT_LINE('test');
END;
/
-- 権限確認
SELECT owner, table_name, privilege, grantee
FROM all_tab_privs
WHERE table_name = 'DBMS_OUTPUT'
ORDER BY grantee, privilege;
ORA-06550と一緒に出る場合
PLS-00201は、匿名ブロックやストアドオブジェクトのコンパイル時に ORA-06550 と一緒に出ることが多いです。この場合、ORA-06550はPL/SQL全体の失敗を示す入口で、直すべきなのは後続のPLS-00201です。
BEGIN unknown_pkg.run; END; / -- ORA-06550: line 2, column 3: -- PLS-00201: identifier 'UNKNOWN_PKG.RUN' must be declared -- ORA-06550: line 2, column 3: -- PL/SQL: Statement ignored
よくある原因と対処一覧
| 原因 | 確認すること | 対処 |
|---|---|---|
| 変数が未宣言 | DECLARE部にあるか | 変数・定数を宣言する |
| スコープ外 | 内側ブロックの変数を外側から見ていないか | 宣言位置を上げる、または引数で渡す |
| パッケージ名・サブプログラム名ミス | ALL_OBJECTS / ALL_PROCEDURES |
正しい名前・スキーマ修飾に直す |
| パッケージ仕様部に未公開 | PACKAGE仕様部に宣言があるか | 仕様部に公開宣言を追加する |
| 直接権限不足 | ALL_TAB_PRIVS |
所有者から直接GRANTする |
| シノニム不足 | ALL_SYNONYMS |
シノニム作成と実体への権限付与 |
| 表・ビューが見えない | ALL_OBJECTS / 権限 |
スキーマ修飾、SELECT権限付与 |
本番障害時の調査SQLセット
本番でPLS-00201が出た場合は、エラーメッセージに出ている識別子をもとに、存在、権限、シノニムを確認します。以下はパッケージや表を疑う時の調査SQLです。
DEFINE obj_name = 'UTIL_PKG'
SELECT owner, object_name, object_type, status
FROM all_objects
WHERE object_name = UPPER('&obj_name')
ORDER BY owner, object_type;
SELECT owner, table_name, privilege, grantee
FROM all_tab_privs
WHERE table_name = UPPER('&obj_name')
ORDER BY owner, grantee, privilege;
SELECT owner, synonym_name, table_owner, table_name, db_link
FROM all_synonyms
WHERE synonym_name = UPPER('&obj_name')
ORDER BY owner, synonym_name;
PLS-00201と関連エラーの違い
| エラー | 意味 | 見るべき場所 |
|---|---|---|
PLS-00201 |
識別子が宣言されていない、または見えない | 宣言、スコープ、権限、シノニム |
ORA-06550 |
PL/SQLブロック全体の失敗を示す入口 | 後続の PLS- エラー |
PLS-00905 |
参照しているオブジェクトが無効 | USER_ERRORS |
ORA-01031 |
権限不足 | 直接GRANTと実行ユーザー |
ORA-00942 |
表またはビューが存在しない、または見えない | 存在、スキーマ修飾、SELECT権限 |
ORA-00904 |
列名や識別子がSQLとして無効 | 列名、別名、引用符、大文字小文字 |
オブジェクトが無効化されている場合は PLS-00905の原因と解決方法、呼び出し先が実行時に使えない場合は ORA-06508の原因と解決方法 も確認してください。
修正チェックリスト
| 項目 | 確認内容 | OKの状態 |
|---|---|---|
| エラー位置 | 行番号・列番号を見たか | 対象識別子が特定できている |
| 宣言 | 変数や定数をDECLARE部で宣言したか | 参照前に宣言済み |
| スコープ | ブロック外から見えない変数を参照していないか | 参照範囲内にある |
| パッケージ | 仕様部に公開宣言があるか | 外部呼び出し可能 |
| 存在 | ALL_OBJECTS に対象があるか |
想定スキーマに存在 |
| 権限 | 直接GRANTされているか | EXECUTE/SELECTが直接付与済み |
| シノニム | 正しい実体を向いているか | 解決先と権限が一致 |
よくある質問
SELECTできるのにPL/SQLでPLS-00201になります
ロール経由の権限でSELECTできている可能性があります。ストアドプロシージャやパッケージでは、対象表やパッケージへの直接権限が必要になることがあります。
パッケージ内のプロシージャが見つかりません
パッケージ本体だけでなく、仕様部に宣言されているか確認してください。仕様部にないサブプログラムは外部から呼べません。
DBMS_OUTPUT.PUT_LINEでPLS-00201になります
まずスペルを確認します。特殊な権限制限がある環境では、DBMS_OUTPUT へのEXECUTE権限も確認してください。
シノニムを作れば解決しますか?
名前解決には役立ちますが、権限付与の代わりにはなりません。シノニム作成に加えて、実体オブジェクトへのEXECUTEやSELECT権限が必要です。
ORA-06550も一緒に出ています
ORA-06550はPL/SQLブロック全体の失敗を示す入口です。後続のPLS-00201に出ている識別子を直してください。
まとめ
PLS-00201は、PL/SQLが識別子を解決できない時に発生します。原因は、変数の未宣言、スコープ外参照、パッケージ仕様部に未公開、名前ミス、別スキーマ参照、直接権限不足、シノニム不足などです。
対応は、エラー行の識別子を特定し、ローカル宣言とスコープを確認し、オブジェクトなら ALL_OBJECTS、権限なら ALL_TAB_PRIVS、シノニムなら ALL_SYNONYMS を確認する流れです。PL/SQLではロール経由ではなく直接GRANTが必要になる場面があるため、権限不足を早めに疑うと解決が早くなります。
参考
PLS-00201 – Oracle Database Error Help
Coding PL/SQL Subprograms and Packages – Oracle Database Development Guide

