Come faccio ad aggiornare automaticamente un timestamp in PostgreSQL


132

Voglio che il codice sia in grado di aggiornare automaticamente il timestamp quando viene inserita una nuova riga come posso fare in MySQL usando CURRENT_TIMESTAMP.

Come sarò in grado di raggiungere questo obiettivo in PostgreSQL?

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

6
A proposito, il tipo di dati di timestampè definito dalle specifiche SQL come abbreviazione di TIMESTAMP WITHOUT TIME ZONE. Quasi certamente non è quello che vuoi, come spiegato dall'esperto di Postgres David E. Wheeler . L'altro tipo, TIMESTAMP WITH TIME ZONEè probabilmente quello che vuoi, usando qualsiasi informazione di offset del fuso orario passato per regolare la data-ora su UTC (ma in realtà non memorizza le informazioni di quel fuso orario nonostante il nome del tipo).
Basil Bourque,

3
Dopo averlo nuovamente imparato, ho scritto un post dettagliato sul blog su come registrare la data e l'ora sia della creazione che della modifica di una riga usando default, funzione e trigger. Include un esempio completo di codice SQL e PL / pgSQL per l'uso in Postgres.
Basil Bourque,

Risposte:


197

Per popolare la colonna durante l'inserimento, utilizzare un DEFAULTvalore:

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

Si noti che il valore per quella colonna può essere esplicitamente sovrascritto fornendo un valore INSERTnell'istruzione. Se vuoi impedirti di aver bisogno di un grilletto .

È inoltre necessario un trigger se è necessario aggiornare quella colonna ogni volta che la riga viene aggiornata (come indicato da EJ Brennan )

Si noti che l'utilizzo di parole riservate per i nomi di colonna non è in genere una buona idea. Dovresti trovare un nome diverso datimestamp


14
Ricorda che Postgres ha delle funzioni per dirti (1) l'ora del momento attuale, (2) l'ora di inizio della dichiarazione e (3) l'ora di inizio della transazione. L'esempio mostrato qui è l'inizio della transazione corrente. Potresti o meno volerlo al contrario delle altre due possibilità.
Basil Bourque,

6
Buon punto bonus per evitare nomi che si scontrano con parole riservate. Si noti che le specifiche SQL promettono esplicitamente di non utilizzare mai un carattere di sottolineatura finale come parola riservata. Così si può fare timestampin timestamp_. Ancora meglio sarebbe un nome più descrittivo come row_created_.
Basil Bourque,

La prima metà non è affatto quella che l'OP ha chiesto, anche se la seconda metà si riferiva ad un'altra risposta (che è corretta), ma è ancora fuorviante. Questo non dovrebbe essere accettato come risposta.
Eric Wang,

1
Lo afferma nella documentazione di Postgres dei tipi. Varchar ha cicli CPU aggiuntivi per verificare il vincolo, che non si verifica su TEXT.
Rahly,

3
non con un singolo campo, ma non ho mai visto una tabella utile con un singolo campo. Questo vincolo è aggravato dal numero di campi. Ricordo di aver cambiato tutti i varchar di una tabella in testo e ho ottenuto un miglioramento della scrittura del 15%. Inoltre, una penalità ridotta non è "NO".
Rahly,

104

Dovrai scrivere un trigger di inserimento e, eventualmente, un trigger di aggiornamento se desideri che cambi quando viene modificato il record. Questo articolo lo spiega abbastanza bene:

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

Applicare il grilletto in questo modo:

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

2
Questa è la risposta migliore, IMO (anche se un valore predefinito è abbastanza per l'inserimento).
kik,

2
Cosa c'è di NUOVO qui?
Naveen,


Questa è una soluzione più completa che funzionerebbe con gli INSERT iniziali e con tutti gli AGGIORNAMENTI successivi (ottimo per il controllo dei dati). Concesso, l'OP chiede solo il primo.
Pavel Lechev,

5
@Naveen non molto, cosa c'è di nuovo in te?
Underyx

57

Aggiornamento data / ora, solo se i valori sono cambiati

Basato sul link EJ e aggiungi un'istruzione if da questo link ( 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

L'uso di "now ()" come valore predefinito genera automaticamente la marca temporale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.