PL/pgSQLは、PostgreSQLデータベースシステム用の読み込み可能な手続き言語なのですが、テーブル走査をする方法としてカーソルが提供されています。今回は、このカーソルを扱うときの処理についてみてみましょう。

サンプルとかでよく見かける例

適当なテーブル(ここでは、user_id, nameを持つ、usersとしました。)を走査する場合、下記のような例をよく見かけます。

CREATE OR REPLACE FUNCTION
funcXXX()
RETURNS VOID AS $$
  DECLARE
    var_rec RECORD;
    var_cursor CURSOR FOR SELECT user_id,  name FROM users;
  BEGIN
    OPEN var_cursor;
    LOOP
	FETCH var_cursor INTO var_rec;
	IF NOT FOUND THEN
	  EXIT;
	END IF;
	RAISE NOTICE 'row1=%, row2=%', var_rec.user_id, var_rec.name;
    END LOOP;
    CLOSE var_cursor;
  END;
$$ LANGUAGE plpgsql;

正直、OPEN, CLOSEは良いのですが、FOUNDという変数の結果がFalseの場合、処理をやめる(EXIT)するというこのロジック、正直わかりづらいと感じますね。

FOR LOOPを使って同じことを書く

下記のようになります。

CREATE OR REPLACE FUNCTION
funcXXX()
RETURNS VOID AS $$
  DECLARE
    var_cursor CURSOR FOR SELECT user_id,  name FROM users;
  BEGIN
    FOR var_rec IN var_cursor LOOP 
	RAISE NOTICE 'row1=%, row2=%', var_rec.user_id, var_rec.name;
    END LOOP;
  END;
$$ LANGUAGE plpgsql;

Open, Close, FOUND、Fetch自体もなくなり非常にすっきりしています。おまけにvar_recというレコードを保存するための変数の宣言もなくなります。

カーソル走査をイディオム的に覚えるのなら、For Loopを使う形式

FOR var_rec IN cursor LOOP
  -- レコードに対して必要な処理を行う
END LOOP;

で覚えることをおすすめします。