[pgsql-jp: 39072] Re: 複数テーブルからの検索結果を、複数行列返す関数

ITAGAKI Takahiro itagaki.takahiro @ oss.ntt.co.jp
2008年 1月 25日 (金) 17:55:44 JST


NASUNO Isao <isao.nasuno @ ctc-g.co.jp> wrote:

> これからも関数を作る場面が出てきそうなのですが、
> PL/pgSQL と SQL の違いが、私にはよく飲み込めません。
> 
> PL/pgSQL=SQL手続き言語というのは、LOOPやFORなどを使って、
> 手続き式にSQLを処理するような記述をしたものでしょうか。
> 
> 今回、FOR、LOOP、IN EXECUTE などを使った例も参考にしたのですが(難しくて挫折した)、
> これらには、教えていただいた方法は使えないということでしょうか?

例示された testfunc() ならばシンプルなので、SQL のみで実現できると思います。
もし、testfunc() でもっと複雑なことをしようと思うと、SQL だけでは足りず、
フロー制御などがある手続き言語 (PL/pgSQL など) を使うことになると思います。

しかし、ストアド関数に SQL 以外の言語を使った場合、今回の書き方では
エラーになるようです。エラーを避けるには、「複数テーブルからの検索結果を
マージするストアド関数」も自作する必要がありそうです。
(二重のFORループで実現できそうですが、効率が悪い場合も若干あります。)

SQL 関数の場合はそのまま処理できる理由は、関数のインライン化が効き、
単純な JOIN にまでクエリを変形できているからだと思われます。


-- PL/pgSQL で同じ機能を実現(ただしエラーになる)
CREATE FUNCTION testfunc2(integer,
   OUT id integer,
   OUT key text)
RETURNS SETOF record AS
$$
DECLARE
  r record;
BEGIN
  FOR id, key IN SELECT
      header.id, target.name||' '||target.descript
    FROM
      header,
      target
    WHERE
      header.id=$1 and header.targetid=target.id
  LOOP
    RETURN NEXT;
  END LOOP;
END;
$$ LANGUAGE plpgsql;




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