[pgsql-jp: 31510] Re: TRIGGERの中で使用する「 now」について

bxcel bxcel @ prophet.jp
2003年 11月 19日 (水) 14:56:41 JST


松本と申します。

> たぶん、
> CREATE or replace FUNCTION test_func() RETURNS TRIGGER AS '
> BEGIN
>   INSERT INTO test_log
>       VALUES(old.s,old.update_time,CURRENT_USER,''now()'');
>  --                                             ^^^^^^^^^
>   RETURN NEW;
> END;
> ' LANGUAGE 'plpgsql';
> 
> のように書き直されたかと思いますが、正解は
> 
>       VALUES(old.s,old.update_time,CURRENT_USER,now());
> 
> です。

あ....、全くその通りです。「''now()''」としてました。

> ''now()'' とすると、この PL/pgSQL が初めて実行された時の日時
> になってしまいます。初回実行時にコンパイルされ、'' で囲まれ
> ているため固定された文字列(now()の実行結果)が入ります。

なるほど、そういう仕組みだったんですね。理解不足でした。
シーラカンス本のトリガ用関数の定義を参考にさせて頂いたのですが、
もしかしたら''で囲むのがなんか影響しているのかと思い、

       VALUES(old.s,old.update_time,CURRENT_USER,now);

としてみたりもしたのですが、エラーとなってしまったので、
''で囲むものと思い込んでおりました。
関数とリテラル値に関して理解できてませんでした。
鈴木さんに教えてもらった時に気づくべきでしたね。

あと「初回実行時にコンパイルされ」についてですが、これは
「postgresを起動した後の初回」ではなく、コネクション単位
なんですね。

期待した通りの結果となっていた時もあったので、おかしいなぁ
と思っていたのですが、コネクションプールの使いまわし具合?
だったんですね。

同じく鈴木さんに教えてもらったマニュアルを読み返してみると
最後の方の「Note:」に「定数が解釈された時、システムが 
now を timestamp に変換するので....」という記述があり
ここからも私が期待した結果と違う理由が読み取れましたね。

> ・・・・う。色々と実験されてるようですね。
> 外してたらごめんなさい。

レベルの低さをさらしちゃいまして恥ずかしいです....
とっても遠回りしちゃってましたね。
ありがとうございました。



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