PostgreSQLのタイムスタンプを自動的に更新する方法


132

MySQLでCURRENT_TIMESTAMPを使用して実行できるように、新しい行が挿入されたときにコードがタイムスタンプを自動的に更新できるようにしたい。

PostgreSQLでこれをどのように実現できますか?

CREATE TABLE users (
    id serial not null,
    firstname varchar(100),
    middlename varchar(100),
    lastname varchar(100),
    email varchar(200),
    timestamp timestamp
)

6
ちなみに、のデータ型はtimestamp、SQL仕様での省略形として定義されていますTIMESTAMP WITHOUT TIME ZONEPostgresのエキスパートであるDavid E. Wheelerが説明しているように、これはほぼ間違いなく望ましいことではありません。もう1つのタイプTIMESTAMP WITH TIME ZONEはおそらく必要なもので、日付と時刻をUTCに調整するために渡されたタイムゾーンオフセット情報を使用します(ただし、タイプ名にもかかわらず実際にはそのタイムゾーン情報を格納しません)。
バジルブルク2014年

3
これをもう一度再学習した後、デフォルト、関数、およびトリガーを使用して行の作成と変更の両方の日時をログに記録することに関する詳細なブログ投稿を書きました。Postgresで使用するための完全なサンプルSQLおよびPL / pgSQLコードが含まれています。
バジルブルク2014年

回答:


197

挿入中に列にデータを入力するには、DEFAULT値を使用します。

CREATE TABLE users (
  id serial not null,
  firstname varchar(100),
  middlename varchar(100),
  lastname varchar(100),
  email varchar(200),
  timestamp timestamp default current_timestamp
)

INSERTステートメントに値を指定することにより、その列の値を明示的に上書きできることに注意してください。それを防ぎたい場合はトリガーが必要です。

行が更新されるたびにその列を更新する必要がある場合も、トリガーが必要です(EJ Brennanが言及)。

通常、列名に予約語を使用することはお勧めできません。あなたは別の名前を見つける必要がありますtimestamp


14
Postgresには、(1)実際の現在の時刻、(2)ステートメントが開始した時刻、(3)トランザクションが開始した時刻を通知する機能があることに注意してください。ここに示す例は、現在のトランザクションの開始です。他の2つの可能性とは対照的に、それを望む場合もあれば望まない場合もあります。
バジル

6
予約語と衝突する名前を避けることについての良いボーナスポイント。SQL仕様では、末尾のアンダースコアを予約語として使用しないことが明示的に約束されていることに注意してください。だから、作ることができますtimestamptimestamp_。のようなよりわかりやすい名前がより良いでしょうrow_created_
バジルブルク2014年

前半はOPが要求したものではありませんが、後半は他の回答を参照していますが(それは正しい)、それでも誤解を招く可能性があります。これは答えとして受け入れられるべきではありません。
Eric Wang

1
型のPostgresドキュメントでそう言っています。Varcharには制約をチェックするための余分なCPUサイクルがありますが、TEXTでは発生しません。
ラーリー、2017年

3
単一のフィールドではありませんが、単一のフィールドを持つ便利なテーブルは見たことがありません。この制約は、フィールドの数によって悪化します。テーブル内のすべてのvarcharをテキストに変更したことを覚えており、15%の書き込みの改善を得ました。また、小さなパフォーマンスペナルティは「NO」のパフォーマンスペナルティではありません。
Rahly

104

レコードが変更されたときに挿入トリガーを変更する必要がある場合は、挿入トリガーと更新トリガーを作成する必要があります。この記事はそれをかなりうまく説明しています:

http://www.revsys.com/blog/2006/aug/04/automatically-updating-a-timestamp-column-in-postgresql/

CREATE OR REPLACE FUNCTION update_modified_column()   
RETURNS TRIGGER AS $$
BEGIN
    NEW.modified = now();
    RETURN NEW;   
END;
$$ language 'plpgsql';

次のようにトリガーを適用します。

CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON customer FOR EACH ROW EXECUTE PROCEDURE  update_modified_column();

2
これがIMOの最良の答えです(ただし、デフォルトでは挿入には十分です)。
2016年

2
ここで何が新しいですか?
Naveen


これは、最初のINSERTと後続のUPDATEで機能するより完全なソリューションです(データ監査に適しています)。確かに、OPは前者のみを要求します。
Pavel Lechev

5
@Naveenそれほど多くない、あなたと何が新しいのですか?
Underyx

57

タイムスタンプの更新、値が変更された場合のみ

EJのリンクに基づいて、このリンクからifステートメントを追加しますhttps://stackoverflow.com/a/3084254/1526023

CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
   IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
      NEW.modified = now(); 
      RETURN NEW;
   ELSE
      RETURN OLD;
   END IF;
END;
$$ language 'plpgsql';

9

'now()'をデフォルト値として使用すると、タイムスタンプが自動的に生成されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.