Wie aktualisiere ich automatisch einen Zeitstempel in PostgreSQL?


132

Ich möchte, dass der Code den Zeitstempel automatisch aktualisieren kann, wenn eine neue Zeile eingefügt wird, wie dies in MySQL mit CURRENT_TIMESTAMP möglich ist.

Wie kann ich dies in PostgreSQL erreichen?

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

6
Übrigens wird Ihr Datentyp von timestampdurch die SQL-Spezifikation als Abkürzung für definiert TIMESTAMP WITHOUT TIME ZONE. Das ist mit ziemlicher Sicherheit nicht das, was Sie wollen, wie der Postgres-Experte David E. Wheeler erklärt hat . Der andere Typ TIMESTAMP WITH TIME ZONEist wahrscheinlich das, was Sie möchten, indem Sie alle übergebenen Zeitzonenversatzinformationen verwenden, um die Datums- und Uhrzeit auf UTC anzupassen (aber diese Zeitzoneninformationen trotz des Typnamens nicht tatsächlich speichern).
Basil Bourque

3
Nachdem ich dies noch einmal gelernt hatte, schrieb ich einen ausführlichen Blog-Beitrag über das Protokollieren der Datums- und Uhrzeit der Erstellung und Änderung einer Zeile mit Standard, Funktion und Trigger. Enthält einen vollständigen SQL- und PL / pgSQL-Beispielcode zur Verwendung in Postgres.
Basil Bourque

Antworten:


196

Verwenden Sie einen DEFAULTWert , um die Spalte beim Einfügen zu füllen:

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

Beachten Sie, dass der Wert für diese Spalte explizit überschrieben werden kann, indem ein Wert in der INSERTAnweisung angegeben wird. Wenn Sie dies verhindern möchten, benötigen Sie einen Auslöser .

Sie benötigen auch einen Auslöser, wenn Sie diese Spalte bei jeder Aktualisierung der Zeile aktualisieren müssen (wie von EJ Brennan erwähnt ).

Beachten Sie, dass die Verwendung reservierter Wörter für Spaltennamen normalerweise keine gute Idee ist. Sie sollten einen anderen Namen als findentimestamp


14
Beachten Sie, dass Postgres über Funktionen verfügt , mit denen Sie (1) den Zeitpunkt des aktuellen Moments, (2) den Zeitpunkt des Beginns der Anweisung und (3) den Zeitpunkt des Starts der Transaktion angeben können. Das hier gezeigte Beispiel ist der Beginn der aktuellen Transaktion. Möglicherweise möchten Sie dies im Gegensatz zu den beiden anderen Möglichkeiten.
Basil Bourque

6
Guter Bonuspunkt, um Namen zu vermeiden, die mit reservierten Wörtern kollidieren. Beachten Sie, dass die SQL-Spezifikation ausdrücklich verspricht, niemals einen nachgestellten Unterstrich als reserviertes Wort zu verwenden. So können Sie machen timestampin timestamp_. Noch besser wäre ein aussagekräftigerer Name wie row_created_.
Basil Bourque

Die erste Hälfte ist überhaupt nicht das, was das OP gefragt hat, obwohl sich die zweite Hälfte auf eine andere Antwort bezog (was richtig ist), aber sie ist immer noch irreführend. Dies sollte nicht als Antwort akzeptiert werden.
Eric Wang

1
Sagt so in der Postgres-Dokumentation der Typen. Varchar verfügt über zusätzliche CPU-Zyklen, um die Einschränkung zu überprüfen, die bei TEXT nicht auftritt.
Rahly

3
nicht mit einem einzelnen Feld, aber ich habe noch nie eine nützliche Tabelle mit einem einzelnen Feld gesehen. Diese Einschränkung wird durch die Anzahl der Felder verstärkt. Ich erinnere mich, dass ich alle Varchars in einer Tabelle in Text geändert habe und eine 15% ige Verbesserung beim Schreiben erzielt habe. Eine kleine Leistungsstrafe ist auch keine "NEIN" -Leistungsstrafe.
Rahly

104

Sie müssen einen Einfügetrigger und möglicherweise einen Aktualisierungstrigger schreiben, wenn Sie möchten, dass er sich ändert, wenn der Datensatz geändert wird. Dieser Artikel erklärt es ganz nett:

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

Wenden Sie den Auslöser folgendermaßen an:

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

2
Dies ist die beste Antwort, IMO (obwohl eine Standardeinstellung zum Einfügen ausreicht).
Kik

2
Was ist hier NEU?
Naveen


Dies ist eine vollständigere Lösung, die sowohl mit anfänglichen INSERTs als auch mit nachfolgenden UPDATEs (gut für die Datenprüfung) funktioniert. Zugegeben, das OP fragt nur nach dem ersteren.
Pavel Lechev

5
@Naveen nicht viel, was ist neu bei dir?
Underyx

57

Aktualisieren des Zeitstempels nur, wenn sich die Werte geändert haben

Basierend auf dem Link von EJ und fügen Sie eine if-Anweisung von diesem Link hinzu ( 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

Wenn Sie 'now ()' als Standardwert verwenden, wird automatisch ein Zeitstempel generiert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.