外部ユーザー定義関数の作成

外部ユーザー定義関数 は、プログラミング言語で記述された関数であり、他の SQL プログラムと類似しています。 IFI 呼び出しを介して発行される静的 SQL ステートメントまたは動的 SQL ステートメント、IFI 呼び出し、および Db2 コマンドを組み込むことができます。

プロシージャー

外部ユーザー定義関数は、アセンブラー、C、C++、COBOL、PL/I、または Java™ で記述できます。

COBOLで記述されたユーザー定義関数には、他のDb2COBOLプログラムと同様に、オブジェクト指向の拡張機能を含めることができます。 Javaで記述されたユーザー定義関数は、Java固有のコーディングガイドラインと制限に従う必要があります。

ユーザー定義関数は、CONNECT または SET CONNECTION 文を使用して DRDA アクセスを行うことで、リモートデータにもアクセスできます。

ユーザー定義関数プログラムの制約事項
ユーザー定義関数を作成するときは、以下の制約事項を守ってください。
  • Db2 は、ユーザー定義関数とのインタフェースとして資源回収サービス付属設備 (RRSAF)を使用するため、ユーザー定義関数にRRSAFの呼び出しを含めることはできません。 Db2 ユーザー定義関数内で見つかったRRSAFコールをすべて拒否します。
  • ユーザー定義関数がパラメーター SCRATCHPAD または EXTERNAL ACTION を指定して 定義されていない場合、そのユーザー定義関数は、呼び出しのたびに 同じタスクのもとで実行されることを保証されません。
  • ユーザー定義関数では、COMMIT または ROLLBACK ステートメントを 実行できません。
  • ユーザー定義スカラー関数でオープンされたカーソルは、 すべてクローズする必要があります。 Db2 ユーザー定義のスカラー関数が、完了前に開いたすべてのカーソルを閉じなかった場合、SQLエラーを返します。
  • ユーザー定義関数プログラムを作成する場合の言語選択時、 その言語においてルーチンに渡すことができるパラメーター数の制約に 注意する必要があります。 特にユーザー定義表関数では、 多くのパラメーターを必要とする場合があります。 渡すことができるパラメーター数については、ユーザー定義関数の 作成を予定している言語のプログラミングのガイドを調べてください。
  • LOB ファイル参照変数をパラメーターとしてユーザー定義関数に渡すことはできません。
  • ユーザー定義関数は LOB ファイル参照変数を戻すことはできません。
  • タイプ XML のパラメーターをユーザー定義関数に渡すことはできません。 XML 列を含む表またはビューは、表ロケーター・パラメーターとして指定できます。 ただし、ユーザー定義関数の本体内で XML 列を参照することはできません。
主プログラムまたはサブプログラムとしてのユーザー定義関数のコーディング
ユーザー定義関数は、主プログラムかサブプログラムのいずれかとしてコーディングできます。 プログラムのコーディング方法は、ユーザー定義関数を定義した方法と一致している必要が あります。この定義には、PROGRAM TYPE MAIN か PROGRAM TYPE SUB パラメーターを使います。 主な違いは、メインプログラムが開始されるとき、 Language Environment® が外部ユーザー定義関数が使用するアプリケーションプログラム記憶領域を割り当てる点です。 メインプログラムが終了すると、 Language Environment はファイルを閉じ、動的に割り当てられた記憶領域を解放します。

ユーザー定義関数をサブプログラムとしてコーディングし、 ストレージとファイルをユーザー自身で管理すると、パフォーマンスが向上します。 ユーザー定義関数は、終了する前に必ず、 割り振られたストレージをすべて解放する必要があります。 複数のユーザー定義関数呼び出し間でまたがってデータを保持するには、 スクラッチパッドを使用します。

外部リソースにアクセスするユーザー定義表関数は、 サブプログラムとしてコーディングする必要があります。 また定義者が、CREATE FUNCTION または ALTER FUNCTION ステートメントに、 EXTERNAL ACTION パラメーターを確実に指定しなければなりません。 サブプログラムのプログラム変数は、複数のユーザー定義関数呼び出し間でまたがってそのままの状態で残り 、EXTERNAL ACTION パラメーターを使用すると、ユーザー定義関数は、ある呼び出しから別の呼び出しまで、 必ず同一アドレス・スペースにとどまることが保証されます。

並列処理の考慮事項
定義者がユーザー定義スカラー関数の定義にパラメーター ALLOW PARALLEL を指定し、 しかも呼び出し側の SQL ステートメントが並列状態で実行される場合、 このユーザー定義スカラー関数は並列タスクのもとで実行できます。 Db2 並列タスクごとにユーザー定義関数の別々のインスタンスを実行します。 関数プログラムを作成する場合、予期しない結果を避けるために、 次のパラメーター値が ALLOW PARALLEL とどのような相互作用をするかを理解する必要があります。
  • SCRATCHPAD

    SQLステートメントがALLOWPARALLELパラメーターで定義されたユーザー定義関数を呼び出すと、Db2関数への各参照の並列タスクごとに1つのスクラッチパッドが割り当てられます。 この方法は、以下のような使用方法の場合は、予期しない結果、または誤った結果となることもあります。

    例えば、このユーザー定義関数は、スクラッチパッドを使用して、自分が 呼び出される回数を数えるものとします。 スクラッチパッドが各並列タスクに対して割り振られる場合、この数は並列タスク が行った呼び出しの回数であり、SQL ステートメント全体の数ではないため、意図した結果ではありません。

  • FINAL CALL

    あるユーザー定義関数が、その関数への最終呼び出しに対して、 外部アクション (メモ送信など) を行うと、その関数呼び出しに対して一度ではなく、 各並列タスクに対して 1 つのメモが送信されます。

  • EXTERNAL ACTION

    外部アクションを伴うユーザー定義関数によっては、その 関数が並列タスクによって実行されると、誤った結果を受け取ることがあります。

    例えば、関数が、関数への各初期呼び出しに対してメモを送信する場合、 関数呼び出しに対して一度ではなく、並列タスクごとに 1 つのメモが送信されます。

  • NOT DETERMINISTIC

    非決定論的ユーザー定義関数は、並列タスク下で実行すると正しくない結果を生じる場合があります。

    例えば、並列タスクで次の照会を実行するとします。
    SELECT * FROM T1 WHERE C1 = COUNTER();
    COUNTER は、呼び出されるたびにスクラッチパッドの変数を増分する ユーザー定義関数です。 同じ入力が常に同じ出力を生成するとは限らないため、カウンターは決定論的ではありません。 表 T1 には、次の値を持つ 1 つの列 C1 が入っています。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    クエリが並列処理なしで実行されると、Db2表T1の各行に対して1回COUNTERが呼び出され、Db2 COUNTERが最初に実行されるときに初期化されるカウンター用のスクラッチパッドが1つあります。 最初に COUNTER が実行 されると、COUNTER は 1 を戻し、2 番目の実行では 2 を戻し、以下同様です。 照会の結果表の値は次のようになります。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    ここで、クエリが並列処理で実行され、 Db2 が3つの並列タスクを作成したと仮定します。 Db2 並列タスクごとに、WHERE = COUNTER() という述語を実行します。 C1 このことは、各並列タスクがそれ自体のユーザー定義関数のインスタンスを呼び出し、 その独自のスクラッチパッドを持つことを意味します。 Db2 並列タスクごとにユーザー定義関数が最初に呼び出された際に、スクラッチパッドをゼロに初期化します。

    並列タスク 1 が行 1 から 3 を処理し、 並列タスク 2 が行 4 から 6 を処理し、並列タスク 3 が行 7 から 10 を処理すると、 次の結果になります。
    • 並列タスク 1 の実行時に、C1 は値 1、2、および 3 を持ち、 COUNTER は値 1、2、および 3 を戻すので、照会は値 1、2、および 3 を戻します。
    • 並列タスク 2 の実行時に、C1 は値 4、5、および 6 を持ちますが、 COUNTER は値 1、2、および 3 を戻すので、照会は行を戻しません。
    • 並列タスク 3 の実行時に、C1 は値 7、8、9、および 10 を持ちますが、 COUNTER は値 1、2、3、および 4 を戻すので、照会は行を戻しません。
    したがって、クエリから予想される10行を返す代わりに、Db23行のみを返します。