Да, это ужасная идея.
Вместо того, чтобы идти:
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
Теперь вам нужно идти:
SELECT Deal.ID, Deal.Name, DealCategories
FROM Deal
WHERE Deal.DealID = 1234
Затем вам нужно сделать что-то в коде приложения, чтобы разбить этот список запятых на отдельные числа, а затем запросить базу данных отдельно:
SELECT DealCategory.Name
FROM DealCategory
WHERE DealCategory.DealCategoryID IN (<<that list from before>>)
Этот дизайн антипаттерна проистекает либо из полного недопонимания реляционного моделирования (вам не нужно бояться таблиц. Таблицы - ваши друзья. Используйте их), либо из-за странного заблуждения о том, что быстрее взять список, разделенный запятыми, и разделить его. в коде приложения, чем добавить таблицу ссылок (это никогда не происходит). Третий вариант - они не уверены в себе и не достаточно компетентны в SQL, чтобы иметь возможность устанавливать внешние ключи, но в этом случае они не должны иметь ничего общего с дизайном реляционной модели.
Антипаттерны SQL (Karwin, 2010) посвящают этому антипаттерну целую главу (которую он называет «Jaywalking»), страницы 15-23. Кроме того, автор разместил на аналогичный вопрос в SO . Ключевые моменты, которые он отмечает (применительно к этому примеру):
- Запрашивать все сделки в определенной категории довольно сложно (самый простой способ решить эту проблему - это регулярное выражение, но регулярное выражение само по себе является проблемой).
- Вы не можете навязать ссылочную целостность без отношений внешнего ключа. Если вы удалите DealCategory Nr. # 26, вы затем, в своем коде приложения, должны пройти каждую сделку в поисках ссылок на категорию # 26 и удалить их. Это то, что должно быть обработано на уровне данных, и необходимость обрабатывать это в вашем приложении - очень плохая вещь .
- Совокупные запросы (
COUNT
и SUM
т. Д.), Опять же, варьируются от «сложных» до «почти невозможных». Спросите ваших разработчиков, как они могут получить список всех категорий с подсчетом количества сделок в этой категории. При правильном дизайне это четыре строки SQL.
- Обновления становятся намного сложнее (т.е. у вас есть сделка в пяти категориях, но вы хотите удалить две и добавить еще три). Это три строки SQL с правильным дизайном.
- В конце концов вы столкнетесь с
VARCHAR
ограничениями длины списка. Хотя если у вас есть разделенный запятыми список длиной более 4000 символов, есть вероятность, что в любом случае монстр будет работать очень медленно.
- Вытащить список из базы данных, разделить его, а затем вернуться к базе данных для другого запроса, по сути, медленнее, чем один запрос.
TLDR: это принципиально некорректный дизайн, он плохо масштабируется, он добавляет дополнительную сложность даже к самым простым запросам и сразу же из коробки замедляет работу вашего приложения.