質問: PostgreSQLのバージョンは、12.1で、Windows Server 2019で動かしています。 MySQLのON UPDATE CURRENT_TIMESTAMPと同様の動き(データをアップデートした日時を記録する) をPostgreSQLでも実現させたく、ファンクションとトリガーを使って実現しようとしています。 以下のような仕組みを考えています。 ・テーブルを作成 ``` CREATE TABLE aabbcc ( "id" integer DEFAULT nextval('aabbcc_id_seq'::regclass) NOT NULL, "cd" character varying(9) NOT NULL, "update_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT "aabbcc_pkey" PRIMARY KEY ("id") USING INDEX TABLESPACE "pg_default" ) TABLESPACE "pg_default" ; ``` ・ファンクションを作成 ``` CREATE OR REPLACE FUNCTION fnc_update_at() RETURNS trigger LANGUAGE plpgsql AS $function$ begin new.update_at := 'now()'; return new; end; $function$ ; ``` ・トリガーを作成 ``` CREATE TRIGGER aabbcc_update_at BEFORE UPDATE ON aabbcc FOR EACH ROW EXECUTE PROCEDURE fnc_update_at() ; ``` ファンクションの6行目が、「new.update_at := 'now()';」だとUPDATE時にupdate_atカラムが正しく更新されるのですが、 これだとトランザクションの開始日時になってしまうため、「new.update_at := 'statement_timestamp()';」 に変更して実行すると、データのアップデート時に以下のエラーになってしまいます。 ``` ERROR:invalid input syntax for type timestamp with time zone:"statement_timestamp()" ``` now()もstatement_timestamp()も、戻り値の型はtimestamp with time zoneなので問題なく動くと 想定していましたが、エラーになってしまいました。 なぜエラーになってしまうのでしょうか?
回答: 「PostgreSQLのnow()とstatement_timestamp()の違いに関して」のみ begin;するとわかりますが、end;までの間 ``` now() 変わらない transaction_timestamp() 変わらない当然 statement_timestamp() 変わる clock_timestamp() 変わる timeofday() 何故か変わる ``` があります。 マニュアルからすると ``` PostgreSQLでは利便性のために、下記に示されているような特別な日付/時刻入力値を サポートしています。 infinityと-infinityの値は、特別にシステム内部で表現され、 変更されずに表示されます。 他のものは、単に簡略化された表記で、 読み込まれるときに通常の日付/時刻値に変換されます。 (特にnowとその関連文字列は読み込まれるとすぐにその時点の値に変換されます。) epoch infinity -infinity now today tomorrow yesterday allballs ``` これらは’today()’でも動作しているので()までは見てないのでは? 'now' = 'now()' = 'now{}' = 'now$$' 利便性文字列の中で、nowだけ関数登録されていました、now()関数としても使えます。