Imaginez un formulaire Web avec un ensemble de cases à cocher (tout ou partie d'entre eux peuvent être sélectionnés). J'ai choisi de les enregistrer dans une liste de valeurs séparées par des virgules stockées dans une colonne de la table de base de données.
Maintenant, je sais que la bonne solution serait de créer une deuxième table et de normaliser correctement la base de données. La mise en œuvre de la solution simple a été plus rapide et je voulais avoir une preuve de concept de cette application rapidement et sans avoir à y consacrer trop de temps.
Je pensais que le temps gagné et le code plus simple en valaient la peine dans ma situation, est-ce un choix de conception défendable, ou aurais-je dû le normaliser dès le départ?
Un peu plus de contexte, il s'agit d'une petite application interne qui remplace essentiellement un fichier Excel qui a été stocké sur un dossier partagé. Je demande aussi parce que je pense à nettoyer le programme et à le rendre plus maintenable. Il y a certaines choses là-dedans dont je ne suis pas entièrement satisfait, l'une d'elles est le sujet de cette question.
la source
Réponses:
En plus de violer la première forme normale en raison du groupe répétitif de valeurs stockées dans une seule colonne, les listes séparées par des virgules ont beaucoup d'autres problèmes plus pratiques:
idlist REGEXP '[[:<:]]2[[:>:]]'
*Pour résoudre ces problèmes, vous devez écrire des tonnes de code d'application, réinventant des fonctionnalités que le SGBDR fournit déjà beaucoup plus efficacement .
Les listes séparées par des virgules sont suffisamment erronées pour que j'en fasse le premier chapitre de mon livre: Antipatterns SQL: éviter les pièges de la programmation de base de données .
Il y a des moments où vous devez utiliser la dénormalisation, mais comme le mentionne @OMG Ponies , ce sont des cas d'exception. Toute «optimisation» non relationnelle profite à un type de requête au détriment d'autres utilisations des données, alors assurez-vous de savoir lesquelles de vos requêtes doivent être traitées de manière si spéciale qu'elles méritent une dénormalisation.
* MySQL 8.0 ne prend plus en charge cette syntaxe d'expression de limite de mot.
la source
"Une des raisons était la paresse".
Cela fait sonner l'alarme. La seule raison pour laquelle vous devriez faire quelque chose comme ça est que vous savez comment le faire "de la bonne façon", mais vous êtes arrivé à la conclusion qu'il y a une raison tangible de ne pas le faire de cette façon.
Cela dit: si les données que vous choisissez de stocker de cette manière sont des données que vous n'aurez jamais besoin d'interroger, alors il peut être judicieux de les stocker de la manière que vous avez choisie.
(Certains utilisateurs contesteraient la déclaration de mon paragraphe précédent, disant que "vous ne pouvez jamais savoir quelles exigences seront ajoutées à l'avenir". Ces utilisateurs sont soit mal avisés, soit déclarent une conviction religieuse. Parfois, il est avantageux de travailler selon les exigences que vous avoir devant vous.)
la source
Il y a de nombreuses questions sur le SO:
Un autre problème avec la liste séparée par des virgules est de s'assurer que les valeurs sont cohérentes - le stockage de texte signifie la possibilité de fautes de frappe ...
Ce sont tous des symptômes de données dénormalisées, et soulignez pourquoi vous devez toujours modéliser des données normalisées. La dénormalisation peut être une optimisation de requête, à appliquer lorsque le besoin se présente réellement .
la source
En général, tout peut être défendable s'il répond aux exigences de votre projet. Cela ne signifie pas que les gens seront d'accord ou voudront défendre votre décision ...
En général, le stockage des données de cette manière n'est pas optimal (par exemple, il est plus difficile d'effectuer des requêtes efficaces) et peut entraîner des problèmes de maintenance si vous modifiez les éléments de votre formulaire. Peut-être auriez-vous pu trouver un juste milieu et utiliser à la place un entier représentant un ensemble d'indicateurs de bits?
la source
Oui, je dirais que c'est vraiment si mauvais. C'est un choix défendable, mais cela ne le rend pas correct ou bon.
Il rompt la première forme normale.
Une deuxième critique est que le fait de mettre les résultats d'entrée bruts directement dans une base de données, sans aucune validation ou liaison du tout, vous laisse ouvert aux attaques par injection SQL.
Ce que vous appelez la paresse et le manque de connaissances SQL, c'est ce dont les néophytes sont faits. Je recommanderais de prendre le temps de le faire correctement et de le voir comme une occasion d'apprendre.
Ou laissez-le tel quel et apprenez la douloureuse leçon d'une attaque par injection SQL.
la source
Eh bien, j'utilise une liste séparée par des tabulations de paires clé / valeur dans une colonne NTEXT dans SQL Server depuis plus de 4 ans maintenant et cela fonctionne. Vous perdez la flexibilité de faire des requêtes mais d'un autre côté, si vous avez une bibliothèque qui persiste / dérive la paire clé-valeur, ce n'est pas une mauvaise idée.
la source
J'avais besoin d'une colonne à valeurs multiples, elle pourrait être implémentée comme un champ xml
Il peut être converti en virgule délimitée si nécessaire
interroger une liste XML dans le serveur SQL à l'aide de Xquery .
En étant un champ xml, certaines des préoccupations peuvent être résolues.
Avec CSV: impossible de garantir que chaque valeur correspond au bon type de données: aucun moyen d'empêcher 1,2,3, banane, 5
Avec XML: les valeurs d'une balise peuvent être forcées pour être du bon type
Avec CSV: impossible d'utiliser des contraintes de clé étrangère pour lier des valeurs à une table de recherche; aucun moyen de faire respecter l'intégrité référentielle.
Avec XML: toujours un problème
Avec CSV: impossible d'appliquer l'unicité: aucun moyen d'empêcher 1,2,3,3,3,5
Avec XML: toujours un problème
Avec CSV: impossible de supprimer une valeur de la liste sans récupérer la liste entière.
Avec XML: les éléments uniques peuvent être supprimés
Avec CSV: difficile de rechercher toutes les entités avec une valeur donnée dans la liste; vous devez utiliser un scan de table inefficace.
Avec XML: le champ xml peut être indexé
Avec CSV: difficile de compter les éléments de la liste, ou effectuez d'autres requêtes agrégées. **
Avec XML: pas particulièrement difficile
Avec CSV: difficile de joindre les valeurs à la table de recherche à laquelle elles font référence. **
Avec XML: pas particulièrement difficile
Avec CSV: difficile de récupérer la liste dans l'ordre trié.
Avec XML: pas particulièrement difficile
Avec CSV: le stockage d'entiers sous forme de chaînes prend environ deux fois plus d'espace que le stockage d'entiers binaires.
Avec XML: le stockage est encore pire qu'un csv
Avec CSV: Plus beaucoup de virgules.
Avec XML: les balises sont utilisées à la place des virgules
En bref, l'utilisation de XML permet de contourner certains des problèmes liés à la liste délimitée ET peut être converti en liste délimitée selon les besoins
la source
Oui, il est mauvais. Mon opinion est que si vous n'aimez pas utiliser les bases de données relationnelles, alors cherchez une alternative qui vous convient mieux, il existe de nombreux projets "NOSQL" intéressants avec des fonctionnalités vraiment avancées.
la source
Je prendrais probablement le juste milieu: faire de chaque champ du CSV une colonne distincte de la base de données, mais ne vous inquiétez pas beaucoup de la normalisation (du moins pour l'instant). À un moment donné, la normalisation peut devenir intéressante, mais avec toutes les données placées dans une seule colonne, vous n'retirez pratiquement aucun avantage de l'utilisation d'une base de données. Vous devez séparer les données en champs / colonnes logiques / tout ce que vous voulez les appeler avant de pouvoir les manipuler de manière significative.
la source
Si vous avez un nombre fixe de champs booléens, vous pouvez utiliser un
INT(1) NOT NULL
(ouBIT NOT NULL
s'il existe) ouCHAR (0)
(nullable) pour chacun. Vous pouvez également utiliser unSET
(j'oublie la syntaxe exacte).la source
INT(1)
prend 4 octets; le(1)
n'a pas de sens.