SQL 解説書


メソッド

構造タイプのデータベース・メソッドは、一連の入力データ値と、 一連の結果値との関連のことです。ここで、 最初の入力値 (またはサブジェクト引き数) は、メソッドと同じ値になるか、 サブジェクト・タイプ (サブジェクト・パラメーター ともいう) のサブタイプになります。 たとえば、タイプが ADDRESS である CITY というメソッドは、 タイプが VARCHAR の入力データ値に渡すことができます。 結果は ADDRESS (または ADDRESS のサブタイプ) になります。

メソッドは、ユーザー定義構造タイプの定義の一部として、暗黙的にあるいは明示的に定義されます。

暗黙的に定義されたメソッドは、構造タイプごとに作成されます。 また、構造タイプの属性ごとに、監視用メソッドが定義されます。 監視用メソッドを使うと、アプリケーション側は、 該当タイプのインスタンスの属性値を知ることができます。 変更メソッドも属性ごとに定義されます。これにより、アプリケーション側では、 タイプ・インスタンスの属性の値を変更することによってタイプ・インスタンスを変更できます。 上記の CITY メソッドは、タイプ ADDRESS の変更メソッドの一例です。

明示的に定義したメソッド、すなわちユーザー定義メソッド は、 CREATE TYPE (または ALTER TYPE ADD METHOD) および CREATE METHOD ステートメントを組み合わせて使用して、 SYSCAT.FUNCTIONS のデータベースに登録されるメソッドです。 特定構造タイプ用に定義されたメソッドはすべて、そのタイプと同じスキーマで定義されます。

構造タイプのユーザー定義メソッドの使用により、 DB2 ではユーザーおよびアプリケーションの開発者は、 データベース・システムの関数を拡張することができます。 このことは、ユーザーもしくは他社によって提供されたメソッド定義を追加し、 データベース・エンジンの構造タイプ・インスタンスに適用することにより実現します。 追加したメソッド定義により、データベースから行を取り出したり、 取り出したデータに対して関数を適用するときの場合とは逆に、パフォーマンスが著しく向上します。 さらに、データベース・メソッドを定義することにより、データベースは、 アプリケーションで使われるエンジン内にある同じメソッドを活用できます。 このようにすると、アプリケーションとデータベースとの間のやり取りの効率が、著しく向上します。 これは、さらにオブジェクト指向になっているため、 アプリケーション開発者は、生産性を高めることができます。

外部および SQL ユーザー定義メソッド

ユーザー定義メソッドは、外部メソッドとするか、 SQL 式に基づくものとすることができます。 外部メソッドは、オブジェクト・コード・ライブラリーと、 メソッド呼び出し時に実行されるそのライブラリー内の関数によって、 データベースに対して定義されます。 SQL 式に基づいたメソッドは、メソッドの呼び出し時に、その SQL 式の結果を戻します。 そのようなメソッドでは、すべてが SQL で作成されているので、 オブジェクト・コード・ライブラリーが必要ありません。

ユーザー定義メソッドでは、呼び出されるたびに単一値の応答を戻すことができます。 この値は、構造タイプとすることができます。 また、メソッドを (SELF AS RESULT を使用して) タイプ保持 として定義し、 メソッドの戻されるタイプとして、動的タイプのサブジェクト引き数を戻すようにすることが可能です。 暗黙的に定義した変更メソッドは、タイプ保持されます。

メソッド・シグニチャー

メソッドは、そのサブジェクト・タイプ、メソッド名、パラメーター数、 およびそのパラメーターのデータ・タイプによって識別されます。 これはメソッド・シグニチャーと呼ばれ、データベース内で固有である必要があります。

以下の場合に、同じ名前を付けられた構造タイプのメソッドが、複数存在する可能性があります。

複数のメソッド・インスタンスを持つメソッド名のことを、多重定義メソッド といいます。 あるメソッド名があるタイプ内で多重定義される場合、そのタイプには、 その名前で 2 つ以上のメソッドがあるということです (それぞれのタイプにはすべて、 異なるパラメーター・タイプがあります)。 メソッド名はサブジェクト・タイプ階層においても多重定義可能です。 その場合、そのタイプ階層にその名前のメソッドが 2 つ以上ありますが、 それぞれのメソッドには異なるパラメーター・タイプがなければなりません。

メソッドの呼び出し

メソッドを呼び出すときには、許可されている文脈で、 構造タイプ・インスタンス (サブジェクト引き数) への参照と二重ドット演算子の両方が先頭に記されているメソッド名を参照します。 その後に、括弧で囲まれた引き数のリストが続きます。 実際に呼び出されるメソッドは、次の項で説明されているメソッド解決法により、 静的タイプのサブジェクト・タイプに基づいて決められます。 関数呼び出しを使い、WITH FUNCTION ACCESS で定義されているメソッドを呼び出すこともできます。 その場合、関数解決のための通常のルールが適用されます。

メソッド解決

特定のメソッドの呼び出しに対して、データベース・マネージャーは、 同じ名前をもつ呼び出し可能なメソッドの中でどれが「最適」かを判別する必要があります。 メソッド解決時には、関数 (組み込みまたはユーザー定義) は考慮されません。

引き数とは、呼び出し時にメソッドに渡される値です。 SQL の中で呼び出されるとき、メソッドには (特定構造タイプの) サブジェクト引き数、 およびゼロ個以上の引き数のリストが渡されます。 このような引き数は、 引き数が引き数リストの位置によって決定されるという意味で定位置と言えます。 このサブジェクト引き数は、最初の引き数であると見なされます。 パラメーターは、メソッドへの入力の形式上の定義です。

メソッドがデータベースに対して暗黙的に (特定タイプ用にシステム生成される)、 またはユーザーによって (ユーザー定義メソッド) 定義されるとき、 メソッドのパラメーターが (最初のパラメーターとしてのサブジェクト・パラメーター付きで) 指定されます。 パラメーターの定義の順序がパラメーターの位置、 およびその結果としてパラメーターの意味を定義することになります。 したがって、どのパラメーターもメソッドの特定の定位置入力です。 呼び出し時に、引き数リスト中のその位置によって、引き数は特定のパラメーターに対応します。

データベース・マネージャーは、呼び出しで指定されるメソッド名、引き数の数とデータ・タイプ、 サブジェクト引き数の静的タイプ (およびそのスーパータイプ) 用に同じ名前をもつすべてのメソッド、 対応するパラメーターのデータ・タイプを使用して、あるメソッドを選択するかどうかの判断基準とします。

メソッドを決定する過程で発生する可能性のある結果について以下に示します。

  1. 特定のメソッドが最適であると判断される場合。 たとえば、シグニチャーが以下のように定義されたタイプ SITE の RISK というメソッドを考えてみます。
       PROXIMITY(INTEGER) FOR SITE 	
       PROXIMITY(DOUBLE) FOR SITE
    

    続くメソッドの呼び出しは次のようになります (ここで、ST は SITE 列、DB は DOUBLE 列です)。

       SELECT ST..PROXIMITY(DB) ...
    

    この場合は、2 番目の PROXIMITY が選択されます。

    以下のようにメソッドが呼び出される場合は (SI は SMALLINT 列)、

       SELECT ST..PROXIMITY(SI) ...
    

    最初の PROXIMITY が選択されます。これは、SMALLINT は INTEGER にプロモート可能であり、 優先順位リストでの順位がさらに下になる DOUBLE よりも一致性が高いためです。

    構造タイプである引き数について考慮する場合、優先順位リストには、 静的タイプの引き数のスーパータイプが含まれます。 最適なのは、構造タイプ階層の中で、 静的タイプの関数引き数に最も近いスーパータイプ・パラメーターで定義する関数です。

  2. 許容できる適合性をもつメソッドがないと判断される場合。 たとえば、前出の例と同じ 2 つの関数が指定され、 以下のように関数が参照されたとします (C は CHAR(5) 列)。
       SELECT ST..PROXIMITY(C) ...
    

    この場合、引き数はどちらの PROXIMITY 関数のパラメーターとも整合性がありません。

  3. タイプ階層のメソッド、 および呼び出し時に渡される引き数の数とデータ・タイプに基づいて特定のメソッドが選択される場合。 たとえば、シグニチャーが以下のように定義された、 タイプ SITE および DRILLSITE (SITE のサブタイプ) の RISK というメソッドを考えてみます。
       RISK(INTEGER) FOR DRILLSITE
       RISK(DOUBLE) FOR SITE
    

    続くメソッドの呼び出しは次のようになります (ここで、DRST は DRILLSITE 列、DB は DOUBLE 列です)。

       SELECT DRST..RISK(DB) ...
    

    DRILLSITE は SITE へプロモートできるので、この場合は、2 番目の RISK が選択されます。

    以下のようにメソッドが参照される場合は (SI は SMALLINT 列)、

       SELECT DRST..RISK(SI) ...
    

    最初の RISK が選択されます。これは、 SMALLINT は INTEGER にプロモート可能 (優先順位リストでの順位が DOUBLE よりも近い) であり、 DRILLSITE は、SITE よりも一致性が高いスーパータイプであるためです。

    同じタイプ階層内のメソッドで同じシグニチャーを使い、 サブジェクト・パラメーター以外のパラメーターで利用することはできません。

最適な選択をするための方式

引き数のデータ・タイプと、 対象とするメソッドのパラメーターに定義されているデータ・タイプとの比較は、 似たような名前のメソッドの中でどれが『最適』かを決定する基準となります。 考慮しているメソッドの結果のデータ・タイプは、この決定には関係しないことに注意してください。

メソッド解決は、以下の手順で行われます。

  1. まず、カタログ (SYSCAT.FUNCTIONS) から、 以下のすべての条件が真となるすべてのメソッドを探します。
  2. 次に、メソッド呼び出しの個々の引き数を左から右に検討していきます。 左端の引き数 (すなわち最初の引き数) は、暗黙的な SELF パラメーターです。 たとえば、タイプ ADDRESS_T に定義したメソッドには、 暗黙的な最初のパラメーターとしてタイプ ADDRESS_T があります。

    引き数ごとに、その引き数に対して最適な一致ではない関数をすべて除去していきます。 ある引き数の最適な一致とは、 表 5 の引き数データ・タイプに対応する優先順位リストの中で、 そのデータ・タイプのパラメーターをもつ関数が存在するデータ・タイプのうち、 最初に記述されているデータ・タイプです。

    長さ、精度、位取り、および "FOR BIT DATA" 属性は、この比較では考慮されません。 たとえば、DECIMAL(9,1) の引き数は DECIMAL(6,5) のパラメーターと完全に一致するとみなされ、 また VARCHAR(19) の引き数は VARCHAR(6) のパラメーターと完全に一致するとみなされます。

    ユーザー定義構造タイプ引き数に最適なのは、それ自体です。 次に適しているのは、すぐ上のスーパータイプです。このことは、 引き数の各スーパータイプに当てはまります。 ここで考慮しているのは、静的タイプ (宣言済みタイプ) の構造タイプ引き数であり、 動的タイプ (最も特定的なタイプ) ではありません。

  3. ほとんどの場合、ステップ 2 の実行後に候補メソッドが 1 つ残ります。 このメソッドを選択します。
  4. ステップ 2 の後で候補となるメソッドが残らなかった場合は、エラー (SQLSTATE 42884) になります。

メソッド解決の例

以下は、正常なメソッド解決の例を示しています。

GOVERNOR の階層内で定義された3 つの構造タイプに関し、 HEADOFSTATE のサブタイプとしての EMPEROR のサブタイプとして、 7 つの FOO メソッドがあります。それぞれは、シグニチャーで登録されています。

   CREATE METHOD FOO (CHAR(5), INT, DOUBLE)  FOR HEADOFSTATE SPECIFIC FOO_1 ...
   CREATE METHOD FOO (INT, INT, DOUBLE)      FOR HEADOFSTATE SPECIFIC FOO_2 ...
   CREATE METHOD FOO (INT, INT, DOUBLE, INT) FOR HEADOFSTATE SPECIFIC FOO_3 ...
   CREATE METHOD FOO (INT, DOUBLE, DOUBLE)   FOR EMPEROR     SPECIFIC FOO_4 ... 
   CREATE METHOD FOO (INT, INT, DOUBLE)      FOR EMPEROR     SPECIFIC FOO_5 ...
   CREATE METHOD FOO (SMALLINT, INT, DOUBLE) FOR EMPEROR     SPECIFIC FOO_6 ...
   CREATE METHOD FOO (INT, INT, DEC(7,2))    FOR GOVERNOR    SPECIFIC FOO_7 ...  

以下のようにメソッドが参照されるとします (I1 および I2 は INTEGER 列、 D は DECIMAL 列、そして E は EMPEROR 列です)。

   SELECT E..FOO(I1, I2, D) ...

アルゴリズムに従ってゆきます。

タイプ GOVERNOR は EMPEROR のサブタイプなので (スーパータイプではない)、 FOO_7 は候補から除かれます。

パラメーターの数が違っているため、FOO_3 は候補から除かれます。

第 1 引き数 (サブジェクト引き数ではない) が第 1 パラメーターのデータ・タイプにプロモートできないため、 FOO_1 と FOO_6 はどちらも候補から除かれます。 この時点で複数の候補が残っているため、次に引き数が順に検討されます。

サブジェクト引き数の場合、FOO_2 はスーパータイプですが、 FOO_4 と FOO_5 はサブジェクト引き数に一致しています。

最初の引き数については、 残りのメソッド FOO_4 および FOO_5 がその引き数タイプと完全に一致します。 この検討ではどのメソッドも検討の対象から除かれないため、 次の引き数を検討する必要があります。

2 番目の引き数では、FOO_5 が完全に一致しているのに対し、 FOO_4 は一致していないため、FOO_4 が検討の対象から除かれます。 これにより、メソッド FOO_5 が選ばれます。

メソッドの呼び出し

メソッドが選択された後も、いくつかの理由でそのメソッドの使用が許可されない場合があります。

個々のメソッドは特定のデータ・タイプの結果を戻すように定義されています。 この結果のデータ・タイプが、メソッドが呼び出される文脈と互換性がない場合、エラーが生じます。 たとえば、STEP というメソッドが定義されていて、 結果としてそれぞれが別々のデータ・タイプを持っているとします。

   STEP(SMALLINT) FOR TYPEA RETURNS CHAR(5)
   STEP(DOUBLE) FOR TYPEA RETURNS INTEGER

以下のようにメソッドが参照されると (S は SMALLINT 列で TA は TYPEA の列)、

  SELECT 3 + TA..STEP(S) ...

引き数タイプが完全に一致しているため、最初の STEP が選択されます。 しかし、結果のタイプが加法演算子の引き数として求められる数値タイプではなく CHAR(5) であるため、 ステートメントではエラーになります。

選択したメソッドがタイプ保持メソッドである場合、以下の点に注意してください。

これは、タイプ保持メソッド定義で指定した結果タイプのサブタイプになる可能性がありますが、 逆に、メソッドの処理時に実際に戻される動的タイプのスーパータイプになる場合もあります。

メソッド呼び出しの引き数が、選択されたメソッドのパラメーターのデータ・タイプと完全一致でない場合、 列への割り当てと同じ規則を適用して、 実行時に引き数がパラメーターのデータ・タイプに変換されます (割り当てと比較を参照)。 これには、引き数とパラメーターの間で精度、位取り、 または長さが異なる場合も含まれます。ただし、引き数の動的タイプが、 パラメーターの静的タイプのサブタイプである場合を除きます。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]