Peut CURRENT_TIMESTAMP
être utilisé comme un PRIMARY KEY
?
Y a-t-il une possibilité que deux ou plusieurs INSERTS différents obtiennent la même chose CURRENT_TIMESTAMP
?
Peut CURRENT_TIMESTAMP
être utilisé comme un PRIMARY KEY
?
Y a-t-il une possibilité que deux ou plusieurs INSERTS différents obtiennent la même chose CURRENT_TIMESTAMP
?
Réponses:
Selon la documentation , la précision des CURRENT_TIMESTAMP
microsecondes est. Ainsi, la probabilité d'une collision est faible, mais possible.
Imaginez maintenant un bogue qui se produit très rarement et provoque des erreurs de base de données. Est-il difficile de le déboguer? C'est un bug bien pire que celui qui est au moins déterministe.
Le contexte plus large: vous voulez probablement éviter ces petites nuances avec les séquences, ce qui est particulièrement gênant si vous êtes habitué à MySQL.
De plus, si vous utilisez des transactions (la plupart des frameworks Web, en particulier Java, le font!), Les horodatages seront les mêmes à l'intérieur d'une transaction! Une démonstration:
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)
À plus? Deux sélections, exactement le même résultat. Je ne tape pas si vite. ;-)
-
Si vous voulez facilement des identifiants, en évitant l'utilisation des séquences, générez une valeur de hachage à partir des vrais identifiants des enregistrements. Par exemple, si votre base de données contient des humains et que vous savez que leur date de naissance, le nom de jeune fille de leur mère et leur vrai nom les identifient de manière unique, utilisez un
md5(mother_name || '-' || given_name || '-' birthday);
comme id. À côté de cela, vous pouvez utiliser une CreationDate
colonne, après ce que vous indexez la table, mais ce n'est pas une clé (qui est l'id).
Ps En général, c'est une très bonne pratique de rendre votre base de données aussi déterministe que possible. C'est-à-dire que la même opération devrait créer exactement le même changement dans la base de données . Tout ID basé sur l'horodatage ne parvient pas à cette fonctionnalité importante. Et si vous voulez déboguer ou simuler quelque chose? Vous rejouez une opération et le même objet sera créé avec un identifiant différent ... ce n'est vraiment pas difficile à suivre, et cela épargne beaucoup d'heures de travail.
Ps2 Quiconque vérifiera votre code à l'avenir, n'aura pas la meilleure opinion des identifiants générés par l'horodatage, pour les raisons ci-dessus.
INSERT
plusieurs lignes, elles obtiennent toutes la même chose current_timestamp
. Et puis vous avez des déclencheurs ...
Pas vraiment parce qu'il est possible pour CURRENT_TIMESTAMP de fournir deux valeurs identiques pour deux INSERTs suivants (ou un INSERT unique avec plusieurs lignes).
Utilisez plutôt un UUID basé sur le temps: uuid_generate_v1mc () .
Strictement parlant: non . Parce que CURRENT_TIMESTAMP
c'est une fonction et qu'une ou plusieurs colonnes de table peuvent former une PRIMARY KEY
contrainte.
Si vous voulez créer une PRIMARY KEY
contrainte sur une colonne avec la valeur par défaut CURRENT_TIMESTAMP
, la réponse est: oui, vous le pouvez . Rien ne vous empêche de le faire, comme rien ne vous empêche de tirer des pommes de la tête de votre fils. La question n'aurait toujours pas de sens tant que vous n'en définiriez pas le but. Quels types de données les colonnes et les tables sont-elles censées contenir? Quelles règles essayez-vous de mettre en œuvre?
En règle générale, l'idée est liée à des erreurs de clé en double, car il CURRENT_TIMESTAMP
s'agit d'une STABLE
fonction renvoyant la même valeur pour la même transaction (l'heure de début de la transaction). Plusieurs INSERT dans la même transaction sont susceptibles de se heurter - comme d'autres réponses déjà illustrées. Le manuel:
Étant donné que ces fonctions renvoient l'heure de début de la transaction en cours, leurs valeurs ne changent pas pendant la transaction. Ceci est considéré comme une caractéristique: l'intention est de permettre à une seule transaction d'avoir une notion cohérente de l'heure «actuelle», de sorte que plusieurs modifications au sein d'une même transaction portent le même horodatage.
Les horodatages PostgreSQL sont implémentés sous forme d'entiers de 8 octets représentant jusqu'à 6 chiffres fractionnaires (résolution en microsecondes).
Si vous créez une table qui ne doit pas contenir plus d'une ligne par microseconde et que cette condition ne changera pas (quelque chose nommé sensor_reading_per_microsecond
), alors cela pourrait avoir du sens. Les lignes en double sont censées déclencher une erreur de violation de clé en double. C'est une exception exotique, cependant. Et le type de données timestamptz
(non timestamp
) serait probablement préférable. Voir:
Je préfère toujours utiliser une clé primaire série de substitution à la place. Et ajoutez une UNIQUE
contrainte sur la colonne d'horodatage. Moins de complications possibles, sans compter sur les détails de mise en œuvre du SGBDR.
sensor_reading_per_microsecond
peut entrer en collision si vous ne pouvez pas absolument garantir que la synchronisation de chaque lecture est parfaitement synchronisée par rapport à la précédente; une déviation inférieure à la microseconde (ce qui n'est souvent pas impossible) rompt le schéma. En général, j'éviterais tout à fait cela. (Attention, comme vous l'avez indiqué, dans un tel cas, la collision résultante peut être souhaitable!)