ER диаграма: от описание до схема
Накратко: ER диаграмата показва същностите, свойствата им и връзките между тях с кратността им, преди да станат таблици със CREATE TABLE.
Проблем
Тетрадката на читалището
Квартално читалище води заеманията в тетрадка. Библиотекарката ти описва какво иска от новата програма:
„Имаме около 2 000 книги, от някои по няколко бройки. Читателите се записват с име и имейл. Всеки може да вземе книга за три седмици. Искам да знам кои книги са навън, у кого са и кой закъснява. И да търся по автор.“
Преди първия CREATE TABLE трябва да е ясно какви таблици има, какво пазят и как се свързват. Иначе след месец ще преправяш схемата с пълна база.
Идеята
Същности и свойства
Минаваш през описанието и търсиш същностите: нещата, за които пазиш данни. Обикновено са съществителни.
- Читател: име, имейл, кога се е записал.
- Книга: заглавие, година.
- Автор: име.
- Екземпляр: една бройка от книгата, на определен рафт. „От някои по няколко бройки“ значи, че книгата и бройката са различни неща.
- Заемане: кой екземпляр, кой читател, кога е взет, до кога трябва да се върне, кога е върнат.
Всяка същност става таблица, а свойствата ѝ стават колони. Заемането е глагол, но има свои свойства (дати), затова също е таблица.
„Кои са навън“ и „кой закъснява“ не са колони. Това са въпроси, на които ще отговарят заявки.
Идеята
Връзки и кратност
После казваш как се свързват същностите и колко към колко. Картинката с това се казва ER диаграма (entity-relationship, „същност и връзка“). Най-разпространеният ѝ запис е crow's foot, „гарванов крак“, по знака за „много“, който прилича на птичи крак.
Всеки край на линията има два знака. Знакът до таблицата казва колко най-много, а другият колко най-малко. Така се пишат в десния край:
||точно един;o|нула или един;|{един или много;o{нула или много.{е „крачето“.
В левия край са огледални: ||, |o, }|, }o.
Ето библиотеката. Записът е на езика Mermaid, който GitHub и много редактори рисуват като картинка:
erDiagrammembers ||--o{ loans : "взема"copies ||--o{ loans : "се заема"books ||--|{ copies : "има"books ||--|{ book_authors : "е от"authors ||--o{ book_authors : "пише"Текстът след двоеточието е надписът на линията. Mermaid го иска, а за схемата не значи нищо.
members ||--o{ loans се чете така: един читател има нула или много заемания, а всяко заемане е на точно един читател. books ||--|{ copies: всяка книга има поне един екземпляр, а всеки екземпляр е от точно една книга.
Пробвай
Каква е връзката?
Идеята
От диаграмата към таблиците
Правилата са от предишния урок:
- 1:N: външен ключ от страната на „много“-то (
copies.book_id,loans.copy_id,loans.member_id). - M:N: таблица за връзка с първичен ключ от двете колони (
book_authors). - 1:1: външен ключ с
UNIQUE. В библиотеката няма такава.
members
- PK
idinteger nametext *emailtext *joined_attext *
authors
- PK
idinteger nametext *
books
- PK
idinteger titletext *yearinteger
book_authors
- PK
book_idinteger→ books - PK
author_idinteger→ authors
copies
- PK
idinteger - FK
book_idinteger *→ books shelftext *
loans
- PK
idinteger - FK
copy_idinteger *→ copies - FK
member_idinteger *→ members loaned_attext *due_attext *returned_attext
Полетата долу са с тази схема и с няколко книги и читатели. Кои екземпляри на „Под игото“ има и на кой рафт?
По-точно, за любопитните
returned_at е NULL, докато книгата е навън. Така една колона пази и „върната ли е“, и „кога“. Друг вариант е колона status, но тогава трябва да внимаваш двете да не си противоречат.
Диаграмите се рисуват и с инструменти като dbdiagram.io и draw.io, а повечето програми за бази (DBeaver, DataGrip, pgAdmin) правят ER диаграма от готова база. Нотацията е същата.
Виж го
Книга или екземпляр?
Изкушението е заемането да сочи направо към книгата. Пусни историята на „Под игото“:
Екземпляр 1 е бил у двама читатели един след друг, а екземпляр 2 е у Борислав сега. Ако заемането пазеше само „Под игото“, нямаше да знаеш кой от трите е навън, кой е върнат скъсан и колко са на рафта.
Затова в проектирането питаш: какво точно се случва в света? Читателят взема предмет от рафта, а не заглавие.
Пробвай
Кое е навън
Библиотекарката пита кои книги са навън в момента и у кого. Покажи заглавието, номера на екземпляра и читателя.
Решение
SELECT b.title, c.id AS copy, m.name
FROM loans l
JOIN copies c ON c.id = l.copy_id
JOIN books b ON b.id = c.book_id
JOIN members m ON m.id = l.member_id
WHERE l.returned_at IS NULL;Заемане без returned_at е още навън. Минаваш от loans към copies (кой екземпляр), оттам към books (заглавието) и към members (у кого). Пет екземпляра, от които и двата на „Добри поличби“.
Упражнение
Две задачи
1. Днес е 25 октомври 2026. Кой закъснява? Покажи читателя, заглавието и до кога трябваше да върне книгата.
Заеманията, които още не са върнати и срокът им е минал:
Решение
SELECT m.name, b.title, l.due_at
FROM loans l
JOIN copies c ON c.id = l.copy_id
JOIN books b ON b.id = c.book_id
JOIN members m ON m.id = l.member_id
WHERE l.returned_at IS NULL AND l.due_at < '2026-10-25';Две условия: книгата не е върната (returned_at IS NULL) и срокът е преди днешния ден (due_at < '2026-10-25'). Борислав и Галин. Анна трябва да върне своята утре, затова още не закъснява.
2. Търсенето по автор в каталога показва всяка книга с авторите ѝ. Покажи заглавието и името на автора.
Всички книги с авторите им:
Решение
SELECT b.title, a.name
FROM books b
JOIN book_authors ba ON ba.book_id = b.id
JOIN authors a ON a.id = ba.author_id;Минаваш през таблицата за връзка book_authors. Излизат 8 реда за 7 книги: „Добри поличби“ е от двама автори и излиза два пъти.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: CREATE TABLE: нова таблица · Ограничения: правила за данните · Външни ключове: връзки между таблиците · Видове връзки: 1:1, 1:N, M:N
- Продължава в: Нормализация · Пекарната, етап 1: базата и таблиците
- Задачи по темата: Проектиране на база