プライマリ・コンテンツに移動
Oracle® Database開発ガイド
12c リリース1 (12.1)
B71295-06
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次
索引へ移動
索引

前
 
次
 

23 スキーマ・オブジェクトの依存性の理解

オブジェクトAの定義がオブジェクトBを参照している場合、AはBに依存します。この章では、スキーマ・オブジェクトの相互間の依存性と、Oracle Databaseがそのような依存性を自動的に追跡し管理する方法について説明します。こうした自動依存性管理により、AによってBの古いバージョンが使用されることがなく、Bの変更後にAを明示的に再コンパイルする必要もほとんどなくなります。

内容は次のとおりです。

23.1 スキーマ・オブジェクトの依存性の概要

スキーマ・オブジェクトのタイプによっては、定義の中で他のオブジェクトを参照できるものがあります。たとえば、ビューは表や他のビューを参照する問合せによって定義され、サブプログラムの本体の中には、他のオブジェクトを参照するSQL文を含めることができます。オブジェクトAの定義がオブジェクトBを参照している場合、Aは(Bの)依存オブジェクト、Bは(Aの)参照オブジェクトです。

例23-1は、データベース内の依存オブジェクト・タイプと参照オブジェクト・タイプの表示方法(DBAとしてログインしている場合)を示します。

例23-1 依存オブジェクト・タイプと参照オブジェクト・タイプの表示

依存オブジェクト・タイプの表示:

SELECT DISTINCT TYPE
FROM DBA_DEPENDENCIES
ORDER BY TYPE;

結果:

TYPE
------------------
DIMENSION
EVALUATION CONTXT
FUNCTION
INDEX
INDEXTYPE
JAVA CLASS
JAVA DATA
MATERIALIZED VIEW
OPERATOR
PACKAGE
PACKAGE BODY
PROCEDURE
RULE
RULE SET
SYNONYM
TABLE
TRIGGER
TYPE
TYPE BODY
UNDEFINED
VIEW
XML SCHEMA
 
22 rows selected.

参照オブジェクト・タイプの表示:

SELECT DISTINCT REFERENCED_TYPE
FROM DBA_DEPENDENCIES
ORDER BY REFERENCED_TYPE;

結果:

REFERENCED_TYPE
------------------
EVALUATION CONTXT
FUNCTION
INDEX
INDEXTYPE
JAVA CLASS
LIBRARY
OPERATOR
PACKAGE
PROCEDURE
SEQUENCE
SYNONYM
TABLE
TYPE
VIEW
XML SCHEMA

14 rows selected.

参照オブジェクトの定義を変更した場合、その変更の内容によって、依存オブジェクトがエラーなしに機能し続けることができない場合があります。たとえば、表を削除すると、その表に基づくビューは使用できなくなります。

一部の依存性のみを無効にするスキーマ・オブジェクトの変更例として、例23-2に示す2つのビューについて考えてみます。これらのビューは、HR.EMPLOYEES表に基づいています。

例23-2は、EMPLOYEES表から、表内のすべての列を選択するSIXFIGURESビューと、EMAIL列を含まないCOMMISSIONEDビューの2つを作成します。この例が示すように、EMAIL列を変更すると、SIXFIGURESは無効化されますが、COMMISSIONEDはされません。

例23-2 一部の依存オブジェクトを無効にするスキーマ・オブジェクトの変更

CREATE OR REPLACE VIEW sixfigures AS
SELECT * FROM employees
WHERE salary >= 100000;

CREATE OR REPLACE VIEW commissioned AS
SELECT first_name, last_name, commission_pct
FROM employees
WHERE commission_pct > 0.00;
 

SQL*Plus書式設定コマンド:

COLUMN object_name FORMAT A16

問合せ:

SELECT object_name, status
FROM user_objects
WHERE object_type = 'VIEW'
ORDER BY object_name;

結果:

OBJECT_NAME      STATUS
---------------- -------
COMMISSIONED     VALID
EMP_DETAILS_VIEW VALID
SIXFIGURES       VALID

3 rows selected.

EMPLOYEES表のEMAIL列を長くする:

ALTER TABLE employees MODIFY email VARCHAR2(100);

問合せ:

SELECT object_name, status
FROM user_objects
WHERE object_type = 'VIEW'
ORDER BY object_name;

結果:

OBJECT_NAME      STATUS
---------------- -------
COMMISSIONED     VALID
EMP_DETAILS_VIEW INVALID
SIXFIGURES       VALID

ビューは、その問合せ内で参照されているすべてのオブジェクトに依存します。例23-3のビューは、表employeesおよびdepartmentsによって変わります。

例23-3 複数のオブジェクトに依存するビュー

CREATE OR REPLACE VIEW v AS
  SELECT last_name, first_name, department_name
  FROM employees e, departments d
  WHERE e.department_id = d.department_id
  ORDER BY last_name;

注意:

  • CREATE文を実行すると、すべての依存性が自動的に更新されます。

  • 動的SQL文では、依存性は作成されません。たとえば次の文を実行しても、tab1に対する依存性は作成されません。

    EXECUTE IMMEDIATE 'SELECT * FROM tab1'
    

23.2 オブジェクトの依存性の問合せ

静的データ・ディクショナリ・ビューUSER_DEPENDENCIESALL_DEPENDENCIESおよびDBA_DEPENDENCIESには、データベース・オブジェクト間の依存性が表示されます。

utldtree.sql SQLスクリプトを実行すると、オブジェクト依存性ツリーに関する情報が表示されるビューDEPTREEと、DEPTREEをソートした印刷用のビューであるIDEPTREEが作成されます。


参照:

DEPTREEIDEPTREEおよびutldtree.sqlスクリプトの詳細は、『Oracle Databaseリファレンス』を参照してください。

23.3 オブジェクトのステータス

各データベース・オブジェクトには、表23-1に示すステータス値の1つが割り当てられています。

表23-1 データベース・オブジェクトのステータス

ステータス 意味

有効

オブジェクトが、データ・ディクショナリ内の現在の定義を使用して正常にコンパイルされた。

コンパイル・エラー

オブジェクトの最後のコンパイル実行時にエラーが発生した。

無効

参照先のオブジェクトが変更されたため、オブジェクトに無効とマークされている。(無効になるのは依存オブジェクトのみ。)

権限取消し

参照オブジェクトに対するアクセス権限が取り消された。(権限取消しの対象となるのは依存オブジェクトのみ。)



注意:

静的データ・ディクショナリ・ビューUSER_OBJECTSALL_OBJECTSおよびDBA_OBJECTSでは、「コンパイル・エラー」、「無効」、「権限取消し」はすべて同じものとみなされ、INVALIDと表示されます。

23.4 依存オブジェクトの無効化

オブジェクトAがオブジェクトBに、オブジェクトBがオブジェクトCにそれぞれ依存している場合、A、Bはそれぞれ、B、Cに対する直接依存オブジェクトであり、AはCに対する間接依存オブジェクトです。

直接依存オブジェクトは、それ自体に影響を与える参照オブジェクトへの変更(参照オブジェクトのシグネチャの変更)によってのみ無効になります。

間接依存オブジェクトは、それ自体に影響を与えない参照オブジェクトへの変更によって無効になることがあります。つまり、Cの変更によってBが無効になると、それによってA(およびBの他のすべての直接依存オブジェクトと間接依存オブジェクト)が無効になります。これを連鎖的な無効化と呼びます。

緩やかな無効化では、参照オブジェクトを変更するデータ定義言語(DDL)文によって、そのすべての依存オブジェクトが無効になります。

高度な無効化では、参照オブジェクトを変更するDDL文によって、次の文のいずれかに該当する依存オブジェクトのみが無効になります。

  • 依存オブジェクトが、DDL文によって変更された参照オブジェクトの属性に依存している場合

  • 依存オブジェクトのコンパイル済メタデータが、変更された参照オブジェクトに対して正しいものでなくなった場合

たとえば、ビューvが表tの列c1およびc2を選択している場合、tの列c3のみを変更するDDL文では、vは無効になりません。

DDL文CREATE OR REPLACE objectは、次の条件下では効果がありません。

  • objectPL/SQLオブジェクトで、新しいPL/SQLソース・テキストが既存のPL/SQLソース・テキストと同一であり、objectとともに保存されているPL/SQLコンパイル・パラメータ設定がセッション環境のパラメータ設定と同一である。

    PL/SQLコンパイル・パラメータ設定の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

  • objectシノニムで、この文はターゲット・オブジェクトを変更しません。

表23-2の左側の列の操作では高度な無効化が行われますが、右側の列のケースは例外です。右側の列のケース、および表23-2に示されていないすべての操作では、緩やかな無効化が行われます。

表23-2 高度な無効化が発生する操作

操作 例外

ALTER TABLE table ADD column

  • 依存オブジェクト(ビューを除く)で、tableSELECT *が使用された場合。

  • 依存オブジェクトで、table%rowtypeが使用された場合。

  • 依存オブジェクトで、列リストを指定することなくtableに対してINSERTが実行された場合。

  • 依存オブジェクトが、結合が含まれる問合せ内のtableを参照している場合。

  • 依存オブジェクトが、PL/SQL変数を参照する問合せ内のtableを参照している場合。

ALTER TABLE table {MODIFY|RENAME|DROP|SET UNUSED} column

ALTER TABLE table DROP CONSTRAINT not_null_constraint

  • 依存オブジェクトがcolumnを直接参照している場合。

  • 依存オブジェクトで、tableSELECT *が使用された場合。

  • 依存オブジェクトで、table%ROWTYPEが使用された場合。

  • 依存オブジェクトで、列リストを指定することなくtableに対してINSERTが実行された場合。

  • 依存オブジェクトが、行全体に依存するトリガーである(定義で列を指定していない)場合。

  • 依存オブジェクトが、削除された列の右側の列に依存するトリガーである場合。

CREATE OR REPLACE VIEW view

オンライン表再定義(DBMS_REDEFINITION)

新しい定義と以前の定義の列リストが異なり、次の1つ以上に該当する場合。

  • 依存オブジェクトが、ビューまたは表の新しい定義の中で修正または削除された列を参照している場合。

  • 依存オブジェクトで、view%rowtypeまたはtable%rowtypeが使用されている場合。

  • 依存オブジェクトで、列リストを指定することなくビューまたは表に対してINSERTが実行された場合。

  • ビューの新しい定義に新しい列が追加され、かつ結合が含まれている問合せ内のビューまたは表を依存オブジェクトが参照している場合。

  • ビューの新しい定義に新しい列が追加され、PL/SQLを参照する問合せ内のビューまたは表を依存オブジェクトが参照している場合。

  • 依存オブジェクトが、RELIES ON句でビューまたは表を参照している場合。

CREATE OR REPLACE SYNONYM synonym

  • 新旧のsynonymのターゲットが異なり、かつ一方が表ではない場合。

  • synonymの新旧のターゲットがどちらも表で、かつその2つの表の列リストまたは付与権限が異なる場合。

  • synonymの新旧のターゲットがどちらも表で、かつ依存オブジェクトがビューであり、そのビューが参照している列が以前のターゲットの一意索引に関与し、新しいターゲットの一意索引には関与していない場合。

DROP INDEX

  • 索引がファンクション索引であり、依存オブジェクトが、行全体に依存するトリガー、またはファンクション索引が作成された後でtableに追加された列に依存するトリガーである場合。

  • 索引が一意索引であり、依存オブジェクトがビューであって、かつそのビューが一意索引に関与している列を参照している場合。

CREATE OR REPLACE {PROCEDURE|FUNCTION}

コール・シグネチャが変更された場合。コール・シグネチャとは、パラメータ・リスト(パラメータの順序、名前および型)、戻り型、ACCESSIBLE BY句(ホワイト・リスト)、純粋度脚注1、決定性、並列度、パイプライン処理および(プロシージャまたはファンクションがCまたはJavaで実装されている場合は)実装の各プロパティを指します。

CREATE OR REPLACE PACKAGE

  • ACCESSIBLE BY句(ホワイト・リスト)が変更された場合。

  • 依存オブジェクトが、削除または名前変更されたパッケージ・アイテムを参照している場合。

  • 依存オブジェクトが参照しているパッケージ・プロシージャまたはパッケージ・ファンクションのコール・シグネチャまたはエントリ・ポイント番号脚注2が変更された場合。

    参照されているプロシージャまたはファンクションにオーバーロードの候補が複数ある場合、それらの候補のコール・シグネチャまたはエントリ・ポイント番号が変更されるか、候補が追加または削除されると、依存オブジェクトは無効。

  • 依存オブジェクトが参照しているパッケージ・カーソルのコール・シグネチャ、行タイプまたはエントリ・ポイント番号が変更された場合。

  • 依存オブジェクトが参照しているパッケージ・タイプまたはパッケージ・サブタイプの定義が変更された場合。

  • 依存オブジェクトが参照しているパッケージの変数または定数の名前、データ型、初期値、オフセット番号のいずれかが変更された場合。

  • パッケージ純粋度1が変更された場合。


脚注1 純粋度とは、SQL問合せ内部でPL/SQLファンクションを起動する際に不測の影響(予期せぬデータ変更など)が生じるのを回避するための一連のルールです。パッケージ純粋度とは、パッケージ初期化ブロック内のコードの純粋度を指します。

脚注2 プロシージャやファンクションのエントリ・ポイント番号は、PL/SQLパッケージ・コードにおける位置によって決まります。PL/SQLパッケージの最後に追加されたプロシージャやファンクションには、新しいエントリ・ポイント番号が付与されます。


注意:

表23-2の操作により無効化される依存オブジェクトが、静的データ・ディクショナリ・ビュー*_OBJECTSおよび*_OBJECTS_AEに反映されるのは、(コンパイル時または実行時に)そのオブジェクトの参照が試行された後、または次のいずれかのサブプログラムが起動された後です。
  • DBMS_UTILITY.COMPILE_SCHEMA(Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)

  • 任意のUTL_RECOMPサブプログラム(Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)


内容は次のとおりです。

23.4.1 セッションの状態と参照パッケージ

パッケージ構成を参照するセッションごとに、各パッケージの独自のインスタンスが存在します。このインスタンスには、パブリック変数とプライベート変数、カーソルおよび定数の永続的な状態が含まれます。その後、セッションのインスタンス化されたパッケージのいずれかが無効になった後、再度有効化されると、そのセッションのパッケージのインスタンス化は、状態も含めてすべて失われる可能性があります。


参照:

  • パッケージのインスタンス化の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

  • パッケージ状態の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。


23.4.2 セキュリティ認可

データ操作言語(DML)オブジェクト権限またはシステム権限をユーザーまたはPUBLICに対して付与または取り消すと、Oracle Databaseによって、その所有者のすべての依存オブジェクトが無効化されます。これは、依存オブジェクトの所有者が、すべての参照オブジェクトに関する必要な権限を引き続き持つことを確認するためです。

23.5 無効化を回避するためのガイドライン

依存オブジェクトの無効化を回避するには、次のガイドラインに従ってください。

23.5.1 パッケージの最後へのアイテムの追加

アイテムをパッケージに追加するときは、パッケージの最後に追加します。このようにすると、既存の最上位パッケージ・アイテムのエントリ・ポイント番号が維持され、それらのパッケージ・アイテムが無効になりません。

たとえば、次のパッケージについて考えます。

CREATE OR REPLACE PACKAGE pkg1 AUTHID DEFINER IS
  FUNCTION get_var RETURN VARCHAR2;
END;
/

次のようにアイテムをpkg1の最後に追加すると、get_varファンクションを参照する依存オブジェクトが無効になりません。

CREATE OR REPLACE PACKAGE pkg1 AUTHID DEFINER IS
  FUNCTION get_var RETURN VARCHAR2;
  PROCEDURE set_var (v VARCHAR2);
END;
/

次のようにアイテムをget_varファンクションとset_varプロシージャの間に挿入すると、set_varファンクションを参照する依存オブジェクトが無効になります。

CREATE OR REPLACE PACKAGE pkg1 AUTHID DEFINER IS
  FUNCTION get_var RETURN VARCHAR2;
  PROCEDURE assert_var (v VARCHAR2);
  PROCEDURE set_var (v VARCHAR2);
END;
/

23.5.2 ビューを介した各表の参照

ビューを使用して表を間接的に参照すると、次のことができるようになります。

  • 依存ビューまたは依存PL/SQLオブジェクトを無効にせずに、表に列を追加できます。

  • 依存オブジェクトを無効にせずに、ビューで参照されていない列を変更または削除できます。

CREATE OR REPLACE VIEW文を使用しても、新しいROWTYPEが古いROWTYPEと一致する場合は、既存のビューまたはその依存オブジェクトが無効になることはありません。

23.6 オブジェクトの再有効化

参照されたときに無効になっているオブジェクトは、使用できるように有効化する必要があります。有効化は、オブジェクトが参照されるときに自動的に行われます。ユーザーが明示的な操作を行う必要はありません。

オブジェクトが無効な場合、ステータスはコンパイル・エラー、権限取消し、または無効のいずれかです。これらの用語の定義は、表23-1を参照してください。

内容は次のとおりです。

23.6.1 コンパイルされたがエラーがあるオブジェクトの再有効化

コンパイラでは、コンパイルされたがエラーのあるオブジェクトの自動的な再有効化は行われません。コンパイラはオブジェクトを再コンパイルします。オブジェクトがエラーなしで再コンパイルされると、再有効化されます。それ以外は無効のままです。

23.6.2 未許可オブジェクトの再有効化

コンパイラは、そのすべての参照オブジェクトに対するアクセス権限が未許可オブジェクトにあるかどうかを調べます。ある場合、未許可オブジェクトはコンパイラによって再コンパイルなしで再有効化されます。ない場合は、コンパイラによって対応するエラー・メッセージが発行されます。

23.6.3 無効SQLオブジェクトの再有効化

SQLコンパイラによって無効なオブジェクトが再コンパイルされます。オブジェクトがエラーなしで再コンパイルされると、再有効化されます。それ以外は無効のままです。

23.6.4 無効PL/SQLオブジェクトの再有効化

無効のPL/SQLプログラム・ユニット(プロシージャ、ファンクションまたはパッケージ)の場合、PL/SQLコンパイラが、参照オブジェクトの変更が無効オブジェクトに影響を与えるものだったかどうかを調べます。影響を与えた場合、コンパイラによって無効なオブジェクトが再コンパイルされます。オブジェクトがエラーなしで再コンパイルされると、再有効化されます。それ以外は無効のままです。影響がなかった場合、無効オブジェクトはコンパイラによって再コンパイルなしで再有効化されます。

23.7 スキーマの範囲内での名前解決

SQL文で参照されるオブジェクト名は1つ以上の部分で構成されます。各部分はピリオドで区切られます。たとえば、hr.employees.department_idは3つの部分から構成されています。

Oracle Databaseでは、次のプロシージャを使用して、オブジェクト名の解決を試行します。


注意:

プロシージャを正常に実行するには、オブジェクト名のすべての部分が現行エディションで表示されている必要があります。詳細は、24.1.1.1項「エディション・オブジェクトと非エディション・オブジェクトの名前解決」を参照してください。

  1. オブジェクト名の先頭の要素を修飾します。

    オブジェクト名に要素が1つしかない場合は、その要素が最初の要素となります。要素が2つ以上ある場合は、最も左にあるピリオドの左側の要素が先頭の要素です。たとえば、hr.employees.department_idでは、hrが先頭の要素です。

    先頭の要素を修飾する手順は次のとおりです。

    1. オブジェクト名が、SELECT文のFROM句に含まれる表名であり、2つ以上の構成要素を持つ場合は、手順dに進みます。それ以外の場合は、手順bに進みます。

    2. 現在のスキーマ内で、最初の要素と一致する名前を持つオブジェクトが検索されます。

      見つかった場合は、手順2に進みます。それ以外の場合は、手順cに進みます。

    3. 最初の要素と一致するパブリック・シノニムが検索されます。

      見つかった場合は、手順2に進みます。それ以外の場合は、手順dに進みます。

    4. 最初の要素と名前が一致するスキーマが検索されます。

      該当するスキーマが見つかった場合、オブジェクト名に後続の要素があれば、手順eに進みます。それ以外の場合は、エラーが戻され、オブジェクト名を修飾できません。

    5. 手順dで見つかったスキーマ内で、オブジェクト名の2番目の要素と一致する名前を持つ表またはSQLファンクションが検索されます。

      見つかった場合は、手順2に進みます。それ以外の場合は、エラーが戻され、オブジェクト名を修飾できません。


      注意:

      この手順で検出されたSQLファンクションは、手順dで検出されたスキーマによって再定義されています。

  2. スキーマ・オブジェクトは修飾されています。オブジェクト名の残りの要素は、このスキーマ・オブジェクトの有効な部分と一致する必要があります。

    たとえば、オブジェクト名がhr.employees.department_idである場合、hrがスキーマとして修飾されます。employeesが表として修飾されている場合、department_idはその表の列に対応する必要があります。また、employeesがパッケージとして修飾されている場合、department_idはそのパッケージのパブリック定数、変数、プロシージャまたはファンクションに対応する必要があります。

Oracle Databaseによる参照の解決では、オブジェクトは、他のオブジェクトが存在しないという事実に依存する場合があります。このような状況が発生するのは、依存オブジェクトで使用されている参照の解釈が、別のオブジェクトの存在により多義的になる場合です。


参照:

  • SQLとPL/SQLでの名前解決の違いの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。

  • 分散データベース・システムでの名前解決の詳細は、『Oracle Database管理者ガイド』を参照してください。


23.8 ローカル依存性の管理

ローカルの依存性管理は、Oracle Databaseが単一データベースのオブジェクト間の依存性を管理するときに行われます。たとえば、プロシージャ内の文が同じデータベースの表を参照することができます。

23.9 リモートの依存性管理

リモートの依存性管理は、Oracle Databaseがネットワーク上の分散環境で依存性を管理するときに行われます。たとえば、Oracle Formsトリガーは、データベースのスキーマ・オブジェクトに依存することができます。分散データベースでは、ローカル・ビューはリモート表を参照できます。

Oracle Databaseでは、分散データベースの依存性も管理されます。たとえば、Oracle Formsアプリケーションは、表を参照するトリガーを含むことがあります。データベース・システムは、そのオブジェクト間の依存性を把握する必要があります。Oracle Databaseがリモート依存性を管理する際は、関係するオブジェクトに応じて様々なメカニズムを使用します。

内容は次のとおりです。

23.9.1 ローカル・データベース・プロシージャとリモート・データベース・プロシージャの間の依存性

分散データベース・システムのストアド・プロシージャ(ファンクション、パッケージおよびトリガーを含む)間の依存性は、タイムスタンプ・チェック(23.10.1項を参照)、またはシグネチャ・チェック(23.10.2項を参照)を使用して管理されます。

動的初期化パラメータREMOTE_DEPENDENCIES_MODEによって、タイムスタンプとシグネチャのどちらでリモート依存性を管理するかが決まります。


参照:

『Oracle Database PL/SQL言語リファレンス』

23.9.2 その他のリモート・オブジェクト間の依存性

Oracle Databaseでは、ローカル・プロシージャとリモート・プロシージャ間の依存性を除き、リモート・スキーマ・オブジェクト間の依存性は管理されません。

たとえば、リモート表を参照する問合せによってローカル・ビューが作成および定義されるとします。また、ローカル・プロシージャに、同じリモート表を参照するSQL文が含まれるとします。その後、表の定義が変更されます。

したがって、表の変更後にビューとプロシージャが使用され、そのビューとプロシージャがエラーとなった場合でも、ローカル・ビューとプロシージャは無効になりません。この場合、ビューとプロシージャを、エラーが戻されないように手動で変更する必要があります。このような場合は、依存オブジェクトを不必要に再コンパイルするより、依存性を管理しないことをお薦めします。

23.9.3 アプリケーションの依存性

データベース・アプリケーションのコードは、接続先データベースのオブジェクトを参照できます。たとえば、Oracle Call Interface(OCI)およびプリコンパイラ・アプリケーションは無名PL/SQLブロックを発行できます。Oracle Formsアプリケーションのトリガーは、スキーマ・オブジェクトを参照できます。

これらのアプリケーションは、参照しているスキーマ・オブジェクトに依存しています。依存性管理の方法は開発環境によって異なります。Oracle Databaseでは、アプリケーションの依存性が自動的に追跡されることはありません。


参照:

データベース・アプリケーション内のリモート依存性管理の詳細は、アプリケーション開発ツールおよびオペレーティング・システムのマニュアルを参照してください。

23.10 リモート・プロシージャ・コール(RPC)の依存性管理

リモート・プロシージャ・コール(RPC)の依存性管理は、分散データベース・システムでローカル・ストアド・プロシージャがリモート・プロシージャをコールするときに行われます。動的初期化パラメータREMOTE_DEPENDENCIES_MODEは、依存性モードを制御します。選択肢は、タイムスタンプ依存性モード、またはRPCシグネチャ依存性モードです。

内容は次のとおりです。

23.10.1 タイムスタンプ依存性モード

プロシージャのコンパイル時に、タイムスタンプがデータ・ディクショナリに記録されます。タイムスタンプは、プロシージャが作成、変更または置換された時刻を示します。

コンパイル済のプロシージャには、このプロシージャがコールする各リモート・プロシージャの情報(リモート・プロシージャのスキーマ、パッケージ名、プロシージャ名、タイムスタンプなど)が含まれます。

タイムスタンプ依存性モードでは、ローカル・リモート・プロシージャがリモート・プロシージャをコールすると、Oracle Databaseは、リモート・プロシージャに対するローカル・プロシージャのタイムスタンプと、リモート・プロシージャの現在のタイムスタンプを比較します。2つのタイムスタンプが一致した場合、ローカル・プロシージャとリモート・プロシージャの両方が実行されます。どちらも再コンパイルされません。

2つのタイムスタンプが一致しない場合は、ローカル・プロシージャが無効になり、コール元の環境にエラーが返されます。新しいタイムスタンプのリモート・プロシージャに依存する他のすべてのローカル・プロシージャも無効になります。

タイムスタンプは、ローカル・プロシージャ本体の文によってリモート・プロシージャが実行されるときに比較されます。したがって、ローカル・プロシージャ内の無効なプロシージャ・コールよりも前にある文は、正常に実行されることがあります。無効なコールの後の分は実行されません。ローカル・プロシージャは再コンパイルが必要です。

無効なコールの前にDML文がある場合、この文と無効なコールが同じPL/SQLブロックにある場合のみ、この文がロールバックされます。たとえば、次のコードではUPDATE文がロールバックされます。

BEGIN
  UPDATE table SET ...
  invalid_proc;
  COMMIT;
END;

しかし、次のコードではUPDATE文はロールバックされません。

UPDATE table SET ...
EXECUTE invalid_proc;
COMMIT;

タイムスタンプ依存性モードには次のデメリットがあります。

  • ネットワーク上での依存オブジェクトに対して、パフォーマンスに関係なく、不要な再コンパイルが行われることがよくあります。

  • クライアント側アプリケーションでPL/SQLが使用されていると、このモードでは、クライアント側でアプリケーションの実行が妨げられる状況になる場合があります。

    このようなアプリケーションの例はOracle Formsです。インストール中、クライアント・サイトでOracle Formsが使用するクライアント側PL/SQLプロシージャを再コンパイルする必要があります。また、クライアント側プロシージャがサーバー・プロシージャに依存しているときに、サーバー・プロシージャが変更または自動再コンパイルされた場合は、クライアント側PL/SQLプロシージャを再コンパイルする必要があります。ただし、クライアントではPL/SQLコンパイラは使用できません。したがって、クライアント・アプリケーション開発者は、新しいバージョンのアプリケーションをすべての顧客に再配布する必要があります。

23.10.2 RPCシグネチャ依存性モード

Oracle Databaseは、リモート依存性を処理するために、RPCシグネチャを提供します。ローカル環境では常に再コンパイルが可能であるため、RPCシグネチャはローカル依存性に影響を与えません。

RPCシグネチャは、各コンパイル済ストアド・プログラム・ユニットと関連付けられています。これは、次の特性を基準にユニットを識別しています。

  • 名前

  • パラメータ数

  • 各パラメータのデータ型クラス

  • 各パラメータのモード

  • ファンクションの戻り値のデータ型クラス

RPCシグネチャは、先行する特性の少なくとも1つが変更された場合のみ変更されます。


注意:

RPCシグネチャには、DETERMINISTICPARALLEL_ENABLE、または純粋度の情報は含まれません。リモート・システムのあるファンクションについてこれらの設定が変更された場合、これらに基づく最適化は自動的に再検討されません。したがって、SQL文でリモート・ファンクションをコールしたり、ファンクションに基づいたインデックスで使用したりすると、問合せの結果が正しくならないことがあります。

コンパイル済のプログラム・ユニットには、このプログラムがコールする各リモート・プロシージャのRPCシグネチャ(および、リモート・プロシージャのスキーマ、パッケージ名、プロシージャ名、タイムスタンプ)が含まれます。

RPCシグネチャ依存性モードでは、ローカル・プログラム・ユニットがリモート・プログラム・ユニットでサブプログラムをコールすると、データベースはタイムスタンプの不一致を無視し、リモート・サブプログラムに対するローカル・ユニットのRPCシグネチャと、リモート・サブプログラムの現在のRPCシグネチャを比較します。RPCシグネチャが一致する場合、コールは正常に行われます。一致しない場合、データベースからローカル・ユニットにエラーが返され、このユニットが無効化されます。

たとえば、プロシージャget_emp_nameが、Bostonにあるサーバー(BOSTON_SERVER)に格納されているとします。

CREATE OR REPLACE PROCEDURE get_emp_name (
  emp_number  IN  NUMBER,
  hiredate    OUT VARCHAR2,
  emp_name    OUT VARCHAR2) AUTHID DEFINER AS
BEGIN
  SELECT last_name, TO_CHAR(hire_date, 'DD-MON-YY')
  INTO emp_name, hiredate
  FROM employees
  WHERE employee_id = emp_number;
END;
/

get_emp_nameBOSTON_SERVERでコンパイルされたときに、Oracle Databaseにより、RPCシグネチャとタイムスタンプの両方が記録されます。

たとえば、print_nameをコールするPL/SQLプロシージャget_emp_nameがCaliforniaにあるサーバーにあるとしましょう。

CREATE OR REPLACE PROCEDURE print_ename (emp_number IN NUMBER) AUTHID DEFINER AS
  hiredate  VARCHAR2(12);
  ename     VARCHAR2(10);
BEGIN
  get_emp_name@BOSTON_SERVER(emp_number, hiredate, ename);
  dbms_output.put_line(ename);
  dbms_output.put_line(hiredate);
END;
/

print_nameがCaliforniaサーバーでコンパイルされると、このデータベースはBostonサーバーに接続し、get_emp_nameのRPCシグネチャをCaliforniaサーバーに送信してから、get_emp_nameのRPCシグネチャをコンパイル済のprint_enameに記録します。

実行時、print_nameget_emp_nameをコールすると、データベースは、コンパイル済のprint_enameに記録されたget_emp_nameのRPCシグネチャをBostonサーバーに送信します。記録されたRPCシグネチャが、Bostonサーバーのget_emp_nameの現在のRPCシグネチャと一致した場合、コールは正常に行われます。それ以外の場合、データベースはprint_nameにエラーを返し、その後、これが無効化されます。

内容は次のとおりです。

23.10.2.1 パラメータの名前とデフォルト値の変更

サブプログラム・パラメータの名前またはデフォルト値を変更しても、サブプログラムのRPCシグネチャは変更されません。たとえば、次の2つの例でプロシージャP1のRPCシグネチャは同じです。

PROCEDURE P1 (Param1 IN NUMBER := 100);
PROCEDURE P1 (Param2 IN NUMBER := 200);

ただし、コール側で新しいデフォルト値を取得できるようにする必要があるアプリケーションの場合、コールされたプロシージャを再コンパイルする必要があります。

23.10.2.2 パラメータ・モードINの指定の変更

サブプログラム・パラメータ・モードINはデフォルトなので、暗黙的または明示的に指定できます。指定を暗黙的から明示的、または明示的から暗黙的に変更しても、サブプログラムのRPCシグネチャは変更されません。たとえば、次の2つの例でプロシージャP1のRPCシグネチャは同じです。

PROCEDURE P1 (Param1 NUMBER);    -- implicit specification
PROCEDURE P1 (Param1 IN NUMBER);  -- explicit specification

23.10.2.3 サブプログラム本体の変更

サブプログラムの本体を変更しても、サブプログラムのRPCシグネチャは変更されません。

例23-4では、プロシージャget_hire_dateの本体のみ変更されます。したがって、get_hire_dateのRPCシグネチャは変更されません。

例23-4 プロシージャget_hire_dateの本体の変更

CREATE OR REPLACE PROCEDURE get_hire_date (
  emp_number  IN  NUMBER,
  hiredate    OUT VARCHAR2,
  emp_name    OUT VARCHAR2) AUTHID DEFINER AS
BEGIN
  SELECT last_name, TO_CHAR(hire_date, 'DD-MON-YY')
  INTO emp_name, hiredate
  FROM employees
  WHERE employee_id = emp_number;
END;
/

CREATE OR REPLACE PROCEDURE get_hire_date (
  emp_number  IN  NUMBER,
  hiredate    OUT VARCHAR2,
  emp_name    OUT VARCHAR2) AUTHID DEFINER AS
BEGIN
  -- Change date format model
  SELECT last_name, TO_CHAR(hire_date, 'DD/MON/YYYY')
  INTO emp_name, hiredate
  FROM employees
  WHERE employee_id = emp_number;
END;
/

23.10.2.4 パラメータのデータ型クラスの変更

パラメータのデータ型を同じクラスの別のデータ型に変更しても、RPCシグネチャは変更されませんが、別のクラスのデータ型に変更すると、シグネチャも変更されます。

表23-3に、データ型クラスと、クラスを構成するデータ型を示します。NCHARなど、表23-3に含まれないデータ型はデータ型クラスには属していません。これらの型を変更すると、必ずRPCシグネチャも変更されます。

表23-3 データ型クラス

データ型クラス クラスのデータ型

Character

CHAR
CHARACTER

VARCHAR

VARCHAR
VARCHAR2
STRING
LONG
ROWID

Raw

RAW
LONG RAW

Integer

BINARY_INTEGER
PLS_INTEGER
SIMPLE_INTEGER
BOOLEAN
NATURAL
NATURALN
POSITIVE
POSITIVEN

Number

NUMBER
INT
INTEGER
SMALLINT
DEC
DECIMAL
REAL
FLOAT
NUMERIC
DOUBLE PRECISION

Datetime

DATE
TIMESTAMP
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH LOCAL TIME ZONE
INTERVAL YEAR TO MONTH
INTERVAL DAY TO SECOND

例23-5はパラメータhiredateのデータ型をVARCHAR2からDATEに変更します。VARCHAR2DATEは同じデータ型クラスではないので、プロシージャget_hire_dateのRPCシグネチャが変更されます。

例23-5 get_hire_dateパラメータのデータ型クラスの変更

CREATE OR REPLACE PROCEDURE get_hire_date (
  emp_number  IN  NUMBER,
  hiredate    OUT DATE,
  emp_name    OUT VARCHAR2) AS
BEGIN
  SELECT last_name, TO_CHAR(hire_date, 'DD/MON/YYYY')
  INTO emp_name, hiredate
  FROM employees
  WHERE employee_id = emp_number;
END;
/

23.10.2.5 パッケージ・タイプの変更

パッケージ・タイプの名前、または内部コンポーネントの名前を変更しても、パッケージのRPCシグネチャは変更されません。

例23-6では、パッケージemp_packageの内部にレコード型emp_data_typeが定義されます。次に、レコード・フィールドの名前が変更されます。レコード型は変更されません。最後に、レコード型の名前が変更されます。特性は変更されません。パッケージのRPCシグネチャは変更されません。

例23-6 パッケージ・レコード型のフィールド名の変更

CREATE OR REPLACE PACKAGE emp_package AUTHID DEFINER AS
  TYPE emp_data_type IS RECORD (
    emp_number  NUMBER,
    hiredate    VARCHAR2(12),
    emp_name    VARCHAR2(10)
  );
  PROCEDURE get_emp_data (
    emp_data  IN OUT emp_data_type
  );
END;
/

CREATE OR REPLACE PACKAGE emp_package AUTHID DEFINER AS
  TYPE emp_data_type IS RECORD (
    emp_num   NUMBER,
    hire_dat  VARCHAR2(12),
    empname   VARCHAR2(10)
  );
  PROCEDURE get_emp_data (
    emp_data  IN OUT emp_data_type
  );
END;
/

CREATE OR REPLACE PACKAGE emp_package AUTHID DEFINER AS
  TYPE emp_data_record_type IS RECORD (
    emp_num   NUMBER,
    hire_dat  VARCHAR2(12),
    empname   VARCHAR2(10)
  );
  PROCEDURE get_emp_data (
    emp_data  IN OUT emp_data_record_type
  );
END;
/

23.10.3 依存性モードの制御

動的初期化パラメータREMOTE_DEPENDENCIES_MODEは、依存性モードを制御します。初期化パラメータ・ファイルに次のように指定されているとします。この場合は、依存性を解決するためにタイムスタンプのみが使用されます(明示的かつ動的にオーバーライドされない場合)。

REMOTE_DEPENDENCIES_MODE = TIMESTAMP

初期化パラメータ・ファイルでパラメータが次のように指定されている場合は、依存性を解決するためにRPCシグネチャのみが使用されます(明示的かつ動的にオーバーライドされない場合)。

REMOTE_DEPENDENCIES_MODE = SIGNATURE

DDL文を使用して動的にモードを変更することができます。たとえば、次の例では現行セッションの依存性モードが変更されます。

ALTER SESSION SET REMOTE_DEPENDENCIES_MODE = {SIGNATURE | TIMESTAMP}

次の例は、起動後にシステム全体の依存性モードを変更します。

ALTER SYSTEM SET REMOTE_DEPENDENCIES_MODE = {SIGNATURE | TIMESTAMP}

init.oraパラメータ・ファイルに、あるいはALTER SESSIONまたはALTER SYSTEM文を使用して、REMOTE_DEPENDENCIES_MODEパラメータが指定されない場合、TIMESTAMPがデフォルト値になります。したがって、REMOTE_DEPENDENCIES_MODEパラメータを明示的に使用するか適切なDDL文を使用しないかぎり、サーバーはタイムスタンプ依存性モードを使用して実行します。

REMOTE_DEPENDENCIES_MODE=SIGNATUREを使用すると、次のようになります。

  • リモート・プロシージャのパラメータの初期値を変更しても、そのリモート・プロシージャをコールするローカル・プロシージャは無効になりません。リモート・プロシージャへのコールでパラメータが指定されない場合は、初期値が使用されます。この場合、無効化と再コンパイルが自動的には行われないため、古い初期値が使用されます。新しい初期値を確認するには、手動でコール側プロシージャを再コンパイルします。

  • オーバーロードされたプロシージャ(既存プロシージャと同名のプロシージャ)をパッケージへ追加しても、リモート・プロシージャをコールするローカル・プロシージャは無効にされません。このオーバーロードの結果として、ローカル・プロシージャからの既存のコールがタイムスタンプ・モードで再バインドされた場合、ローカル・プロシージャは無効にされないため、RPCシグネチャ・モードでは、この再バインドは行われません。再バインドを成功させるには、ローカル・プロシージャを手動で再コンパイルする必要があります。

  • 新しい型と以前の型が同じになるように既存のパッケージ・プロシージャのパラメータの型が変更された場合でも、ローカルのコール側プロシージャは自動的に無効化または再コンパイルされません。新しい型のセマンティクスを取得するには、コール側プロシージャを手動で再コンパイルする必要があります。

内容は次のとおりです。

23.10.3.1 依存性の解決

REMOTE_DEPENDENCIES_MODE = TIMESTAMP (デフォルト値)のとき、プログラム・ユニット間の依存性は、実行時にタイムスタンプを比較することで処理されます。コールされたリモート・プロシージャのタイムスタンプが、コールしたプロシージャのタイムスタンプと一致しない場合、コール側の(依存)ユニットは無効になり、再コンパイルする必要が生じます。この場合、ローカルPL/SQLコンパイラがない場合は、コール側のアプリケーションを処理できません。

タイムスタンプ依存性モードでは、RPCシグネチャは比較されません。ローカルPL/SQLコンパイラがある場合は、コール側プロシージャが実行されると自動的に再コンパイルされます。

REMOTE_DEPENDENCIES_MODE = SIGNATUREの場合、コール側のユニットの記録済タイムスタンプは、まず最初にコールされたリモート・ユニット内の現在のタイムスタンプと比較されます。タイムスタンプが一致すると、コールが処理されます。タイムスタンプが一致しない場合は、コールされたリモート・サブプログラムのRPCシグネチャは、コール側サブプログラムに記録されたままの状態で、コールされたサブプログラムの現在のRPCシグネチャと比較されます。(23.10.2.4項で説明する基準を使用して)シグネチャが一致しない場合、エラーがコール元セッションに返されます。

23.10.3.2 依存性管理の提案

REMOTE_DEPENDENCIES_MODEパラメータを設定する際には、次のガイドラインに従います。

  • サーバー側PL/SQLユーザーは、パラメータをTIMESTAMPに設定して(つまりデフォルトのままにして)タイムスタンプ依存性モードを使用できます。

  • サーバー側PL/SQLユーザーが、分散システムを使用しており、不要な再コンパイルを回避する場合には、RPCシグネチャ依存性モードを使用できます。

  • クライアント側PL/SQLユーザーは、パラメータをSIGNATUREに設定する必要があります。こうすると、次のようになります。

    • クライアント・サイトにアプリケーションをインストールするときに、プロシージャを再コンパイルする必要がありません。

    • サーバーをアップグレードしてもタイムスタンプの不一致が発生しません。

  • サーバー側でRPCシグネチャ・モードを使用するときは、プロシージャをパッケージ仕様部のプロシージャ(またはファンクション)宣言の最後に追加します。宣言リストの中間にプロシージャを追加すると、依存プロシージャの不必要な無効化と再コンパイルを引き起こすことがあります。

23.11 共有SQLの依存性管理

スキーマ・オブジェクト相互間の依存性管理に加えて、Oracle Databaseでは共有プール内の各共有SQL領域の依存性も管理します。表またはビュー、シノニム、順序を生成、変更または削除したり、プロシージャまたはパッケージ仕様部を再コンパイルすると、それらに依存する共有SQL領域もすべて無効になります。共有SQL領域が無効になった後で、その領域に対応するカーソルを実行すると、Oracle DatabaseによってSQL文が再解析されて、共有SQL領域が再生成されます。