[pgsql-jp: 35174] PL/pgSQLの再帰処理の基本について

小川 修 shuogawa @ mister.co.jp
2005年 4月 4日 (月) 14:55:52 JST


いつも勉強させて頂いております。
バージョン8よりPostgreSQLを利用し始めた小川と申します。

これまでは主にMySQLを利用しておりましたが、
PostgreSQLの提供する様々な機能に触れるにつれ、
アプリケーション開発方法の選択肢が増えた印象をうけております。
引き続き勉強して行きたいと考えておりますので、よろしくお願いします。

今回メールさせて頂きましたのは

PL/pgSQLの再帰関数についてです。

過去に話題になっております内容であり、
過去ログやPostgreSQL完全攻略ガイド改定第四版などを参考に、
実装を試みているのですが、私の知識不足でうまく動作させる事が出来ません。

実現したいことは下記の通りです

全国をルートとしました、地域の階層構造を
テーブル名をtestとし
カラムを
id:シーケンスによる通し番号
parent:親のid
name:地域の名前
flag:変更対象のカラム
とし、表現しております。

テーブル内のデータは下記の用になっております。

id parent name flag
---------------------------------------
1 NULL 全国      0
2 1    関東      0
3 2    東京      0
4 3    新宿    0
5 3    渋谷    0
6 3    六本木  0

今回、東京以下のレコードのflagを1に変更することになりました。
正しい変更が行われた場合、以下のようになります。

id parent name flag
---------------------------------------
1 NULL 全国      0
2 1    関東      0
3 2    東京      1
4 3    新宿    1
5 3    渋谷    1
6 3    六本木  1

この変更を再帰関数にて実装したいと考えおります。

私が作成した関数は以下の通りです。

-------------------------------------------------------------
CREATE OR REPLACE FUNCTION "public"."func_test" (integer) RETURNS boolean
AS'
declare
var1 alias for $1;
var_id integer;
var_record record;
begin
--引数のidのflagを1に変更
UPDATE test set flag=1 where id=var1;
--子階層を検索
FOR var_record IN select * from test where parent=var1 LOOP
    var_id:=var_record."id";
    --子階層のidを引数として、再帰呼び出しを実行
    execute func_test(var_id);
END LOOP;
return;
end;
'LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
--------------------------------------------------------------

状況としましては、この関数を実行すると
ERROR:  syntax error at end of input at character 8
とエラーが発生します。

また
戻り値にbooleanを指定している為、return true;と記述すると
---------------------------------------------------------------
CREATE OR REPLACE FUNCTION "public"."func_test" (integer) RETURNS boolean
AS'
declare
var1 alias for $1;
var_id integer;
var_record record;
begin
--引数のidのflagを1に変更
UPDATE test set flag=1 where id=var1;
--子階層を検索
FOR var_record IN select * from test where parent=var1 LOOP
    var_id:=var_record."id";
    --子階層のidを引数として、再帰呼び出しを実行
    execute func_test(var_id);
END LOOP;
return true;
end;
'LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
--------------------------------------------------------------------
ERROR:  syntax error at or near "t" at character 1
のエラーが発生します。

気づいた点としましては

過去ログや書籍で紹介されている、再帰関数の多くに、RETURN NEXT文が入っているが、 



私の場合はレコードを返す訳ではないため、RETURN NEXTをつかっていないことです。 



 これは問題でしょうか?

その他、特に原因を発見することが出来ず、メールさせて頂きました。
アドバイスよろしくお願い致します。

小川 修





pgsql-jp メーリングリストの案内