Ось готовий урок, створений у стилі CS50 та Девіда Малана.
🎓 Урок: Звʼязки в базах даних: One-to-One (Один-до-Одного)
1. 🔥 Вступ: проблема та мотивація
Привіт, друзі! Радий бачити вас. Давайте одразу до справи.
Уявіть, що ви будуєте систему для великого міжнародного аеропорту. У вас є база даних пасажирів. Ви зберігаєте їхні імена, номери телефонів, улюблене місце біля вікна... І тут постає питання безпеки. Вам потрібно зберігати паспортні дані.
Скажіть мені, чи розумно зберігати серію паспорта, скан сторінки, дату видачі та біометричні дані в тій самій таблиці, де лежить ім'я користувача та його статус "онлайн"?
(Пауза для роздумів)
Звучить як погана ідея, правда? Чому? 1. Безпека: Якщо хтось зламає таблицю, щоб подивитися, хто зараз онлайн, він вкраде і паспорти. 2. Швидкість: Таблиця з користувачами стає величезною і "важкою" через купу зайвих даних, які потрібні раз на рік.
Але ж у кожного пасажира є тільки один дійсний закордонний паспорт (у контексті нашої системи), і цей конкретний паспорт належить тільки одній людині.
Ось тут на сцену виходить зв'язок One-to-One (Один-до-Одного). Це як ваш відбиток пальця: він є тільки у вас, а ви є тільки у нього. Без цього інструменту ваші бази даних перетворяться на повільних, небезпечних монстрів.
2. 🧠 Теоретична база (без сухої академічності)
Давайте заглянемо під капот. Що це таке технічно?
One-to-One (1:1) — це тип зв'язку між двома таблицями, де: * Один рядок у Таблиці А пов'язаний максимум з одним рядком у Таблиці Б. * І навпаки: рядок у Таблиці Б пов'язаний максимум з одним рядком у Таблиці А.
Як це працює?
Ви пам'ятаєте, що таке Primary Key (ID) і Foreign Key (посилання на ID іншої таблиці)?
Щоб зробити зв'язок "Один-до-Одного", ми беремо Foreign Key і робимо його УНІКАЛЬНИМ (UNIQUE).
Запам'ятайте головне: У звичайному зв'язку (One-to-Many) багато людей можуть жити в одному місті. У зв'язку One-to-One ми ставимо жорстке обмеження: "Одне місце — одна людина". Це як стілець у кінотеатрі. Якщо я сів — ви вже не сядете.
Навіщо це робити (три кити 1:1):
1. Розділення даних: Виносимо рідко використовувані або "важкі" дані в окрему таблицю.
2. Безпека: Чутливі дані (паролі, паспорти) лежать окремо, доступ до них обмежений.
3. Логіка: Сутності різні, хоч і пов'язані (наприклад, Автомобіль і Техпаспорт).
3. 🧪 Приклади (від простого до реального)
Приклад 1: Мінімум коду
У нас є таблиця Users (Користувачі) і Passports (Паспорти).
Як би ви це реалізували? (Студент думає: "Мабуть, додам ID користувача в паспорт?")
Саме так! Дивимось SQL (спрощено):
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50)
);
CREATE TABLE passports (
id INT PRIMARY KEY,
passport_number VARCHAR(20),
user_id INT UNIQUE, -- Оце і є магія! Слово UNIQUE робить зв'язок 1:1
FOREIGN KEY (user_id) REFERENCES users(id)
);
Якщо я спробую додати другий паспорт з тим самим user_id, база даних скаже мені: "Ей, стоп! Цей користувач вже має паспорт. Помилка!".
Приклад 2: Реальний світ (Профілі на сайті)
Уявіть Facebook. Є основна таблиця users (логін, пароль, email) — це потрібно при кожному вході.
А є user_profiles (біографія, посилання на школу, улюблена цитата, знак зодіаку). Ці дані не потрібні серверу, коли ви просто логінитесь.
Ми розділяємо їх.
* users: легка таблиця, працює миттєво.
* user_profiles: важка таблиця, завантажується тільки коли ви заходите на сторінку профілю.
Питання: Що буде, якщо ми видалимо користувача з таблиці users?
Відповідь: Його user_profile теж має зникнути (або залишитися сиротою, залежно від налаштувань ON DELETE CASCADE), бо профіль без власника — це сміття.
4. 🛠 Практична частина
Час забруднити руки кодом (або псевдокодом). Виконуйте завдання по черзі:
Завдання 1: "Капітан"
Створіть структуру для космічного корабля.
У нас є таблиця Starship та таблиця Captain.
Правило: У корабля лише один капітан, капітан керує лише одним кораблем.
Напишіть (або уявіть), де буде знаходитись Foreign Key і який атрибут він мусить мати.
Завдання 2: "Порушник"
У вас вже є дані:
Captain Jack (id: 1) керує Black Pearl.
Спробуйте призначити Captain Jack (id: 1) ще й на корабель Flying Dutchman.
Опишіть, яку помилку поверне база даних.
Завдання 3: "Оптимізація"
Ви розробляєте інтернет-магазин. У вас є таблиця Products. Опис товару (description) займає дуже багато тексту (кілобайти!). Але список товарів на головній сторінці має вантажитись миттєво.
Як ви використаєте One-to-One, щоб прискорити завантаження каталогу?
Завдання 4: Міні-кейс "Таємниці"
У вас є співробітники (Employees). Всі бачать їх імена та посади. Але тільки бухгалтер бачить їхню зарплату (Salary).
Спроєктуйте схему з двох таблиць так, щоб ми могли надати права доступу на таблицю зарплат тільки бухгалтеру.
Завдання 5: А що, якщо...
А що, якщо user_id у другій таблиці НЕ буде унікальним (UNIQUE)?
На який тип зв'язку це перетвориться? (Підказка: один користувач зможе мати купу паспортів).
5. 💡 Мислення як у розробника
Послухайте уважно. Новачки часто роблять одну з двох помилок:
- Помилка "Все в одну купу": Створюють таблицю на 150 колонок. Це жах для підтримки. Не бійтеся розбивати сутності.
- Помилка "Надмірне дроблення": Створюють зв'язок One-to-One там, де він не потрібен. Наприклад, виносити
emailв окрему таблицю відuser— це маразм. Email потрібен завжди.
Як думає профі:
"Чи є ці дані невід'ємною частиною сутності, яка потрібна в 99% запитів? Якщо так — лишаємо в головній таблиці. Якщо це приватні дані, важкі дані або необов'язкові дані (які є у 10% юзерів) — виносимо в One-to-One."
Порада: Використовуйте One-to-One, коли хочете зробити код чистішим, а базу — безпечнішою. Це інструмент "гігієни" даних.
6. 🧩 Підсумок
Отже, що ми маємо в сухому залишку?
- One-to-One — це сувора моногамія у світі баз даних.
- Технічно це реалізується через
Foreign Key+UNIQUE. - Ми використовуємо це для безпеки, оптимізації та логічного розділення.
Тепер ви вмієте: проєктувати системи, де дані користувачів захищені, а додатки працюють швидко. Ви не просто "зберігаєте дані", ви їх архітектурите!
Наступного разу ми подивимось на ситуацію, коли одному користувачеві стає замало одного запису. Що, якщо він хоче запостити багато фотографій? Готуйтеся, ми йдемо до One-to-Many!
Це був CS50. Побачимось! 👋