[pgsql-jp: 30944] Re: 複合型を使ったPL/pgSQL 関数について

Jun Kitamura kitamura @ zoozee.jp
2003年 9月 4日 (木) 01:47:34 JST


北村@逃避モードです。

> >CREATE OR REPLACE FUNCTION fnc_1 (EMP)
> EMP のところには、データ型を書きます。
> この場合だと RECODE だと思います。

> ごめんなさい、RECORD でした。
> 
> >DECLARE
> >    emp_record RECORD;
> と、ご自分でもこのデータ型を使っているでしょ、、、

RECORD は PL/pgSQL 内で定義されている、行の値を保持するため
のデータ型ですよ。それを関数の引数に・・って意味わからないで
す。しかも正確にはデータ型ではありません。

> >    FOR emp_record IN SELECT * FROM EMP LOOP
> この文が怪しくて、where 節が無いので、レコード全部が戻って
> きてしまいます。

怪しくないです。
FOR LOOP - END LOOP 間では各行を1行づつ FETCH して扱われます
ので、レコード全部を関数に渡すのではなく「1行づつ渡したい」
という水野さんのやりたいことに近いと思います。

FOR LOOP - END LOOP で各行を処理する際に、プライマリーキーを
指定して func_1(EMP) に渡せば、やりたいことが実現できるかと
思います。
EMP のスキーマが解らないので、仮に
col1(primary key)
col2
col3
をカラムとして持つとします。

CREATE OR REPLACE FUNCTION fnc_2()
(snip)
 FOR emp_record IN SELECT * FROM EMP LOOP
  -- EMP の1行を fnc_1 に渡して結果を result に。
  select fnc_1(ee) into result
   from EMP ee where ee.col1 = emp_record.col1;
 END LOOP;
(以下略)

としてみてはどうでしょう?

EMP という型を fnc_1 に渡すわけですが、現バージョンではテー
ブル内のレコードとしてしか渡せません。そこで、FOR-LOOPで各行
を取り出しつつ、各行のプライマリキーの値で絞り込んだ1行を 
fnc_1 に渡せば良いわけです。
お気づきかとは思いますが、FOR-LOOP 内で使いたいのは1行を絞り
込むためのプライマリーキーの値なので、SELECT * と、全てのカ
ラムを emp_recoed で取り出す必要はありません。余談ですが、
oid のあるテーブルであれば oid でもいいはずです。

さらに、この fnc_2 ですが、FOR-LOOP で囲んでいるものの、
SELECT された最後の1行を渡した fnc_1 の結果が返ってくるだけ
ですよね。何ゆえ fnc_2 を作って FOR-LOOP を使ってまでして全
行を fnc_1 に通しているのかが疑問です。
EMP内の各行を fnc_1 に渡したいのであれば、
select fnc_1(ee) from EMP ee;
で済みます。
select ee.col1,fnc_1(ee) from EMP ee order by ee.col1;
とすれば、
col1 | fnc_1
-----+------
   1 | t
   2 | t
   3 | f
ってな感じの結果が返ると思いますが。

関数をかなり省略してご質問されているようで、何がしたいのかわ
からないです。内容を公開できないのかな?という事情は解ります
が、まともな答えは期待できないと思いますよ。

あと、PL/pgSQL に関しては、どの本よりもマニュアルのが詳しく
書いてあると思います(全ての PostgreSQL関係の本を読んだわけで
はないので何ともいえませんが)。

でわ。





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