[pgsql-jp: 40740] Re: トリガーファンクション?で実現可能でしょうか?

Tomoaki Sato sato @ sraoss.co.jp
2011年 4月 18日 (月) 22:27:58 JST


佐藤です。

From: yukihito miso <oira3ryu @ gmail.com>
Date: Mon, 18 Apr 2011 21:36:30 +0900

> トリガーファンクション?というのでしょうか?
> 
> id sec col cat
> -------------------
>  1   1  1c   1
>  2   2  2c   1
>  3   1  4c  11
>  4   2  8c  11
>  5   3 12c  11
> 
> 上記のテーブルでcatが11の場合
> 
> イメージですが
> merge_col := 1c, 2c, 3c
> ということをしたい。

上記の説明ではよく分からないのですが、cat 列の値が 11 の行の col 列の
値をカンマ区切りで連結した文字列を取得したいということでしょうか。

だとしたら、トリガはテーブルの更新をきっかけに関数を実行する仕組みなの
で、トリガではなく SELECT で実現できます。

=> TABLE tablea;
 id | sec | col | cat 
----+-----+-----+-----
  1 |   1 | 1c  |   1
  2 |   2 | 2c  |   1
  3 |   1 | 4c  |  11
  4 |   2 | 8c  |  11
  5 |   3 | 12c |  11
(5 rows)

=> SELECT array_to_string(array_agg(col), ', ') AS merge_col
->     FROM tablea WHERE cat = '11';
  merge_col  
-------------
 4c, 8c, 12c
(1 row)

ちなみに、

> ためしに、
> 
> CREATE OR REPLACE FUNCTION merge_col()
>   RETURNS trigger AS
> $BODY$
>   DECLARE
>     cnt int;
> BEGIN
>   PERFORM COUNT(col) AS cnt FROM tableA WHERE cat = NEW.cat;
> 
> FOR i IN 1..cnt LOOP
>   SELECT col FROM tableA WHERE sec = i AND cat = NEW.cat;
>   NEW.merge_col := col;
>   RETURN NEW;
> END LOOP;
>   NEW.merge_col := merge_col;
>   RETURN NEW;
> 
> END;
> $BODY$
>   LANGUAGE plpgsql VOLATILE
>   COST 100;
> ALTER FUNCTION merge_col() OWNER TO yu2admin;
> 
> としてみましたが
> 「upper bound FOR of loop cannot be null」
> というエラーが出てしまいます。

これは、FOR ループの上限に指定している変数 cnt が NULL なのでエラーに
なっています。

PERFOM で変数 cnt に tablea の行数を代入しようとしているんだと思います
が、PERFORM は実行結果が不要で破棄してもいい場合に使用するコマンドです。
実行結果を変数に代入したいなら SELECT INTO を使用する必要があります。

  SELECT count(col) INTO cnt FROM tablea WHERE cat = NEW.cat;


----
Tomoaki Sato <sato @ sraoss.co.jp>
SRA OSS, Inc. Japan


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