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

bxcel bxcel @ prophet.jp
2003年 11月 18日 (火) 17:46:39 JST


松本と申します。

TRIGGERの中で使用する「now」について教えてください。

あるテーブルの更新ログテーブルを作成し、TRIGGERを使用
して更新や削除の時に前のデータを保存するようにしました。
この時に更新や削除したユーザと時間を記録するようにしました。

この更新や削除した時間に「now」を使用して更新や削除を
実行した時間が入る事を期待していたのですが、複数回実行
すると2回目以降も1回目と同じ時間が入ってしまいます。

どうも同じコネクションにて複数回更新及び削除すると、
最初に取得された「now」の値が引き継がれているように
見えるのですが、何か設定を間違えているのでしょうか。

RedHat Linux 7.3 で Postgres 7.3.3 と Postgres 7.3.4で
試してみましたが現象は同じでした。

以下は詳細になります。
--ここから-----------------------------------------------------

--あるテーブル
CREATE TABLE test(
    s TEXT,
    update_time TIMESTAMP
) ;

--あるテーブルの更新ログテーブル
CREATE TABLE test_log(
    s TEXT,
    update_time TIMESTAMP,
    log_user TEXT,
    log_time TIMESTAMP
) ;

というテーブルを定義して

CREATE 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';

CREATE TRIGGER test_trigger AFTER UPDATE OR DELETE ON test
  FOR EACH ROW EXECUTE PROCEDURE test_func();

とトリガを定義しました。
まず1行データを追加して更新します。

# INSERT INTO test VALUES('a1','now');
INSERT 117494 1
# UPDATE test SET s = 'a2',update_time = 'now';
UPDATE 1

# SELECT * FROM test;
 s  |        update_time
----+----------------------------
 a2 | 2003-11-18 16:09:12.353329
(1 行)

# SELECT * FROM test_log;
 s  |        update_time        | log_user |          log_time
----+---------------------------+----------+----------------------------
 a1 | 2003-11-18 16:07:57.54663 | test     | 2003-11-18 16:09:12.353329
(1 行)

少し時間を置いてからさらに更新します。

# SELECT now();
             now
------------------------------
 2003-11-18 16:09:28.89699+09
(1 行)

# UPDATE test SET s = 'a3',update_time = 'now';
UPDATE 1
# SELECT * FROM test;
 s  |        update_time
----+----------------------------
 a3 | 2003-11-18 16:09:28.897903
(1 行)

# SELECT * FROM test_log;
 s  |        update_time         | log_user |          log_time
----+----------------------------+----------+----------------------------
 a1 | 2003-11-18 16:07:57.54663  | test     | 2003-11-18 16:09:12.353329
 a2 | 2003-11-18 16:09:12.353329 | test     | 2003-11-18 16:09:12.353329
(2 行)

すると、test_log.log_timeには、同じ時間が記入されます。
さらに更新しても同じ時間となります。

# UPDATE test SET s = 'a4',update_time = 'now';
UPDATE 1
# SELECT * FROM test_log;
 s  |        update_time         | log_user |          log_time
----+----------------------------+----------+----------------------------
 a1 | 2003-11-18 16:07:57.54663  | test     | 2003-11-18 16:09:12.353329
 a2 | 2003-11-18 16:09:12.353329 | test     | 2003-11-18 16:09:12.353329
 a3 | 2003-11-18 16:09:28.897903 | test     | 2003-11-18 16:09:12.353329
(3 行)

一度psqlを終了して起動して同じ事を実行すると

# UPDATE test SET s = 'a5',update_time = 'now';
UPDATE 1
# SELECT * FROM test_log;
 s  |        update_time         | log_user |          log_time
----+----------------------------+----------+----------------------------
 a1 | 2003-11-18 16:07:57.54663  | test     | 2003-11-18 16:09:12.353329
 a2 | 2003-11-18 16:09:12.353329 | test     | 2003-11-18 16:09:12.353329
 a3 | 2003-11-18 16:09:28.897903 | test     | 2003-11-18 16:09:12.353329
 a4 | 2003-11-18 16:09:55.772272 | test     | 2003-11-18 16:10:12.318736
(4 行)

時間が変わります。
--ここまで-----------------------------------------------------

いろいろと試していたら、以下のようにtest_log.log_timeを
「DEFAULT CURRENT_TIMESTAMP」とすると、意図したとおりに
動作する事がわかりました。

TRIGGERの中で使用する「now」と「DEFAULT CURRENT_TIMESTAMP」
では、何か意味が異なるのでしょうか。

CREATE TABLE test_log(
    s TEXT,
    update_time TIMESTAMP,
    log_user TEXT      DEFAULT CURRENT_USER ,
    log_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ;

CREATE FUNCTION test_func() RETURNS TRIGGER AS '
BEGIN
  INSERT INTO test_log(s,update_time)
      VALUES(old.s,old.update_time);
  RETURN NEW;
END;
' LANGUAGE 'plpgsql';

以上、よろしくお願いします。




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