|
|
前のページ 1 2
|
|
フェッチ
|
上述したカーソル属性同様、PostgreSQLではFETCH文の振る舞いも異なります。まずはOracleの例を見てください(リスト23)
|
DECLARE
CURSOR C1 IS SELECT 顧客名 FROM 顧客マスタ;
customer VARCHAR2(20);
BEGIN
OPEN C1;
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
FETCH C1 INTO customer;
DBMS_OUTPUT.PUT_LINE( '顧客名= ' || customer );
CLOSE C1;
END;
|
リスト23:OracleのFETCH文の例
|
Oracleでは最後の行に達した後も、FETCH文のターゲット変数がNULLになりません。実行結果を見てみましょう(図16)。
|
顧客名= (株)ワイキキソフト
顧客名= 鈴木商事
顧客名= 斎藤模型店
顧客名= マクロハード
顧客名= (株)ランヌ
顧客名= (株)ランヌ
PL/SQLプロシージャが正常に完了しました。
|
図16:リスト23の実行結果
|
それに比べて、PostgreSQLでは最後の行に達した後は、FETCH文のターゲット変数にNULLが代入されます(リスト24)。
|
CREATE OR REPLACE FUNCTION TEST_FETCH()
RETURNS VOID AS '
DECLARE
C1 CURSOR IS SELECT 顧客名 FROM 顧客マスタ;
customer VARCHAR(20);
BEGIN
OPEN C1;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
FETCH C1 INTO customer;
RAISE INFO ''顧客名= %'', customer;
CLOSE C1;
RETURN;
END;
' LANGUAGE 'plpgsql';
SELECT TEST_FETCH();
|
リスト24:PostgreSQLのFETCH文の例
|
さきほどのOracleの実行結果(図16)と図17を比べてください。
|
INFO: 顧客名= (株)ワイキキソフト
INFO: 顧客名= 鈴木商事
INFO: 顧客名= 斎藤模型店
INFO: 顧客名= マクロハード
INFO: 顧客名= (株)ランヌ
INFO: 顧客名= <NULL>
test_fetch
------------
(1 row)
|
図17:リスト24の実行結果
|
この微妙な振る舞いの違いがあるため、PostgreSQLではリスト25にあるような、Oracleでよく使われるループの書き方ができません。
|
DECLARE
CURSOR C1 IS SELECT 顧客名
FROM 顧客マスタ ORDER BY 顧客ID;
NAME VARCHAR2(20);
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO NAME;
EXIT WHEN C1%NOTFOUND;
END LOOP;
DBMS_OUTPUT.PUT_LINE( '顧客IDが一番大きい顧客= ' || NAME );
CLOSE C1;
END;
|
リスト25:Oracleでのループ例
|
リスト25の実行結果は次のようになります。
|
顧客IDが一番大きい顧客 = (株)ランヌ
|
|
このため、PostgreSQLではリスト26のようにフェッチ結果の変数への代入を2段階に分ける必要があります。
|
CREATE OR REPLACE FUNCTION TEST_FETCH2()
RETURNS VOID AS '
DECLARE
C1 CURSOR IS SELECT 顧客名
FROM 顧客マスタ ORDER BY 顧客ID;
NAME TEXT;
_NAME TEXT;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO _NAME;
IF NOT FOUND THEN
EXIT;
ELSE
NAME := _NAME;
END IF;
END LOOP;
RAISE INFO ''顧客IDが一番大きい顧客= %'', NAME;
CLOSE C1;
RETURN;
END;
' LANGUAGE 'plpgsql';
SELECT TEST_FETCH2();
|
リスト26:PostgreSQLでのフェッチ結果の代入例
|
これは、PostgreSQLでは次のように単純に変換してしまうと、ループを抜けた後のNAME変数の中身が最後のフェッチ内容ではなくNULLになってしまうためです。
|
LOOP
FETCH C1 INTO NAME;
EXIT WHEN NOT FOUND;
END LOOP;
RAISE INFO ''顧客IDが一番大きい顧客= %'', NAME;
|
|
前のページ 1 2
|
|
|
|
著者プロフィール
奥畑 裕樹(OKUHATA, Hiroki)
Javaとオープンソース技術を得意とする技術コンサルタント。最近のテーマは、ソフトウェア開発の全体最適をはかること。気が付けば、10才のときにプログラミングを始めて以来、常に何かを作っている…。
|
|
|
|