e-learning、オラクル研修、LMS(学習管理システム)のiStudy

e-learning、オラクル研修、LMS(学習管理システム)のiStudy

第83回 「オブジェクトの依存性」

2014.01.22

こんにちは。インストラクターの蓑島です。

年が明けて最初の回です。
本年もエンジニアの皆様に役立つ情報をお届けできるようにします。

さて今回は、プログラミングの話ではないのですが、依存性というものについて簡単に説明します。そして次回、その依存性を表示する方法について説明します。
それにより、例えばプログラムを修正するときの他のオブジェクトに対する影響範囲を事前に把握することができます。

まず、依存性とはあるものの存在なしにその定義は成り立たないという関係です。

例えば、EMP表をもとにビューV_EMPを作成します。

1
2
3
CREATE VIEW V_EMP AS SELECT * FROM EMP;
 
ビューが作成されました。

このとき、V_EMPビューはEMP表があってこそ正しく存在できます。もしここで、EMP表を削除するとV_EMPビューは使用不可能(INVALID)になります。このような関係を、V_EMPビューはEMP表に依存しているといいます。

では次にこのV_EMPビューに依存するファンクションFUNC1を作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**********************************************/
-- V_EMPビューに依存するファンクションFUNC1
/**********************************************/
CREATE OR REPLACE FUNCTION  FUNC1 RETURN NUMBER
IS
     NUM  NUMBER;
BEGIN
     SELECT SUM (SAL) INTO NUM FROM V_EMP;
     RETURN NUM;
END ;
/
 
ファンクションが作成されました。

ここで、この8行目でV_EMPビューの記述があるので、FUNC1ファンクションはV_EMPビューに依存します。
すなわちFUNC1ファンクションは、V_EMPビューが削除されたり、あるいは使用不可状態(INVALID)であれば、FUNC1ファンクションも使用不可(INVALID)となります。
ちなみにこのファンクションはV_EMPビューのSAL列の合計をリターンするものですね。

では、最後にこのFUNC1ファンクションをコールするプロシージャPROC1を作成します。

1
2
3
4
5
6
7
8
9
10
11
/***************************************************/
-- ファンクションFUNC1に依存するプロシージャPROC1
/***************************************************/
CREATE OR REPLACE PROCEDURE PROC1
IS
BEGIN
    DBMS_OUTPUT.PUT_LINE(FUNC1);
END ;
/
 
プロシージャが作成されました。

ここで、7行目でFUNC1ファンクションをコールしているので、PROC1プロシージャは、FUNC1ファンクションに依存しています。
すなわち、FUNC1ファンクションが削除されたり、あるいは使用不可(INVALID)であれば、PROC1プロシージャも使用不可(INVALID)となります。
ちなみにこのプロシージャは、FUNC1ファンクションの戻り値を画面表示するものです。

以上のソースコードの記述から依存性は以下のように連鎖しています。

PROC1プロシージャ ⇒ FUNC1プロシージャ ⇒ V_EMPビュー ⇒ EMP表

左端のPROC1プロシージャのソースコードには右端のEMP表の記述はありませんが、しかし依存性の連鎖によりPROC1プロシージャは間接的にEMP表に依存するわけです。これを間接依存といいます。依存性には直接依存、間接依存があるわけです。

ではここで、EMP表、V_EMPビュー、FUNC1プロシージャ、PROC1プロシージャのステータスを確認します。

1
2
3
4
5
6
7
8
9
10
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM USER_OBJECTS
WHERE  OBJECT_NAME IN ( 'EMP' , 'V_EMP' , 'FUNC1' , 'PROC1' )
/
 
OBJECT_NAM OBJECT_TYPE         STATUS
---------- ------------------- -------
EMP        TABLE               VALID
V_EMP      VIEW                VALID
FUNC1      FUNCTION            VALID
PROC1      PROCEDURE           VALID

ご覧のように4つのオブジェクトとも、ステータスはVALID(有効)なので、オブジェクトは使用可能状態ですね。

ではここで、EMP表の名前を変更するとどうなるでしょうか?例えば、EMP表の名前をEMP2表に変更してみます。

1
2
3
RENAME EMP TO EMP2;
 
表名が変更されました。

V_EMPビューのソースコードはあくまでもEMPという名前のオブジェクトを参照しているので、V_EMPビューは使用不可(INVALID)です。そうすると、V_EMPビューに依存するFUNC1ファンクションも使用不可(INVALID)となり、その結果FUNC1ファンクションに依存するPROC1プロシージャも使用不可(INVALID)となります。
このように連鎖的に依存するオブジェクトはINVALIDとなります。

実際にステータスを確認してみましょう。

1
2
3
4
5
6
7
8
9
10
   SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM USER_OBJECTS
   2* WHERE  OBJECT_NAME IN ( 'EMP2' , 'V_EMP' , 'FUNC1' , 'PROC1' )
SQL> /
 
OBJECT_NAM OBJECT_TYPE         STATUS
---------- ------------------- -------
EMP2       TABLE               VALID
V_EMP      VIEW                INVALID
FUNC1      FUNCTION            INVALID
PROC1      PROCEDURE           INVALID

確かに、V_EMPビュー、FUNC1ファンクション、PROC1プロシージャなど依存するがINVALIDになっていますね。
このような状態で、PROC1プロシージャをコールすると当然、エラーとなります。

1
2
3
4
5
6
7
EXEC PROC1
 
行1でエラーが発生しました。:
ORA-06550: 行1、列7:
PLS-00905: オブジェクト 'SCOTT.PROC1' が無効です。
ORA-06550: 行1、列7:
PL/SQL: Statement ignored

では、EMP2表をもとの名前であるEMPに戻します。

1
2
3
SQL> RENAME EMP2 TO EMP;
 
表名が変更されました。

ではこれで先ほど連鎖的にINVALIDとなったオブジェクトのステータスはもとのVALIDに戻ったでしょうか?確認してみましょう。

1
2
3
4
5
6
7
8
9
10
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM USER_OBJECTS
WHERE  OBJECT_NAME IN ( 'EMP' , 'V_EMP' , 'FUNC1' , 'PROC1' )
/
 
OBJECT_NAM OBJECT_TYPE         STATUS
---------- ------------------- -------
EMP        TABLE               VALID
V_EMP      VIEW                INVALID
FUNC1      FUNCTION            INVALID
PROC1      PROCEDURE           INVALID

そうすると意外に思われたかもしれませんが、オブジェクトのステータスはまだINVALIDのままです。
このようにオブジェクトの名前や定義をもとの状態にしても、それだけでは依存するオブジェクトのステータスは変わりません。再コンパイルが必要です。

では再コンパイルをするまで、PROC1プロシージャは実行できないのかというと、そうではありません。INVALID状態のプログラムを実行すると自動的に再コンパイルが行われるからです。その場合、依存性の川上の方から順番に再コンパイルされます。すなわち、まずV_EMPビューが再コンパイルされてVALIDになる。次に、FUNC1ファンクションが再コンパイルされてVALIDになる。そしてPROC1プロシージャが再コンパイルされてVALIDになり実行されるわけです。

実際にやってみましょう。まず、PROC1プロシージャを実行してみます。

1
2
3
4
5
SET SERVEROUTPUT ON    --画面出力を可能にして
EXEC PROC1             -- PROC1プロシージャをコール
29025                  -- FUNC1ファンクションの結果を画面出力
 
PL/SQLプロシージャが正常に完了しました。

ご覧のように、PROC1プロシージャは実行できましたね。再コンパイルが成功したのです。

ではオブジェクトのステータスも確認してみます。

1
2
3
4
5
6
7
8
9
10
SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM USER_OBJECTS
WHERE  OBJECT_NAME IN ( 'EMP' , 'V_EMP' , 'FUNC1' , 'PROC1' )
/
 
OBJECT_NAM OBJECT_TYPE         STATUS
---------- ------------------- -------
EMP        TABLE               VALID
V_EMP      VIEW                VALID
FUNC1      FUNCTION            VALID
PROC1      PROCEDURE           VALID

依存するオブジェクトのステータスがすべてVALIDになっていますね。実行時にINVALIDのオブジェクトが川上から順番に再コンパイルされてスタータスがVALIDになったわけです。

このようにオブジェクトの名前を変えたり、あるいは影響を及ぼすような定義変更を行った場合はそのオブジェクトに依存するオブジェクトのステータスはINVALIDになります。そうするとそのオブジェクトに依存するオブジェクト、さらにそれに依存するオブジェクトが連鎖的にINVALIDになっていきます。

しかし、INVALIDのオブジェクトは実行するときに、依存性の川上のほうから順番に再コンパイルするので、そのコンパイルが成功すればステータスはVALID(有効)となり実行できるわけです。
もし再コンパイルが失敗するようであれば再コンパイルが成功するように、ビューやPL/SQLプログラムのソースコードを修正する必要があるわけです。

では今回はここまでにします。
オブジェクトの定義を変更するとそれに影響されて依存するオブジェクトのステータスが連鎖的にINVALIDになる様子が確認できたと思います。

次回は、あるオブジェクトに依存するオブジェクトはどのオブジェクトなのかをソースコードを追跡しなくても簡単に特定できる機能がありますので、それをご紹介したいと思います。
それによりプログラムを変更したときに影響を受ける他のプログラムを直接依存、間接依存を含めて簡単に特定できます。プログラム修正前の影響範囲チェックに役立てることができます。

それでは次回、ご期待ください。

先頭へ戻る