J'ai essayé de concevoir une base de données qui corresponde à un concept de projet et je me suis heurté à ce qui semble être une question très controversée. J'ai lu quelques articles et des réponses à Stack Overflow affirmant qu'il n'est jamais (ou presque jamais) de stocker une liste d'identifiants ou similaire dans un champ - toutes les données doivent être relationnelles, etc.
Le problème que je rencontre, cependant, est que j'essaie de faire un assignateur de tâches. Les gens vont créer des tâches, les attribuer à plusieurs personnes et les enregistrer dans la base de données.
Bien sûr, si je sauvegarde ces tâches individuellement dans "Personne", je devrai disposer de dizaines de colonnes "TaskID" factices et les gérer, car il peut y avoir 0 à 100 tâches attribuées à une personne, par exemple.
Là encore, si je sauvegarde les tâches dans un tableau "Tâches", il me faudra des douzaines de colonnes "PersonID" factices et les gérer, le même problème que précédemment.
Pour un problème comme celui-ci, est-il acceptable de sauvegarder une liste d'identifiants prenant une forme ou une autre ou ne pense-t-on pas d'une autre manière que cela est réalisable sans enfreindre les principes?
la source
VARCHAR ARRAY
) pour stocker une liste de balises. Ce n'est probablement pas la façon dont ils finiront par être stockés plus tard sur la ligne, mais les listes peuvent être extrêmement utiles pendant les étapes de prototypage, quand vous n'avez rien d'autre à signaler et que vous ne voulez pas construire le schéma de base de données complet avant de pouvoir le faire. faire autre chose.Réponses:
Le mot clé et le concept clé que vous devez étudier est la normalisation de la base de données .
Ce que vous feriez, plutôt que d'ajouter des informations sur les affectations aux tables de personnes ou de tâches, consiste à ajouter une nouvelle table avec ces informations d'attribution, avec des relations pertinentes.
Exemple, vous avez les tables suivantes:
Personnes:
Les tâches:
Vous créez ensuite une troisième table avec des affectations. Ce tableau modéliserait la relation entre les personnes et les tâches:
Nous aurions alors une contrainte de clé étrangère, telle que la base de données impose que les identifiants PersonId et TaskId doivent être des ID valides pour ces éléments étrangers. Pour la première rangée, nous pouvons voir
PersonId is 1
, donc Alfred , est assigné àTaskId 3
, Traire les vaches .Ce que vous devriez être capable de voir ici, c'est que vous pouvez avoir autant ou autant d'affectations que vous le souhaitez par tâche ou par personne. Dans cet exemple, aucune tâche n'est assignée à Ezekiel et Alfred est affecté à la tâche 2. Si vous avez une tâche avec 100 personnes, cela
SELECT PersonId from Assignments WHERE TaskId=<whatever>;
générera 100 lignes, avec différentes personnes affectées. Vous pouvezWHERE
sur le PersonId pour trouver toutes les tâches assignées à cette personne.Si vous souhaitez renvoyer des requêtes en remplaçant les ID par les noms et les tâches, vous devez apprendre à JOINDRE les tables.
la source
Vous posez deux questions ici.
Tout d’abord, vous demandez s’il est acceptable de stocker des listes sérialisées dans une colonne. Oui ça ira. Si votre projet l’appelle. Un exemple pourrait être les ingrédients de produit pour une page de catalogue, dans lesquels vous ne souhaitez pas suivre chaque ingrédient individuellement.
Malheureusement, votre deuxième question décrit un scénario dans lequel vous devriez opter pour une approche plus relationnelle. Vous aurez besoin de 3 tables. Un pour les personnes, un pour les tâches et un qui conserve la liste des tâches assignées à chaque personne. Ce dernier serait vertical, une ligne par personne / combinaison de tâches, avec des colonnes pour votre clé primaire, identifiant de tâche et identifiant de personne.
la source
Ce que vous décrivez est appelé relation "plusieurs à plusieurs", dans votre cas entre
Person
etTask
. Il est généralement implémenté à l'aide d'une troisième table, parfois appelée table "lien" ou "référence croisée". Par exemple:la source
task_id
premier, si vous exécutez des requêtes filtrées par tâche.Le seul moment où vous pouvez stocker plus d'un élément de données dans un seul champ est quand ce champ est que jamais utilisé comme une seule entité et jamais considérée comme étant composée de ces petits éléments. Un exemple pourrait être une image, stockée dans un champ BLOB. Il est composé de nombreux éléments plus petits (octets), mais ceux-ci ne signifient rien pour la base de données et ne peuvent être utilisés que dans leur ensemble (et attrayants pour un utilisateur final).
Etant donné qu'une "liste" est, par définition, composée d'éléments plus petits (éléments), ce n'est pas le cas ici et vous devez normaliser les données.
Non, vous aurez quelques lignes dans une table d'intersection (ou entité faible) entre une personne et une tâche. Les bases de données sont vraiment efficaces pour travailler avec beaucoup de lignes; En fait, ils sont vraiment nuls au travail avec beaucoup de colonnes [répétées].
Bel exemple clair donné par whatsisname.
la source
Il peut être légitime dans certains champs pré-calculés.
Si certaines de vos requêtes sont coûteuses et que vous décidez d'utiliser des champs précalculés mis à jour automatiquement à l'aide de déclencheurs de base de données, il peut être légitime de conserver les listes dans une colonne.
Par exemple, dans l'interface utilisateur, vous souhaitez afficher cette liste à l'aide de la vue en grille, où chaque ligne peut ouvrir tous les détails (avec les listes complètes) après un double-clic sur:
Vous maintenez la deuxième colonne à jour par déclencheur lorsque le client visite le nouvel article ou par tâche planifiée.
Vous pouvez rendre un tel champ disponible même pour la recherche (en tant que texte normal).
Dans de tels cas, la tenue de listes est légitime. Il suffit de considérer le cas où la longueur de champ maximale pourrait être dépassée.
De plus, si vous utilisez Microsoft Access, les champs à plusieurs valeurs proposés constituent un autre cas d'utilisation spécial. Ils traitent automatiquement vos listes dans un champ.
Mais vous pouvez toujours revenir à la forme normalisée standard indiquée dans d'autres réponses.
Résumé: Les formes normales de base de données sont un modèle théorique nécessaire pour comprendre les aspects importants de la modélisation des données. Mais bien entendu, la normalisation ne prend pas en compte les performances ni les autres coûts d’extraction des données. Cela sort du cadre de ce modèle théorique. Toutefois, la mise en œuvre pratique nécessite souvent de stocker des listes ou d’autres doublons pré-calculés (et contrôlés).
À la lumière de ce qui précède, dans la mise en œuvre pratique, préférerions-nous une requête reposant sur une forme normale parfaite et une durée de 20 secondes ou une requête équivalente reposant sur des valeurs précalculées qui prennent 0,08 s? Personne n'aime que leur logiciel soit accusé de lenteur.
la source
Étant donné deux tables; nous les appellerons Personne et Tâche, chacun avec son propre ID (PersonID, TaskID) ... L'idée de base est de créer une troisième table pour les lier. Nous appellerons cette table PersonToTask. Au minimum, il devrait avoir son propre identifiant, ainsi que les deux autres identifiants. Donc, quand il s'agit d'affecter quelqu'un à une tâche; vous n'aurez plus besoin de METTRE À JOUR la table Personne, il vous suffira d'insérer une nouvelle ligne dans la table PersonToTaskTable. Et la maintenance devient plus facile: le besoin de supprimer une tâche devient simplement un DELETE basé sur TaskID, plus aucune mise à jour de la table Person et son analyse associée
Que diriez-vous d'un simple rapport ou de tous ceux qui sont affectés à une tâche?
Vous pourriez bien sûr en faire beaucoup plus; un TimeReport peut être effectué si vous avez ajouté des champs DateTime pour TaskAssigned et TaskCompleted. Cela ne tient qu'à toi
la source
Cela peut fonctionner si vous avez des clés primaires lisibles par l'homme et souhaitez une liste de tâches sans avoir à gérer la nature verticale d'une structure de table. c'est à dire beaucoup plus facile à lire le premier tableau.
La question serait alors: si la liste de tâches devait être stockée ou générée à la demande, cela dépendrait en grande partie de critères tels que: combien de fois la liste est-elle nécessaire, quel est le nombre exact de lignes de données, comment les données seront-elles utilisées, etc. .. après quoi l'analyse des compromis en fonction de l'expérience utilisateur et du respect des exigences doit être effectuée.
Par exemple, comparez le temps nécessaire pour rappeler les 2 lignes par rapport à l’exécution d’une requête qui générerait les 2 lignes. Si cela prend beaucoup de temps et que l'utilisateur n'a pas besoin de la liste la plus récente (* attend moins de 1 modification par jour), elle peut être stockée.
Ou si l'utilisateur a besoin d'un historique des tâches qui lui sont assignées, il serait également judicieux que la liste soit stockée. Donc, cela dépend vraiment de ce que vous faites, ne dites jamais jamais.
la source
Vous prenez ce qui devrait être une autre table, vous la tournez de 90 degrés et vous la frayez dans une autre table.
C'est comme avoir une table de commandes où vous avez itemProdcode1, itemQuantity1, itemPrice1 ... itemProdcode37, itemQuantity37, itemPrice37. En plus d'être délicat à gérer par programmation, vous pouvez garantir que demain, quelqu'un voudra commander 38 articles.
Je ne le ferais qu'à votre façon si la "liste" n'est pas vraiment une liste, c'est-à-dire qu'elle se trouve dans son ensemble et que chaque élément de campagne individuel ne fait pas référence à une entité claire et indépendante. Dans ce cas, insérez simplement le tout dans un type de données suffisamment volumineux.
Donc, un ordre est une liste, un Bill of Materials est une liste (ou une liste de listes, ce qui serait encore plus un cauchemar à mettre en œuvre "de côté"). Mais une note / commentaire et un poème ne le sont pas.
la source
Si c'est "pas ok", il est assez mauvais que chaque site Wordpress ait une liste dans wp_usermeta avec wp_capabilities dans une rangée, une liste de licenciés_wp_pointers dans une rangée, et d'autres ...
En fait, dans des cas comme celui-ci, la vitesse pourrait être meilleure car vous voudrez presque toujours la liste . Mais Wordpress n'est pas connu pour être l'exemple parfait des meilleures pratiques.
la source