Può CURRENT_TIMESTAMP
essere usato come PRIMARY KEY
?
Esiste la possibilità che due o più INSERTI diversi ottengano lo stesso CURRENT_TIMESTAMP
?
Può CURRENT_TIMESTAMP
essere usato come PRIMARY KEY
?
Esiste la possibilità che due o più INSERTI diversi ottengano lo stesso CURRENT_TIMESTAMP
?
Risposte:
Secondo la documentazione , la precisione CURRENT_TIMESTAMP
è di microsecondi. Pertanto, la probabilità di una collisione è bassa, ma possibile.
Ora immagina un bug che si verifica molto raramente e causa errori del database. Quanto è difficile eseguirne il debug? È un bug molto peggiore di uno che è almeno deterministico.
Il contesto più ampio: probabilmente vorrai evitare queste piccole sfumature con le sequenze, il che è particolarmente fastidioso se sei abituato a MySQL.
Inoltre, se si utilizzano transazioni (la maggior parte dei framework Web, in particolare quelli Java, lo fanno!), I timestamp saranno gli stessi all'interno di una transazione! Una dimostrazione:
postgres=# begin;
BEGIN
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
postgres=# select current_timestamp;
current_timestamp
-------------------------------
2018-08-06 02:41:42.472163+02
(1 Zeile)
Ci vediamo? Due selezioni, esattamente lo stesso risultato. Non scrivo così velocemente. ;-)
-
Se vuoi facilmente ID, evitando l'uso delle sequenze, quindi genera un valore hash dagli identificatori reali dei record. Ad esempio, se il tuo database ha umani e sai che la loro data di nascita, il nome da nubile della madre e il vero nome li identificano in modo univoco, quindi usa un
md5(mother_name || '-' || given_name || '-' birthday);
come id. Inoltre, puoi usare una CreationDate
colonna, dopo ciò che indicizzi la tabella, ma non è una chiave (che è l'id).
Ps In generale, è una buona pratica rendere il tuo DB così deterministico, per quanto possibile. Cioè la stessa operazione dovrebbe creare esattamente la stessa modifica nel DB . Qualsiasi ID basato su data e ora non riesce questa importante funzione. Cosa succede se si desidera eseguire il debug o simulare qualcosa? Ripeti un'operazione e lo stesso oggetto verrà creato con un ID diverso ... in realtà non è difficile da seguire e risparmia molte ore di lavoro.
Ps2 Chiunque controlla il tuo codice in futuro, non avrà la migliore opinione di vedere ID generati da timestamp, sui motivi sopra.
INSERT
di più righe, tutte ottengono la stessa cosa current_timestamp
. E poi hai i trigger ...
Non proprio perché è possibile che CURRENT_TIMESTAMP fornisca due valori identici per due INSERT successivi (o un singolo INSERT con più righe).
Utilizzare invece un UUID basato sul tempo: uuid_generate_v1mc () .
A rigor di termini: No. Perché CURRENT_TIMESTAMP
è una funzione e solo una o più colonne della tabella possono costituire un PRIMARY KEY
vincolo.
Se intendi creare un PRIMARY KEY
vincolo su una colonna con il valore predefinito CURRENT_TIMESTAMP
, la risposta è: Sì, puoi . Niente ti impedisce di farlo, come niente ti impedisce di sparare mele dalla testa di tuo figlio. La domanda non avrebbe ancora senso anche se non ne definisci lo scopo. Che tipo di dati dovrebbero contenere la colonna e la tabella? Quali regole stai cercando di implementare?
In genere, l'idea è destinata a incorrere in errori chiave duplicati poiché CURRENT_TIMESTAMP
è una STABLE
funzione che restituisce lo stesso valore per la stessa transazione (l'ora di inizio della transazione). Più INSERTI nella stessa transazione sono destinati a scontrarsi, come altre risposte già illustrate. Il manuale:
Poiché queste funzioni restituiscono l'ora di inizio della transazione corrente, i loro valori non cambiano durante la transazione. Questa è considerata una caratteristica: l'intenzione è quella di consentire a una singola transazione di avere una nozione coerente del tempo "corrente", in modo che più modifiche all'interno della stessa transazione rechino lo stesso timestamp.
I timestamp di Postgres sono implementati come numeri interi a 8 byte che rappresentano fino a 6 cifre frazionarie (risoluzione di microsecondi).
Se stai costruendo una tabella che dovrebbe contenere non più di una riga per microsecondo e che la condizione non cambierà (qualcosa chiamato sensor_reading_per_microsecond
), allora potrebbe avere senso. Le righe duplicate dovrebbero generare un errore di violazione della chiave duplicata. Questa è un'eccezione esotica, però. E il tipo di dati timestamptz
(non timestamp
) sarebbe probabilmente preferibile. Vedere:
Preferirei comunque utilizzare una chiave primaria seriale surrogata. E aggiungi un UNIQUE
vincolo nella colonna timestamp. Meno complicazioni possibili, non basandosi sui dettagli di implementazione di RDBMS.
sensor_reading_per_microsecond
può collidere se non può assolutamente garantire che i tempi di ogni lettura è perfettamente sincronizzato rispetto alla precedente; una deviazione al di sotto del microsecondo (che spesso non è impossibile) rompe lo schema. In generale, lo eviterei ancora del tutto. (Intendiamoci, come hai indicato, in tal caso, la collisione risultante potrebbe essere desiderabile!)