Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2004/11/25

counter hits
since 1999/11/06


ストアドプロシージャ・ファンクションから配列を受け取る

alertここにある情報はかなり古くなっており、正しくなくなっている可能性があります。掲載しているサンプルコードiなどは、最新のPHPでは動作しない、もしくは、別途設定・調整が必要になるかも知れません。情報を鵜呑みにせず、あなたの手を動かして、あなたの目で確認してください。

caution[2004/11/25] 今までに動作確認できた環境は、PHP4.2.0/4.2.1/4.2.2+Oracle8.1.6i/8.1.7i Enterprise Edition、PHP4.3.0pre2/4.2.2+Oracle8.1.5i、PHP4.3.9+Oracle9.2.0i Standard Editionという環境です。その他情報をお持ちの方は是非ご一報下さい。

php-usersにも流しましたが、ストアドプロシージャ・ファンクションから配列(VARRAY型)を受け取るには、PHP4.0.6から追加されたOCINewCollection関数を使います。例として、以下のようなVARRAY型のTYPEを使って、emp表のENAMEを返すプロシージャ・ファンクションを考えてみます。

●TYPEの定義
CREATE OR REPLACE TYPE test_arr AS VARRAY(100) OF VARCHAR2(10);
/
SHOW ERRORS  

まずは、php-usersに流したファンクションの場合。。。

●ストアドファンクションの定義
CREATE OR REPLACE FUNCTION getUsers(
    nm IN VARCHAR2 := ''
) RETURN test_arr
IS
    CURSOR c1 IS
        SELECT ename FROM emp
        WHERE ename LIKE nm||'%';

    cnt INTEGER := 0;
    ret test_arr := test_arr();
BEGIN
    FOR csr IN c1 LOOP
        cnt := cnt + 1;
        ret.EXTEND(1);
        ret(cnt) := csr.ename;
    END LOOP;

    RETURN ret;
EXCEPTION
    WHEN OTHERS THEN
        RETURN test_arr();
END;
/
SHOW ERRORS
  

これに対するPHPスクリプトは、以下のようになります。

●PHPスクリプト(ストアドファンクションの場合)

<?php
    $nm = "";

    $conn = OCILogon("scott","tiger", "orcl");

    /**
     * 新規コレクションの作成
     */
    $coll = OCINewCollection($conn, "TEST_ARR");

    /**
     * ストアドファンクションの実行
     */
    $stmt = OCIParse($conn, "begin :ret := getUsers(:nm); end; ");

    /**
     * PHP変数をOracleプレースホルダにバインド
     */
    OCIBindByName($stmt, ':RET', $coll, -1, OCI_B_SQLT_NTY);
    OCIBindByName($stmt, ':NM', $nm, -1);

    /**
     * 実行
     */
    OCIExecute($stmt);

    /**
     * データの表示
     */
    for ($i = 0; $i < $coll->size(); $i++) {
        printf("%d => %s<br />", $i, $coll->getElem($i));
    }

    /**
     * コレクションオブジェクトのリソースを解放
     */
    OCIFreeCollection($coll);
    OCIFreeStatement($stmt);
    OCILogOff($conn);
?>

次に、プロシージャの場合。。。

●ストアドプロシージャの定義
CREATE OR REPLACE PROCEDURE pgetUsers(
    nm IN VARCHAR2 := '',
    ret OUT test_arr
)
IS
    CURSOR c1 IS
        SELECT ename FROM emp
        WHERE ename LIKE nm||'%';

    cnt INTEGER := 0;
BEGIN
    ret := test_arr();
    FOR csr IN c1 LOOP
        cnt := cnt + 1;
        ret.EXTEND(1);
        ret(cnt) := csr.ename;
    END LOOP;
EXCEPTION
    WHEN OTHERS THEN
        ret := test_arr();
END;
/
SHOW ERRORS
  

これに対するPHPスクリプトの差分は、以下のようになります。ファンクションとの違いは、実行する無名プロシージャだけです。

●PHPスクリプト(ストアドプロシージャの場合)

<?php
            :
    /**
     * ストアドプロシージャの実行
     */
    $stmt = OCIParse($conn, "begin pgetUsers(:nm, :ret); end; ");
            :
?>

初め、PHPマニュアルにもあるOCICollSize関数やOCICollGetElem関数を使ってみたところ、何も帰ってこなかったのでまだダメかと思いましたが、OCINewCollection関数の戻り値がObject(gettype関数で確認)でしたので、「ひょっとしてメソッドなら。。。」ということで試してみました。関数でうまくいった方がいらっしゃいましたら、情報をお願いします(^-^;



About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2004 by Hideyuki SHIMOOKA all rights reserved.