Oui, c'est une terrible idée.
Au lieu d'aller:
SELECT Deal.Name, DealCategory.Name
FROM Deal
INNER JOIN
DealCategories ON Deal.DealID = DealCategories.DealID
INNER JOIN
DealCategory ON DealCategories.DealCategoryID = DealCategory.DealCategoryID
WHERE Deal.DealID = 1234
Vous devez maintenant aller:
SELECT Deal.ID, Deal.Name, DealCategories
FROM Deal
WHERE Deal.DealID = 1234
Ensuite, vous devez faire des choses dans votre code d'application pour diviser cette liste de virgules en nombres individuels, puis interroger la base de données séparément:
SELECT DealCategory.Name
FROM DealCategory
WHERE DealCategory.DealCategoryID IN (<<that list from before>>)
Ce motif de conception découle soit d'une incompréhension complète de la modélisation relationnelle (vous n'avez pas à avoir peur des tableaux. Les tableaux sont vos amis. Utilisez-les), soit d'une croyance bizarrement erronée qu'il est plus rapide de prendre une liste séparée par des virgules et de la diviser dans le code d'application que pour ajouter une table de liens (ce n'est jamais le cas ). La troisième option est qu'ils ne sont pas suffisamment confiants / compétents avec SQL pour pouvoir configurer des clés étrangères, mais si c'est le cas, ils ne devraient rien avoir à voir avec la conception d'un modèle relationnel.
SQL Antipatterns (Karwin, 2010) consacre un chapitre entier à cet antipattern (qu'il appelle «Jaywalking»), pages 15-23. En outre, l'auteur a posté une question similaire sur SO . Les points clés qu'il note (appliqués à cet exemple) sont:
- La recherche de toutes les offres dans une catégorie spécifique est plutôt compliquée (le moyen le plus simple de résoudre ce problème est une expression régulière, mais une expression régulière est un problème en soi).
- Vous ne pouvez pas appliquer l'intégrité référentielle sans relations de clés étrangères. Si vous supprimez DealCategory nr. # 26, vous devez ensuite, dans votre code d'application, parcourir chaque transaction à la recherche de références à la catégorie # 26 et les supprimer. C'est quelque chose qui devrait être géré au niveau de la couche de données, et devoir le gérer dans votre application est une très mauvaise chose .
- Les requêtes agrégées (
COUNT
, SUM
etc.), là encore, varient de «compliquées» à «presque impossibles». Demandez à vos développeurs comment ils vous obtiendraient une liste de toutes les catégories avec un décompte du nombre d'offres dans cette catégorie. Avec une conception appropriée, cela représente quatre lignes de SQL.
- Les mises à jour deviennent beaucoup plus difficiles (c'est-à-dire que vous avez un accord dans cinq catégories, mais que vous souhaitez en supprimer deux et en ajouter trois autres). C'est trois lignes de SQL avec une conception appropriée.
- Finalement, vous rencontrerez des
VARCHAR
limitations de longueur de liste. Bien que si vous avez une liste séparée par des virgules de plus de 4000 caractères, il est probable que le monstre sera lent comme l'enfer de toute façon.
- Extraire une liste de la base de données, la diviser, puis revenir à la base de données pour une autre requête est intrinsèquement plus lent qu'une requête.
TLDR: C'est une conception fondamentalement imparfaite, elle n'évolue pas bien, elle introduit une complexité supplémentaire, même pour les requêtes les plus simples, et dès le départ, elle ralentit votre application.