Ai-je besoin d'ID dans ma base de données si les enregistrements peuvent être identifiés par la date?

17

J'écris ma première application pour Android et j'utiliserai la base de données SQLite, j'essaierai donc de limiter la taille autant que possible, mais je pense que la question s'applique en général à la conception de la base de données.

Je prévois de stocker des enregistrements contenant du texte et la date de création. L'application est une application autonome, c'est-à-dire qu'elle ne sera pas liée à Internet et qu'un seul utilisateur la mettra à jour, il n'y a donc aucune chance qu'il y ait plus d'une entrée avec une date donnée.

Ma table a-t-elle encore besoin d'une colonne ID? Dans l'affirmative, quels sont les avantages d'utiliser l'ID comme identifiant d'enregistrement par rapport à la date?

Nieszka
la source
SQLite créera toujours une colonne entière pour rowid si vous ne spécifiez pas de PK entier. Ne comptez donc pas sur l'absence d'une colonne "ID" pour économiser de l'espace.
Codisme
J'ajouterai que dans Android, certaines classes ont besoin de tables pour avoir une colonne _id pour fonctionner. Plus d'informations sur cette réponse SO .
bigstones
5
Si vous obtenez la date à partir du téléphone lui-même et que l'utilisateur se déplace vers un fuseau horaire antérieur (et que son téléphone met à jour l'heure automatiquement), il y a une légère chance que vous puissiez obtenir le même horodatage plus d'une fois.
Eugene

Réponses:

22

À mon humble avis, il vaut mieux éviter d'utiliser une colonne de date comme clé primaire.

J'ai travaillé sur des systèmes où un champ de date est utilisé comme clé primaire et l'écriture de requêtes pour retirer des sous-ensembles de données est un peu compliquée si vous travaillez avec des champs de date.

Quelques autres points que vous voudrez peut-être considérer:

Vous pourriez penser qu'un point dans le temps est unique, mais cela dépend plutôt de la granularité de la colonne de date. S'agit-il de minutes, secondes, millisecondes, etc. Pouvez-vous être absolument sûr que vous n'obtiendrez jamais de violation de clé primaire?

Enfin, si vous souhaitez migrer la base de données vers une autre plateforme, vous pouvez à nouveau rencontrer des problèmes où la granularité des données de date diffère entre les plateformes.

Vous devez bien sûr trouver un équilibre entre l'idéal et ce avec quoi vous devez travailler. Si l'espace est vraiment un sujet de préoccupation, l'utilisation de la colonne date pourrait être le moindre de deux maux. C'est une décision de conception que vous devrez prendre.

Éditer:

Je dois souligner que cela n'indique nullement qu'il s'agit d'une mauvaise décision de conception. Juste qu'il pourrait y avoir des problèmes avec les aspects pratiques du SGBDR en question.

Robbie Dee
la source
cela fait un moment que je n'ai pas écrit de requête SQLite, mais le filtrage par dates n'est-il pas identique au filtrage par entiers, à part la déclaration plus détaillée des valeurs de liaison?
DougM
C'est juste plus verbeux et sur certains SGBDR, vous obtenez ce problème où l'élément jour et mois est inversé si la base de données a été configurée au format américain.
Robbie Dee
Merci, ce sont toutes de bonnes réponses, mais votre expérience au travail a définitivement scellé l'affaire.
Nieszka
En tant que post-scriptum à ceci: Ce n'est qu'aujourd'hui que j'ai été confronté à un problème de support pour une table d'audit d'application où ils obtiennent une violation de clé primaire pour un numéro d'employé et une date / heure d'accès PK en raison d'un décalage horaire entre 2 appareils clients. ..
Robbie Dee
13

Non, vous n'avez pas strictement besoin d'une colonne ID définie dans votre schéma si vous pouvez garantir qu'il n'y aura jamais de date en double.

MAIS ...

... cela dit, vous pourriez aussi bien l'utiliser de toute façon. Le petit secret ici est que SQLite a déjà un ID unique à incrémentation automatique pour chaque table appelée ROWID. Si vous déclarez une colonne entière à incrémentation automatique dans votre table en tant que PK, SQLite ne créera pas de nouvelle colonne - elle aliasera simplement cette colonne ROWID préexistante.

Dans SQLite, chaque ligne de chaque table a un ROWID entier signé 64 bits. Le ROWID de chaque ligne est unique parmi toutes les lignes de la même table.

Vous pouvez accéder au ROWID d'une table SQLite en utilisant l'un des noms de colonne spéciaux ROWID, ROWID ou OID. Sauf si vous déclarez une colonne de table ordinaire pour utiliser l'un de ces noms spéciaux, l'utilisation de ce nom fera référence à la colonne déclarée et non au ROWID interne.

Si une table contient une colonne de type INTEGER PRIMARY KEY, cette colonne devient un alias pour le ROWID. Vous pouvez ensuite accéder au ROWID en utilisant l'un des quatre noms différents, les trois noms d'origine décrits ci-dessus ou le nom donné à la colonne INTEGER PRIMARY KEY. Tous ces noms sont des alias les uns pour les autres et fonctionnent aussi bien dans n'importe quel contexte.

http://www.sqlite.org/autoinc.html

Donc, vous n'économiserez pas d'espace en n'utilisant pas de colonne ID car vous en obtenez une par table, que vous le vouliez ou non!

GrandmasterB
la source
9

Utilisez un champ ID si l'une des conditions suivantes est vraie:

  1. Aucune clé naturelle n'existe (la date ne sera pas unique)
  2. Le champ de date changera souvent
  3. La date peut ne pas être connue au moment de l'insertion.
  4. Un identifiant multicolonne dépasse trois colonnes, ce qui rendrait les jointures trop verbeuses.

Lisez cette question: Existe - t-il une source canonique prenant en charge les «substituts de substitution»?

Éditer:

Puisque, à mon avis, il semble que rien de ce qui précède ne soit vrai, vous n'avez pas besoin d'utiliser le champ ID, mais vous pouvez en utiliser un si vous le souhaitez.

Tulains Córdova
la source
1
Les colonnes +1 d'ID sont une odeur de code de schéma, indiquant que vos données ne correspondent pas vraiment au modèle relationnel.
Ross Patterson
10
@ RossPatterson, je n'en suis pas si sûr. Je peux penser à un certain nombre de cas où aucune clé naturelle pourrait exister, mais les données peuvent toujours correspondre au modèle relationnel. Un seul cas qui me vient à l'esprit: le stockage d'informations sur des personnes vivantes. De nombreux pays ( pas tous! ) Attribuent des identifiants uniques à chaque citoyen, mais cela ne signifie pas que l'utilisation de cet identifiant est appropriée ou même possible (il peut ne pas être connu au moment de la création de l'enregistrement, peut ne pas être attribué ou son utilisation). peut être interdit, par exemple par les réglementations applicables). Est-ce à dire que les données ne correspondent pas au modèle relationnel? Je ne pense pas.
un CVn
Et il y a le petit fait drôle que là où il y a un identifiant unique, la police (etc.) utilise parfois des doublons pour ses faux identifiants. Et quand ce n'est pas intentionnel, une erreur d'écriture assurera de toute façon des doublons.
user470365
4
Qu'il soit intégré (à la Oracle) ou ajouté en tant que colonne de bonne foi, ils sont très utiles. En tant que personne qui a été des deux côtés de la clôture (DBA et développeur), il est beaucoup plus facile de dédupliquer une table avec un identifiant dont vous pouvez garantir qu'elle sera unique.
Robbie Dee
1
@RobbieDee Vous avez raison. C'est hors sujet.
Tulains Córdova
2

Gardez à l' esprit que vous pouvez également changer le sens de la colonne « date » de created_atla updated_atou tout autre changement dans ce sens, que je trouve être le cas très fréquent.

L'ajout d'une colonne d'identification dans certains cas vous donnera plus de flexibilité lorsque votre conception change.

wlk
la source
+1 en ajoutant date_created et date_modified aux tables est très utile pour suivre quand les lignes ont été créées et mises à jour. Cela vaut son pesant d'or lorsque l'on examine les problèmes de mise à jour du référentiel / entrepôt de données.
Robbie Dee