Comment représenter un type énuméré dans une base de données relationnelle?

12

Je travaille sur le développement d'une base de données relationnelle qui suit les transactions qui se produisent sur un appareil sur lequel je travaille pour mon entreprise. Il existe différents types de transactions qui peuvent se produire sur l'appareil, nous avons donc un champ "trans_type" dans l'une de nos principales tables d'enregistrement. Mon groupe a décidé de faire du type de ce champ un entier et de le traiter comme un type énuméré. Mon intuition me dit qu'il serait préférable de faire de ce champ une chaîne afin que nos données de base de données soient plus lisibles et utilisables. Mes collègues semblent craindre que cela ne cause plus de problèmes que cela n'en vaut la peine. Les comparaisons de chaînes sont trop coûteuses et la possibilité de fautes de frappe est trop grande.

Donc, à votre avis, lorsqu'il s'agit d'un champ dans une base de données relationnelle qui est essentiellement une valeur énumérée, est-il une meilleure décision de conception de faire de ce champ un entier ou une chaîne? Ou y a-t-il une autre alternative que j'ai négligée?

Remarque: les types énumérés explicites ne sont pas pris en charge par la base de données que nous utilisons. Et le logiciel que nous développons qui interfacera avec cette base de données est écrit en C ++.

c.hughes
la source
Cela frappe-t-il quelqu'un d'autre depuis longtemps pour en faire une définition de type vérifiée dans la table de création? Quelque chose comme: CREATE TABLE hit (ip varchar (40), ip_class ENUM (0, "IPv4", 1, "IPv6")); Il devrait vous permettre de vérifier = <et> avec l'ordinal ou la chaîne (qui correspond à l'ordinal).
dlamblin

Réponses:

26

Les types énumérés doivent être une table distincte dans votre base de données qui ont un numéro d'identification et un nom de chaîne et toutes les autres colonnes que vous pourriez trouver utiles. Ensuite, chaque type existe sous forme de ligne dans ce tableau. Ensuite, dans votre table, vous enregistrez les transactions, le champ "trans_Type" doit être une clé étrangère à la clé de cette table de référence. Il s'agit d'une pratique standard de normalisation de base de données.

De cette façon, vous avez stocké la seule chaîne de nom officielle, utilisez des comparaisons de nombres pour les performances et assurez l'intégrité référentielle que chaque transaction a un type valide.

Ryathal
la source
1
Oui et si vous décidez de changer «O» en «Ouvrir», vous n'avez qu'à changer une ligne.
Daniel Kaplan
+1. une simple table int / string est la meilleure façon de représenter des énumérations dans un db relationnel.
mike30
Probablement, les visiteurs à venir qui sont à la recherche de solution Java trouver ce utile
Jauhien
2
Cette. Pour un crédit supplémentaire - si l'équipe de développement a défini les entiers dans une énumération Java / C # ou quelque chose de similaire, vous pouvez écrire un test qui vérifie si la définition de l'énumération de code a divergé de la table de recherche. Il y a toujours un danger que l'ajout d'un élément hors séquence puisse désynchroniser les choses et vous ne vous rendez pas compte jusqu'à ce qu'un enregistrement de données en direct semble incorrect.
Julia Hayward
4

Une pratique courante consiste à créer une trans_typestable, puis à faire référencer votre table principale avec une clé étrangère nommée trans_type_id. Cela garantit que vos enregistrements ne feront référence qu'à des types énumérés valides.

Exemple:

trans_type
----------
  id
  Nom

transactions
------------
  id
  trans_date
  détails
  trans_type_id (FK à trans_type.id)

Exemples de données:

trans_type

ID | NOM
----------
1 | SOUMETTRE
2 | ANNULER


transactions

ID | trans_date | trans_type_id
---------------------------------
1 | 2012-12-31 | 1
2 | 2013-01-09 | 2
FrustratedWithFormsDesigner
la source
3

Si les valeurs entrent dans la base de données sous forme d'entiers, stockez-les de cette façon. Il n'est pas nécessaire de surcharger la conversion en chaînes lors de l'écriture dans la base de données. Vous pouvez toujours vous associer à une table de recherche avec les valeurs chaîne / texte (plus normalisé).

Cela présente l'avantage supplémentaire de mettre à jour la valeur de chaîne dans un seul emplacement au lieu d'exécuter une sorte de routine de mise à jour. Au lieu de 1 = «Rouge», cela pourrait correspondre à «Vraiment rouge»

Ce n'est pas idéal pour rapporter les performances par rapport au simple besoin d'une table avec des valeurs de chaîne (dénormalisées). Un index sur ce champ rendrait les performances suffisamment bonnes.

La plupart des SGBDR permettront une puissance suffisante. Bien que votre idée de pouvoir «lire» le tableau dans son formulaire de données simple, rejoindre une table n'est pas très grave. Prenez simplement l'habitude d'utiliser une vue ou un objet similaire.

JeffO
la source
2

Je ne suis pas d'accord avec les autres réponses à cette question préconisant l'approche par table de recensement séparée.

Cependant, je suis certainement en faveur de ne pas répéter ce qui a déjà été dit, je vais donc simplement me référer à la réponse acceptée à (plus ou moins) la même question sur Stack Overflow: /programming//a/229919 / 114626

Eyal Roth
la source
+1 pour la réponse liée. Pour cette question, votre réponse liée semble être la bonne. Mais bien sûr, si le questionneur veut de la flexibilité dans les types énumérés, une table de référence serait bien meilleure.
Harke