Сущности, атрибуты и связи
Прежде чем создавать таблицы, предметную область описывают на языке сущностей и связей. Разберём базовый словарь ER-моделирования.
ER-модель (Entity-Relationship, «сущность-связь») — это способ описать структуру предметной области в терминах сущностей, их атрибутов и связей между ними, не привязываясь к конкретной СУБД. Предложена Питером Ченом в 1976 году.
Зачем нужна ER-модель
Реляционная схема (таблицы, ключи) — это уже технический артефакт. Но прежде чем её строить, нужно понять саму предметную область: что в магазине вообще есть и как это связано. Если сразу прыгнуть к таблицам, легко упустить связь или продублировать сущность. ER-модель — это промежуточный, человекопонятный язык между заказчиком и базой данных. На ней проще обсуждать: «у заказа есть клиент», «книгу написали авторы» — и лишь затем механически перевести это в таблицы (следующий урок).
Три уровня проектирования
Прежде чем нырять в детали, поместим ER-моделирование на карту проектирования. Принято выделять три уровня моделей. Концептуальная модель (наш случай) — высокоуровневое описание предметной области без оглядки на конкретную СУБД: сущности, связи, бизнес-правила. Логическая модель — перевод концептуальной в конкретную модель данных (для нас — реляционную): таблицы, столбцы, ключи, но ещё без физических деталей. Физическая модель — как это ляжет в конкретную СУБД: типы данных, индексы, разбиение. ER-диаграмма живёт на концептуальном уровне; следующий урок — переход к логической модели; физику мы затронем в разделе про хранение. Такое разделение перекликается с трёхуровневой архитектурой из первого раздела и преследует ту же цель: думать о смысле данных отдельно от их реализации, чтобы решения на одном уровне не диктовались деталями другого.
Сущности
Сущность (entity) — объект предметной области, о котором мы храним данные и который можно отличить от других. Тип сущности — это класс однотипных объектов (Клиент, Книга, Заказ), а экземпляр сущности — конкретный объект (клиент «Анна»). На ER-диаграмме тип сущности рисуют прямоугольником. В будущей реляционной схеме типу сущности обычно соответствует таблица, а экземпляру — строка.
Как отличить сущность от атрибута? Сущность — это то, о чём мы хотим хранить несколько фактов и что имеет самостоятельное существование. «Клиент» — сущность (у него есть имя, телефон, заказы). «Цвет» — скорее атрибут товара, а не отдельная сущность, если про цвет нам нечего больше сказать.
Как читать ER-диаграмму
Хотя в текстовом курсе мы не рисуем диаграммы, важно знать их условные обозначения, потому что вы встретите их везде. В классической нотации Чена прямоугольник — тип сущности, овал — атрибут, ромб — связь, а линии соединяют их. Двойные контуры означают «слабые» элементы (слабая сущность, идентифицирующая связь — об этом в третьем уроке). Кардинальность подписывают у линий: «1» и «N» либо специальными значками. Существует и более компактная нотация «вороньей лапки» (crow's foot), популярная в инструментах проектирования, где множественность изображается раздвоенным окончанием линии. Какую бы нотацию вы ни встретили, за значками стоят те же три понятия — сущность, атрибут, связь, — поэтому, освоив словарь, вы прочтёте любую диаграмму.
Атрибуты и их виды
Атрибут — свойство сущности. Атрибуты бывают разных видов, и различать их полезно, потому что на этапе перевода в таблицы они ведут себя по-разному.
- Простой (атомарный) — неделим:
age,cena. - Составной — состоит из частей:
address= (город, улица, дом). Его либо хранят целиком, либо разбивают на отдельные столбцы. - Многозначный — у одного экземпляра несколько значений: у клиента несколько телефонов. Многозначный атрибут нельзя положить в одну ячейку (нарушит 1NF) — его выносят в отдельную таблицу.
- Производный (вычислимый) — выводится из других:
ageизbirth_date. Его обычно не хранят, а вычисляют. - Ключевой — однозначно идентифицирует экземпляр (будущий первичный ключ).
Связи
Связь (relationship) — ассоциация между сущностями. «Клиент оформляет Заказ», «Автор пишет Книгу». На диаграмме связь традиционно рисуют ромбом. У связи может быть своя степень — число участвующих типов сущностей: бинарная (два типа, самый частый случай), тернарная (три) и так далее.
У связи бывают и собственные атрибуты. Классический пример — связь «Студент изучает Курс» с атрибутом ocenka: оценка принадлежит не студенту и не курсу по отдельности, а именно факту изучения. Такие атрибуты подсказывают, что связь при переводе в таблицы станет отдельной таблицей.
Сущность или атрибут: как решить
Граница между сущностью и атрибутом — одно из самых частых мест сомнений в проектировании, и стоит дать практический критерий. Спросите про кандидата три вещи. Есть ли у него собственные свойства, которые мы хотим хранить? Если «город» — это только название, он атрибут клиента; если про город мы храним регион, население, индекс — он тянет на сущность. Существует ли он независимо и переиспользуется? Если на «город» ссылаются многие клиенты и мы не хотим дублировать его данные — это сущность со своей таблицей. Бывает ли его несколько у одного владельца? Тогда это как минимум многозначный атрибут, а скорее отдельная сущность. Эти вопросы переводят интуицию в проверяемые критерии. Ошибиться в обе стороны легко: сделать сущностью то, что было простым атрибутом (лишние таблицы и соединения), или, наоборот, спрятать в атрибут то, у чего есть своя жизнь (избыточность и потеря данных).
Виды связей по кардинальности
Кардинальность описывает, сколько экземпляров одной сущности может быть связано с экземпляром другой. Три базовых типа:
| Тип | Обозначение | Пример |
| Один-к-одному | 1:1 | Сотрудник — его пропуск |
| Один-ко-многим | 1:N | Клиент — его заказы |
| Многие-ко-многим | M:N | Книга — авторы (у книги много авторов, у автора много книг) |
Кардинальность — ключевое решение проектирования. Перепутав 1:N и M:N, вы построите неверную схему. Спросите себя про обе стороны: «у одного клиента сколько заказов?» (много) и «у одного заказа сколько клиентов?» (один) — значит, связь 1:N.
Степень связи: бинарные, тернарные, рекурсивные
Большинство связей бинарны (соединяют два типа сущностей), но не все. Рекурсивная связь соединяет тип сущности с самим собой: «сотрудник руководит сотрудником», «деталь входит в состав детали». Такие связи естественны для иерархий и реализуются самоссылающимся внешним ключом, как мы видели в разделе про ключи. Тернарная связь соединяет сразу три сущности, когда факт по-настоящему трёхсторонний: «поставщик поставляет товар в магазин» — здесь ни одна пара не передаёт смысл без третьего участника. Тернарные связи коварны: их часто ошибочно разбивают на три бинарные, теряя информацию (из трёх отдельных связей «кто-что», «что-где», «кто-где» нельзя восстановить, какой именно поставщик привёз какой товар в какой магазин). Признак истинной тернарной связи — наличие атрибута, зависящего от всех трёх участников сразу (например, количество поставки). Такие связи при переводе становятся таблицей с тремя внешними ключами.
Класс принадлежности (обязательность)
Помимо «сколько», важно «обязательно ли». Класс принадлежности (участие в связи) бывает обязательным (total) или необязательным (partial). «Каждый заказ обязан принадлежать клиенту» — обязательное участие заказа. «Не у каждого клиента есть заказы» — необязательное участие клиента. Это влияет на то, разрешим ли мы NULL во внешнем ключе и нужны ли внешние соединения при выборках.
Пример: ER-описание интернет-магазина
Соберём словами небольшую ER-модель.
- Сущности: Клиент(id, имя, email, телефон), Заказ(номер, дата), Товар(артикул, название, цена).
- Связь «Клиент оформляет Заказ» — 1:N (у клиента много заказов, у заказа один клиент). Участие заказа обязательное.
- Связь «Заказ содержит Товар» — M:N (в заказе много товаров, товар в разных заказах). У связи есть атрибут
quantity(количество). - Телефон клиента — потенциально многозначный (несколько номеров), email — простой атрибут, адрес — составной.
Уже на этом уровне видны будущие решения: M:N-связь и многозначный телефон превратятся в отдельные таблицы. Но пока мы говорим о предметной области, а не о таблицах — и это правильно.
Типичные ошибки проектирования
- Сущность вместо атрибута и наоборот. Делать «Цвет» отдельной сущностью без причины — переусложнение; хранить несколько телефонов в одном атрибуте — потеря данных.
- Неверная кардинальность. Принять M:N за 1:N — и часть связей потеряется; всегда проверяйте обе стороны.
- Атрибут связи приписан сущности. Оценку за курс кладут в студента или в курс, хотя она принадлежит факту «студент изучает курс».
- Игнорирование обязательности. Не продумали участие — и в схеме оказываются заказы без клиента.
Итог
- ER-модель описывает предметную область сущностями, атрибутами и связями — до построения таблиц.
- Атрибуты бывают простыми, составными, многозначными, производными и ключевыми; вид влияет на будущую схему.
- Кардинальность (1:1, 1:N, M:N) и обязательность участия — ключевые решения проектирования.
- Атрибуты связи (например, оценка или количество) принадлежат самой связи, а не сущностям.