| Oracle Database 概要 10gリリース2(10.2) B19215-02 |
|
ビューやプロシージャなどのオブジェクトの定義では、他のオブジェクト(表など)が参照されます。したがって、定義するオブジェクトは、その定義で参照する他のオブジェクトに依存しています。この章では、スキーマ・オブジェクトの相互間の依存性と、Oracleがそのような依存性を自動的に追跡し管理する方法について説明します。
この章の内容は、次のとおりです。
スキーマ・オブジェクトのタイプによっては、定義の一部として他のオブジェクトを参照できるものがあります。たとえば、ビューは表や他のビューを参照する問合せによって定義されます。また、プロシージャ本体には、データベースの他のオブジェクトを参照するSQL文を組み込めます。定義の一部として他のオブジェクトを参照するオブジェクトを依存オブジェクトと呼び、参照されるオブジェクトを参照オブジェクトと呼びます。図6-1に、各種の依存オブジェクトと参照オブジェクトを示します。
参照オブジェクトの定義を変更した場合、その変更の内容によって、依存オブジェクトがエラーなしで機能し続ける場合と、そうでない場合があります。たとえば、表を削除した場合、その表に基づくビューは使用できなくなります。
Oracleではオブジェクト間の依存性が自動的に記録されるため、データベース管理者とユーザーは依存性管理の複雑な作業から解放されます。たとえば、複数のストアド・プロシージャが依存している表を変更すると、依存プロシージャは、次に参照された(再度実行またはコンパイルされた)時点で自動的に再コンパイルされます。
スキーマ・オブジェクト間の依存性を管理するために、データベース内のすべてのスキーマ・オブジェクトはステータスを持ちます。
無効になる可能性があるのは、依存しているオブジェクトのみです。表、順序およびシノニムは、常に有効です。
ビュー、プロシージャ、ファンクションまたはパッケージが無効である場合、Oracleがそのオブジェクトをコンパイルしようとしても、そのオブジェクトに関連したエラーが発生します。たとえば、ビューのコンパイル時に、実表の1つが存在しなかったり、実表の正当な権限がなかったりする場合があります。パッケージのコンパイル時には、PL/SQLまたはSQLの構文エラーが発生したり、参照されているオブジェクトについての適切な権限が存在しない場合があります。このような問題があるスキーマ・オブジェクトは無効のままです。
Oracleはデータベースの変更を自動的に追跡し、関係するオブジェクトのステータスをデータ・ディクショナリに記録します。
ステータスの記録は再帰的な処理です。参照オブジェクトの状態が変更されると、直接的に依存するオブジェクトのステータスが変更されるだけでなく、間接的に依存するオブジェクトのステータスも変更されます。
たとえば、ビューを直接参照するストアド・プロシージャを考えます。ストアド・プロシージャは、このビューの実表を間接的に参照します。このため、実表を変更するとビューは無効になり、さらにストアド・プロシージャも無効になります。図6-2に、間接的な依存性を示します。
スキーマ・オブジェクトがSQL文によって直接的に、または依存オブジェクトの参照を介して間接的に参照されるときに、OracleはSQL文に明示的に指定されているオブジェクトと参照オブジェクトのステータスを、必要に応じてチェックします。Oracleの処理は、SQL文で直接および間接的に参照されるオブジェクトのステータスに応じて異なります。
次の条件が満たされている場合は、ビューまたはPL/SQLプログラム・ユニットをコンパイルして、その状態を有効にすることができます。
INSERT権限が必要です。
ビューは、そのビューの定義問合せで参照されている実表またはビューに依存しています。たとえば、SELECT * FROM tableのように、ビューの定義問合せで参照される列が明示的に定義されていなければ、定義問合せはデータ・ディクショナリへの格納時に展開され、参照先の実表内の現行の列がすべて含まれるようになります。
ビューの実表またはビューを変更、改名または削除すると、そのビューは無効になりますが、その定義は無効なビューを参照する権限、シノニム、他のオブジェクトおよび他のビューとともに、データ・ディクショナリ内に残ります。
無効なビューを使用すると、そのビューは動的に再コンパイルされます。再コンパイルされたビューは、次に示す条件に応じて有効または無効になります。
SELECT * FROM tableの問合せで定義されたビューに特に当てはまります。このような定義問合せはビューの作成時にデータ・ディクショナリ内で展開され、そのまま永続的に格納されるためです。
参照オブジェクトの定義を変更すると、プログラム・ユニットは自動的に無効になります。たとえば、スタンドアロン・プロシージャに表、ビュー、別のスタンドアロン・プロシージャおよびパブリック・パッケージ・プロシージャを参照する複数の文が含まれているとします。このような場合は、次のような条件が成立します。
一部のデータ・ウェアハウスでは、ロード時間を速めるために夜間に索引を削除します。ただし、索引が削除された表に依存するすべてのビューは無効になります。このことは、その後実行されるパッケージがこれら削除されたビューを参照すると、そのパッケージが無効になることを意味します。
表、索引およびビューを作成した後に索引を削除すると、その表に依存するビュー、パッケージ、パッケージ本体、ファンクションおよびプロシージャなどのオブジェクトはすべて無効になることに注意してください。このことにより、更新可能な結合ビューが保護されます。
ビューを再び有効にするには、次の文を使用します。
SELECT * FROM vtest;
または
ALTER VIEW vtest compile;
パッケージ構成を参照するセッションごとに、各パッケージの独自のインスタンスが存在します。このインスタンスには、パブリック変数とプライベート変数、カーソルおよび定数の永続的な状態が含まれます。その後、セッションのインスタンス化されたパッケージのいずれかが無効にされて再コンパイルされると、セッションのパッケージのすべてのインスタンス化が、状態も含めて失われる可能性があります。
ユーザーやPUBLICに対してDMLオブジェクト権限やシステム権限の付与または取消しが実行された場合、Oracleはその所有者のすべての依存オブジェクトを自動的に無効にします。Oracleは依存オブジェクトを無効にして、その依存オブジェクトの所有者が参照オブジェクトに対する必要な権限を引き続き持っていることを検証します。Oracleは内部的に、そのようなオブジェクトを再コンパイルする必要はないことを確認します。つまり、オブジェクト構造を検証するのではなく、セキュリティ認可のみを検証します。このように最適化すると、不要な再コンパイルが省略され、依存オブジェクトのタイム・スタンプを変更する必要もありません。
SQL文で参照するオブジェクト名は、複数の要素をピリオドで区切って指定できます。Oracleでは、次の方法でオブジェクト名が解決されます。
hr.employeesでは、hrが最初の要素です。要素が1つしかない場合は、その要素が最初の要素とみなされます。
手順cでスキーマが見つからない場合、オブジェクトは修飾できず、エラーが戻されます。
hr.employees.department_idが名前の場合、hrはスキーマ、employeesは表としてそれぞれ修飾され、department_idは1列に対応する必要があります(employeesが表であるため)。employeesがパッケージとして修飾されている場合、department_idはそのパッケージのパブリック定数、変数、プロシージャまたはファンクションに対応する必要があります。
Oracleによる参照の解決では、オブジェクトは、他のオブジェクトが存在しないという事実に依存する場合があります。このような状況は、依存オブジェクトが使用している参照が、別のオブジェクトが存在する場合に異なって解釈される可能性がある場合に発生します。
スキーマ・オブジェクト相互間の依存性管理に加えて、Oracleは共有プール内の各共有SQL領域の依存性も管理します。表またはビュー、シノニム、順序を生成、変更または削除したり、プロシージャまたはパッケージ仕様部を再コンパイルすると、それらに依存する共有SQL領域もすべて無効になります。共有SQL領域が無効になった後で、その領域に対応するカーソルを実行すると、OracleによってSQL文が再解析され、共有SQL領域が再生成されます。
依存性の追跡や必要な再コンパイルは、Oracleによって自動的に実行されます。ローカル依存性の管理が発生するのは、Oracleが単一データベース内のオブジェクト間の依存性を管理する場合です。たとえば、プロシージャ内の文が、同じデータベース内の表を参照する場合があります。
リモート依存性の管理が発生するのは、Oracleがネットワークを介した分散環境で依存性を管理する場合です。たとえば、Oracle Formsトリガーは、データベース内のスキーマ・オブジェクトに依存する場合があります。また、分散データベースにおいて、ローカル・ビューの定義問合せがリモート表を参照する場合があります。
Oracleは、データベース内部の依存性表を使用してローカル依存性を管理します。この表は、スキーマ・オブジェクトごとに依存オブジェクトを追跡し、記録するものです。参照オブジェクトが修正されると、この依存性表を使用して依存オブジェクトが識別され、それらの依存オブジェクトが無効にされます。
たとえば、ストアド・プロシージャUPDATE_SALが表JWARD.employeesを参照している場合を考えます。この表の定義になんらかの変更があると、ストアド・プロシージャUPDATE_SALを含めて、JWARD.employeesを参照するすべてのオブジェクトのステータスがINVALIDに変更されます。そのため、このプロシージャは、再コンパイルされて有効にされるまで実行できません。同様に、ユーザーのDML権限を取り消すと、そのユーザーのスキーマ内の依存オブジェクトはすべて無効になります。ただし、認可が取り消されたために無効になったオブジェクトは、再認可によって有効にできます。その場合は、完全に再コンパイルする必要はありません。
Oracleは、アプリケーションからデータベースへの依存性と分散データベースの依存性も管理します。たとえば、Oracle Formsアプリケーションには表を参照するトリガーが含まれていたり、ローカルなストアド・プロシージャから分散データベース・システム内のリモート・プロシージャがコールされることがあります。データベース・システムでは、このようなオブジェクト間の依存性を管理する必要があります。関係するオブジェクトの種類によっては、リモート依存性を管理するために別のメカニズムが使用されます。
ファンクション、パッケージおよびトリガーなど、ストアド・プロシージャの相互間の依存性は、分散データベース・システムにおいてはタイム・スタンプのチェックまたはシグネチャのチェックを使用して管理されます。
動的初期化パラメータREMOTE_DEPENDENCIES_MODEは、タイム・スタンプとシグネチャのどちらでリモート依存性を管理するかを決定します。
タイム・スタンプのチェックの依存性モデルでは、プロシージャがコンパイルまたは再コンパイルされるたびに、そのタイム・スタンプ(作成、変更または置換された時刻)がデータ・ディクショナリに記録されます。タイム・スタンプは、プロシージャが作成、変更または置換された時刻の記録です。さらに、コンパイル済プロシージャには、それが参照するリモート・プロシージャごとに、スキーマ、パッケージ名、プロシージャ名、タイム・スタンプなどの情報も含まれています。
依存プロシージャが使用されると、Oracleは、コンパイル時に記録されたリモート・タイム・スタンプと、リモートで参照されたプロシージャのカレント・タイム・スタンプを比較します。比較結果に応じて、次の2つの処理が発生します。
ローカル・プロシージャ本体の文によりリモート・プロシージャが実行されると、実際のタイム・スタンプが比較されます。分散データベースの通信リンクを使用してタイム・スタンプが比較されるのは、このときのみです。したがって、ローカル・プロシージャの文のうち無効なプロシージャ・コールより前にあるすべての文は、正常に実行される可能性があります。無効なプロシージャ・コールより後の文はまったく実行されません。コンパイルが必要です。
無効なプロシージャ・コールの実行方法によっては、その前に実行されたDML文がロールバックされます。たとえば、次の例では、PL/SQLブロックの変更全体がロールバックされるため、UPDATEの結果はロールバックされます。
BEGIN UPDATE table set ... invalid_proc; COMMIT; END;
ただし、次の例では、UPDATEの結果は確定されます。この場合、ロールバックされるのはPROCコールのみです。
UPDATE table set ... EXECUTE invalid_proc; COMMIT;
Oracleには、シグネチャを使用するリモート依存性の機能もあります。このシグネチャ機能の影響を受けるのは、リモート依存性のみです。ローカル依存性は、その環境でいつでも再コンパイルできるため影響を受けません。
プロシージャのシグネチャには、次の項目に関する情報が含まれます。
シグネチャ依存性モデルが有効である場合に、依存単位に親単位のプロシージャへのコールが含まれており、かつ、そのプロシージャのシグネチャが互換性のない方法で変更されていると、リモート・プログラム・ユニットへの依存性により、その依存単位が無効になります。プログラム・ユニットは、パッケージ、ストアド・プロシージャ、ストアド・ファンクションまたはトリガーのいずれかです。
Oracleでは、ローカル・プロシージャとリモート・プロシージャの間の依存性を除いては、リモート・スキーマ・オブジェクト間の依存性は管理されません。
たとえば、リモート表を参照する問合せによって、ローカル・ビューを作成して定義するとします。また、ローカル・プロシージャに、同じリモート表を参照するSQL文が含まれているとします。その後、表の定義が変更されたとします。
表の変更後にビューとプロシージャが使用され、そのビューとプロシージャがエラーとなった場合でも、ローカル・ビューとプロシージャは無効になりません。この場合、ビューとプロシージャを、エラーが戻されないように手動で変更する必要があります。このような場合は、依存オブジェクトを不必要に再コンパイルするより、依存性を管理しないことをお薦めします。
データベース・アプリケーションのコードでは、接続されているデータベース内のオブジェクトを参照できます。たとえば、OCIおよびプリコンパイラ・アプリケーションは、無名PL/SQLブロックを発行できます。Oracle Formsアプリケーション内のトリガーは、スキーマ・オブジェクトを参照できます。
このようなアプリケーションは、参照するスキーマ・オブジェクトに依存しています。依存性管理の方法は、開発環境によって異なります。
|
![]() Copyright © 2006 Oracle Corporation. All Rights Reserved. |
|