フェッチ


   上述したカーソル属性同様、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: 顧客名=
 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;

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30