PL/SQLのパッケージを保守していると、「このパッケージを直すと、どこまで影響するのか」「INVALIDになったオブジェクトをどの順に直すべきか」を確認したくなります。Oracleでは ALL_DEPENDENCIES を使うと、パッケージ、プロシージャ、ファンクション、ビュー、トリガーなどの静的な依存関係を確認できます。
この記事では、ALL_DEPENDENCIES の基本だけでなく、依存方向の読み方、影響範囲の調べ方、循環依存の検出、Graphviz用の出力、INVALID再コンパイルへつなげる判断まで、実務で使う形に寄せて整理します。
ALL_DEPENDENCIESで「依存元」と「参照先」を正しく読む方法- あるパッケージが参照しているオブジェクトを階層表示するSQL
- 変更したオブジェクトの影響を受けるPL/SQLを探すSQL
- 外部スキーマ参照、循環依存、INVALIDを確認する観点
- 再コンパイル順序を誤らないための考え方
INVALIDの確認や再コンパイルそのものは 依存オブジェクトとINVALID再コンパイルの制御、権限まわりは AUTHIDと権限管理の設計 と合わせて読むと整理しやすくなります。
ALL_DEPENDENCIESで見るべき列
ALL_DEPENDENCIES は、「あるオブジェクトが、どのオブジェクトを参照しているか」を持つビューです。まずは列の意味をそろえます。
- OWNER / NAME / TYPE: 依存している側。パッケージやビューなど、変更影響を受ける可能性があるオブジェクトです。
- REFERENCED_OWNER / REFERENCED_NAME / REFERENCED_TYPE: 参照されている側。テーブル、ビュー、パッケージ、シノニムなどです。
- DEPENDENCY_TYPE: 依存の種別です。通常は
HARDとして扱う場面が多いです。
矢印で書くなら、OWNER.NAME -> REFERENCED_OWNER.REFERENCED_NAME です。左が依存元、右が参照先です。この向きを間違えると、影響調査と再コンパイル順序を逆に考えてしまいます。
SELECT owner, name, type, referenced_owner, referenced_name, referenced_type, dependency_type FROM all_dependencies WHERE owner = UPPER(:owner) AND name = UPPER(:object_name) ORDER BY type, referenced_owner, referenced_type, referenced_name;
まずはこのSQLで、対象オブジェクトが直接参照している相手を確認します。USER_DEPENDENCIES でも見られますが、複数スキーマをまたぐ保守では ALL_DEPENDENCIES を使い、所有者を明示したほうが誤読しにくくなります。
依存関係を階層でたどる
Oracleで依存を階層表示するなら、WITH RECURSIVE ではなく、CONNECT BY NOCYCLE またはOracleの再帰的サブクエリファクタリングを使います。ここではバージョン差の少ない CONNECT BY NOCYCLE で示します。
WITH dep AS (
SELECT
owner,
name,
type,
referenced_owner,
referenced_name,
referenced_type
FROM all_dependencies
WHERE owner = UPPER(:owner)
AND referenced_owner IS NOT NULL
)
SELECT
LEVEL AS depth,
LPAD(' ', (LEVEL - 1) * 2) || owner || '.' || name AS from_object,
referenced_owner || '.' || referenced_name AS to_object,
referenced_type,
SYS_CONNECT_BY_PATH(owner || '.' || name, ' -> ') AS path_text
FROM dep
START WITH owner = UPPER(:owner)
AND name = UPPER(:object_name)
CONNECT BY NOCYCLE
PRIOR referenced_owner = owner
AND PRIOR referenced_name = name
AND PRIOR referenced_type = type
ORDER SIBLINGS BY referenced_owner, referenced_type, referenced_name;
このSQLは「対象パッケージが何を参照しているか」を下流へたどるためのものです。たとえば PKG_ORDER が PKG_CUSTOMER を呼び、さらに PKG_CUSTOMER が別のビューを参照している場合、その連鎖を追えます。
ALL_DEPENDENCIES は静的な依存関係を中心に扱います。動的SQLで組み立てたテーブル名、文字列で呼び出すプロシージャ名、アプリケーション側からのSQL実行までは完全には拾えません。重要な変更では、ソース検索や実行ログも併用します。
変更影響を受けるオブジェクトを探す
テーブル、ビュー、パッケージ仕様などを変更したときに知りたいのは、「それを参照している側」です。つまり先ほどとは逆に、REFERENCED_OWNER / REFERENCED_NAME を起点にします。
WITH dep AS (
SELECT
owner,
name,
type,
referenced_owner,
referenced_name,
referenced_type
FROM all_dependencies
WHERE referenced_owner IS NOT NULL
)
SELECT
LEVEL AS depth,
owner || '.' || name AS affected_object,
type AS affected_type,
referenced_owner || '.' || referenced_name AS depends_on,
SYS_CONNECT_BY_PATH(owner || '.' || name, ' <- ') AS impact_path
FROM dep
START WITH referenced_owner = UPPER(:changed_owner)
AND referenced_name = UPPER(:changed_object)
CONNECT BY NOCYCLE
PRIOR owner = referenced_owner
AND PRIOR name = referenced_name
AND PRIOR type = referenced_type
ORDER BY depth, affected_type, affected_object;
この結果の depth=1 は直接影響、depth=2 以降は間接影響です。修正対象を洗い出すときは、まず直接影響を確認し、その後に間接影響をどこまでテスト対象に含めるかを判断します。
再コンパイル順序は参照される側から整える
依存関係の再コンパイルでは、基本的に「参照される側」を先に整えます。たとえば PKG_A が PKG_B を呼んでいるなら、先に PKG_B の仕様や本体を有効にし、その後で PKG_A を確認します。
UTL_RECOMP は便利ですが、根本原因を隠したまま再実行を繰り返すと原因調査が遅れます。SELECT
owner,
object_type,
object_name,
status,
last_ddl_time
FROM all_objects
WHERE status = 'INVALID'
AND owner = UPPER(:owner)
AND object_name IN (
SELECT name
FROM all_dependencies
WHERE owner = UPPER(:owner)
OR referenced_owner = UPPER(:owner)
)
ORDER BY object_type, object_name;
INVALIDの解消で迷ったら、依存関係の上流にあるオブジェクトから確認します。詳細な再コンパイル手順は USER_DEPENDENCIES・UTL_RECOMPの記事 で扱っています。
外部スキーマ参照を確認する
外部スキーマ参照の判定は、オブジェクト名にドットが含まれるかではなく、OWNER と REFERENCED_OWNER の差で見ます。シノニムを経由する場合もあるため、所有者列を使うほうが正確です。
SELECT owner || '.' || name AS object_name, type, referenced_owner || '.' || referenced_name AS referenced_object, referenced_type FROM all_dependencies WHERE owner = UPPER(:owner) AND referenced_owner IS NOT NULL AND referenced_owner <> owner ORDER BY referenced_owner, referenced_type, referenced_name;
本番環境だけでINVALIDになる場合は、外部スキーマへの直接GRANT不足、シノニムの向き違い、Definer Rights / Invoker Rightsの違いが原因になることがあります。権限設計は AUTHIDと権限管理の記事 も参考になります。
循環依存を見つける
パッケージ間で相互参照が増えると、変更影響が読みづらくなります。CONNECT_BY_ISCYCLE を使うと、循環の疑いがある経路を拾えます。
WITH dep AS (
SELECT
owner,
name,
type,
referenced_owner,
referenced_name,
referenced_type
FROM all_dependencies
WHERE owner = UPPER(:owner)
AND referenced_owner IS NOT NULL
)
SELECT
owner || '.' || name AS object_name,
referenced_owner || '.' || referenced_name AS referenced_object,
SYS_CONNECT_BY_PATH(owner || '.' || name, ' -> ') AS path_text
FROM dep
WHERE CONNECT_BY_ISCYCLE = 1
CONNECT BY NOCYCLE
PRIOR referenced_owner = owner
AND PRIOR referenced_name = name
AND PRIOR referenced_type = type
START WITH owner = UPPER(:owner);
循環依存が見つかったからといって、すぐに不具合とは限りません。ただし、仕様パッケージに共通型やインターフェースを寄せる、実装依存を分離するなど、依存方向を単純にできないか検討する価値があります。
Graphvizで依存関係を可視化する
依存関係が多い場合は、SQL結果を眺めるより図にしたほうが早いです。次のSQLはGraphvizのDOT形式に近い行を出力します。
SELECT 'digraph plsql_dependencies {' AS dot_line FROM dual
UNION ALL
SELECT ' "' || owner || '.' || name || '" -> "' ||
referenced_owner || '.' || referenced_name || '";' AS dot_line
FROM all_dependencies
WHERE owner = UPPER(:owner)
AND referenced_owner IS NOT NULL
AND type IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'VIEW', 'TRIGGER')
UNION ALL
SELECT '}' AS dot_line FROM dual;
出力した行を .dot ファイルに保存すれば、依存元から参照先への矢印として可視化できます。影響調査では、「変更対象へ向かっている矢印」と「変更対象から伸びている矢印」を分けて見ると混乱しにくくなります。
調査時のチェックリスト
- 依存の向きは
OWNER.NAME -> REFERENCED_OWNER.REFERENCED_NAMEと読めているか - 変更したいオブジェクトを参照しているPL/SQLを洗い出したか
- 外部スキーマ参照を
REFERENCED_OWNERで確認したか - 動的SQLやアプリケーション側SQLなど、ビューに出ない依存を別途確認したか
- INVALIDは参照される側から順に解消しているか
- 循環依存や過密な共通パッケージが変更リスクを高めていないか
まとめ
ALL_DEPENDENCIES は、PL/SQLの依存関係を読むための基本ビューです。重要なのは、単に一覧を出すことではなく、依存元と参照先の向きを正しく読み、変更影響と再コンパイル順序に落とし込むことです。
まず直接依存を確認し、必要に応じて階層表示、影響範囲、外部スキーマ参照、循環依存を確認します。そのうえでINVALIDや権限不足を切り分ければ、パッケージ改修時の調査漏れを減らせます。

