Так, це жахлива ідея.
Замість того, щоб їхати:
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 Antipatterns ( Karwin , 2010) присвячує цілу главу цьому антипатрійту (який він називає "Jaywalking"), сторінки 15-23. Також автор розмістив аналогічне запитання в SO . Основні моменти, які він зазначає (як застосовано до цього прикладу):
- Запит на всі угоди в певній категорії досить складний (найпростіший спосіб вирішити цю проблему - це регулярний вираз, але регулярний вираз - проблема сама по собі).
- Ви не можете забезпечити референтну цілісність без зовнішніх ключових відносин. Якщо ви видалите DealCategory nr. №26, тоді ви, у своєму коді заявки, повинні пройти кожну угоду, шукаючи посилання на категорію №26 та видалити їх. Це щось, з чим слід звертатися на рівні даних, і доводиться обробляти це у вашому додатку - дуже погана річ .
- Знову сукупні запити (
COUNT
і SUM
т. Д.) Знову різняться від "складних" до "майже неможливих". Запитайте своїх розробників, як вони отримають вам список усіх категорій з урахуванням кількості угод у цій категорії. При правильному дизайні це чотири рядки SQL.
- Оновлення стає набагато складніше (тобто у вас є угода, яка складається з п'яти категорій, але ви хочете видалити дві та додати ще три). Це три рядки SQL з належним дизайном.
- Врешті-решт ви зіткнетесь із
VARCHAR
обмеженнями довжини списку. Хоча якщо у вас є список, відокремлений комами, налічує понад 4000 символів, ймовірність аналізувати, що монстр все одно буде повільним, як пекло.
- Витягнення списку з бази даних, розділення його та повернення до бази даних для іншого запиту суттєво повільніше, ніж один запит.
TLDR: Це принципово недосконала конструкція, вона не буде масштабуватись, вона додає додаткових складностей навіть найпростішим запитам, і прямо поза коробкою вона уповільнює вашу програму.