Ключи в БД
Ключи в БД — столбцы или группы столбцов для идентификации строк и связывания таблиц. Иерархия: суперключ (любая уникальная комбинация столбцов) → потенциальный ключ (минимальный суперключ, уникальный, not null) → первичный ключ (выбранный потенциальный ключ, главный идентификатор таблицы). Альтернативный ключ — потенциальный ключ, не выбранный как первичный. Внешний ключ — ссылается на первичный ключ другой таблицы, обеспечивает ссылочную целостность. Составной ключ — из нескольких столбцов (для таблиц «многие-ко-многим»). Свойства первичного ключа: уникальность, not null, стабильность, один на таблицу. Искусственный ключ (id) предпочтительнее естественного (паспорт, email) — не меняется. Примеры, обозначения (PK, FK, AK), типичные ошибки (отсутствие PK, внешний ключ не объявлен, путаница PK и FK).
Введение: Как отличить одного человека от другого
Представьте, что вы пришли в компанию, где работает 1000 человек. Как отличить Ивана Петрова от другого Ивана Петрова? По паспорту. По табельному номеру. По отпечатку пальца.
В базе данных та же проблема. В таблице могут быть сотни тысяч строк. Нужен способ уникально идентифицировать (опознать) каждую строку. И способ связывать строки из разных таблиц.
Для этого придумали ключи.
Ключ в базе данных – это столбец (или группа столбцов), который используется для идентификации строк или для установления связей между таблицами.
Суперключ (Superkey)
Суперключ – это комбинация столбцов (один столбец или несколько), которая уникально идентифицирует каждую строку в таблице. Другими словами, не может быть двух строк с одинаковым набором значений этих столбцов.
Это самое широкое понятие. Любой ключ – это суперключ. Но не любой суперключ - это “хороший” ключ.
Простыми словами: Суперключ – это “у меня есть способ отличить одного человека от другого. Я могу использовать имя, фамилию, дату рождения и город. Или только паспорт. Или только номер телефона. Или вообще все данные сразу”.
Пример:
Рассмотрим таблицу “Студенты”:
| FirstName | LastName | Year | Phone |
|---|---|---|---|
| Иван | Петров | 2000 | 79001234567 |
| Петр | Иванов | 2001 | 79007654321 |
| Иван | Петров | 2000 | 79009999999 |
Какие комбинации столбцов являются суперключами?
{Phone}- да, телефон уникален для каждого студента.{FirstName, LastName, Year, Phone}- да, это вообще все столбцы.{FirstName, Phone}- да, телефон уже все решает.{LastName, Phone}- да.{Year, Phone}- да.{FirstName, LastName, Year}- НЕТ. Видите двух Иванов Петровых 2000 года рождения? Они неразличимы без телефона.
Важный вывод: Суперключ может быть “жирным” (содержать лишние столбцы). Например, {FirstName, LastName, Year, Phone} – это суперключ, но столбцы FirstName, LastName, Year там лишние, потому что Phone уже все делает.
Потенциальный ключ (Candidate Key)
Потенциальный ключ (Candidate Key) – это минимальный суперключ. Он удовлетворяет трем условиям:
- Уникальность: значения уникальны для каждой строки.
- Минимальность (неприводимость): нельзя убрать ни один столбец из этого набора, не потеряв уникальность.
- Не null: столбцы не могут быть пустыми (NOT NULL).
Потенциальный ключ – это “кандидат” на то, чтобы стать первичным ключом.
Простыми словами: Потенциальный ключ - это “самый экономный способ отличить одного человека от другого”. Никаких лишних столбцов. Только то, что реально нужно для уникальности.
Пример:
Из всех суперключей, которые мы нашли, вычеркиваем те, которые не минимальны.
| Суперключ | Минимальный? | Почему |
|---|---|---|
{FirstName, LastName, Year, Phone} | Нет | Можно убрать FirstName, LastName, Year - останется {Phone} |
{FirstName, Year, Phone} | Нет | Можно убрать FirstName, Year - останется {Phone} |
{LastName, Year, Phone} | Нет | Можно убрать LastName, Year - останется {Phone} |
{FirstName, Phone} | Нет | Можно убрать FirstName - останется {Phone} |
{LastName, Phone} | Нет | Можно убрать LastName - останется {Phone} |
{Year, Phone} | Нет | Можно убрать Year - останется {Phone} |
{Phone} | Да | Нельзя убрать ни одного столбца (он один). |
Потенциальный ключ: {Phone}.
Но есть нюанс. А если студент может не иметь телефона? Тогда Phone может быть NULL. А потенциальный ключ не может содержать NULL. В этом случае у таблицы может не быть естественного потенциального ключа.
Что тогда? Тогда добавляют искусственный столбец специально для идентификации. Например, student_id.
Первичный ключ (Primary Key)
Первичный ключ (Primary Key) – это потенциальный ключ, который выбран для уникальной идентификации строк в таблице. Это “главный” способ отличить одну строку от другой.
Свойства первичного ключа
| Свойство | Что означает |
|---|---|
| Уникальность | Не может быть двух строк с одинаковым значением первичного ключа |
| Не NULL | Первичный ключ всегда должен иметь значение |
| Стабильность | Не должен меняться (или меняется крайне редко) |
| Один на таблицу | У таблицы может быть только один первичный ключ |
Что может быть первичным ключом
Естественный ключ (Natural Key): уже существующее уникальное поле.
Примеры:
- Номер паспорта (уникальный, не меняется)
- ИНН
- Номер заказа (внутри компании)
Искусственный ключ (Surrogate Key): специально созданное поле, которого не было в реальном мире.
Примеры:
id- автоинкрементирующееся целое числоUUID- глобально уникальный идентификатор
Почему искусственный ключ часто лучше
| Проблема естественного ключа | Решение искусственным ключом |
|---|---|
| Номер паспорта может измениться (при замене паспорта) | id никогда не меняется |
| ИНН есть не у всех (иностранцы, дети) | id есть у всех |
| Номер паспорта может быть введен с ошибкой | id генерируется системой |
| Ссылаться на длинный текст неудобно | Ссылаться на число удобно |
Рекомендация для аналитика: В 90% случаев используйте искусственный первичный ключ id. Это стандарт.
Пример
Таблица “Пользователи”:
| user_id (PK) | phone | name | |
|---|---|---|---|
| 1 | ivan@mail.ru | 79001234567 | Иван |
| 2 | petr@mail.ru | 79007654321 | Петр |
user_id – первичный ключ. Искусственный, никогда не меняется, всегда уникален.
Альтернативный ключ (Alternate Key)
Если у таблицы есть несколько потенциальных ключей, и вы выбрали один из них в качестве первичного, то остальные потенциальные ключи называются альтернативными ключами (Alternate Key).
Пример:
Таблица “Пользователи”:
| user_id (PK) | phone | name | |
|---|---|---|---|
| 1 | ivan@mail.ru | 79001234567 | Иван |
| 2 | petr@mail.ru | 79007654321 | Петр |
user_id- первичный ключ (искусственный).email- альтернативный ключ (уникальный, не NULL).phone- альтернативный ключ (уникальный, не NULL).
Зачем нужны альтернативные ключи
- Чтобы запретить дублирование. База данных не даст создать двух пользователей с одинаковым email.
- Чтобы быстро искать. Индекс на альтернативном ключе ускорит поиск по email.
- Чтобы входить в систему. Пользователь может входить и по email, и по телефону – оба поля уникальны.
Внешний ключ (Foreign Key)
Внешний ключ (Foreign Key) – это столбец (или группа столбцов) в одной таблице, который ссылается на первичный ключ другой таблицы. Внешний ключ устанавливает связь между таблицами.
Простыми словами: Внешний ключ – это “я знаю, что этот заказ принадлежит клиенту с id=5”. В таблице заказов хранится client_id, а этот client_id ссылается на запись в таблице клиентов.
Пример:
Таблица “Клиенты” (parent - родительская):
| client_id (PK) | name | phone |
|---|---|---|
| 1 | Иван Петров | 79001234567 |
| 2 | Мария Сидорова | 79007654321 |
Таблица “Заказы” (child - дочерняя):
| order_id (PK) | client_id (FK) | order_date | total |
|---|---|---|---|
| 101 | 1 | 2024-01-15 | 2500 |
| 102 | 1 | 2024-02-20 | 1800 |
| 103 | 2 | 2024-02-25 | 5000 |
client_id в таблице “Заказы” - это внешний ключ. Он ссылается на client_id в таблице “Клиенты”.
Что дает внешний ключ
- Связь: Мы знаем, что заказ 101 сделал клиент 1 (Иван Петров).
- Ссылочная целостность: СУБД не даст создать заказ с
client_id = 999, если клиента с таким id не существует. - Каскадные операции: Можно настроить, чтобы при удалении клиента удалялись и его заказы (CASCADE DELETE).
Обозначения
| Обозначение | Что означает |
|---|---|
| PK | Primary Key - первичный ключ |
| FK | Foreign Key - внешний ключ |
Составной ключ (Composite Key)
Составной ключ – это ключ, который состоит из двух или более столбцов. Может быть как первичным, так и внешним.
Когда нужен составной ключ
Чаще всего в таблицах для связи “многие-ко-многим”.
Пример: Таблица “Заказы_Товары” (связывает заказы и товары).
| order_id (FK) | product_id (FK) | quantity |
|---|---|---|
| 101 | 1 | 2 |
| 101 | 2 | 1 |
| 102 | 1 | 5 |
Здесь составной первичный ключ: (order_id, product_id). Пара “заказ-товар” уникальна. Один и тот же товар не может быть дважды в одном заказе.
Важное правило для составных ключей
Вторая нормальная форма (2NF) требует, чтобы все неключевые поля зависели от ВСЕГО составного ключа, а не от его части. В примере выше поле quantity зависит от всей пары (order_id, product_id) – это правильно.
Все типы ключей в одной таблице
Таблица “Сотрудники”:
| employee_id (PK) | passport_number (AK) | phone (AK) | department_id (FK) | name |
|---|---|---|---|---|
| 1 | 4015 123456 | 79001234567 | 10 | Иван Петров |
| 2 | 4015 654321 | 79007654321 | 20 | Мария Сидорова |
Разберем каждый ключ:
| Ключ | Тип | Почему |
|---|---|---|
employee_id | Первичный ключ (PK) | Искусственный, уникальный, не NULL, выбран для идентификации |
passport_number | Альтернативный ключ (AK) | Потенциальный ключ, но не выбран как первичный |
phone | Альтернативный ключ (AK) | Потенциальный ключ, но не выбран как первичный |
department_id | Внешний ключ (FK) | Ссылается на таблицу “Отделы” |
Какие еще есть ключи (не в таблице):
- Суперключи:
{employee_id},{passport_number},{phone},{employee_id, name},{passport_number, name}и так далее – любые комбинации, включающие уникальный столбец. - Потенциальные ключи:
{employee_id},{passport_number},{phone}– минимальные суперключи.
Таблица сравнения ключей
| Тип ключа | Что делает | Минимальный? | Может быть NULL? | Может быть несколько в таблице? |
|---|---|---|---|---|
| Суперключ | Уникально идентифицирует (определяет) строку | Нет (может содержать лишние столбцы) | Зависит от столбцов | Да (много) |
| Потенциальный ключ | Уникально идентифицирует, минимальный | Да | Нет | Да (несколько) |
| Первичный ключ | Главный идентификатор таблицы | Да | Нет | Только один |
| Альтернативный ключ | Потенциальный ключ, не выбранный как первичный | Да | Нет | Да (несколько) |
| Внешний ключ | Ссылается на первичный ключ другой таблицы | Не применимо | Да (может быть NULL) | Да (много) |
| Составной ключ | Ключ из нескольких столбцов | Да (если потенциальный или первичный) | Нет (если PK) | Да |
Типичные ошибки в работе с ключами
Ошибка 1: Нет первичного ключа в таблице
Создают таблицу без уникального идентификатора. Как тогда обновлять конкретную строку? Как удалять? Как связывать?
Как исправить: Всегда добавляйте id как первичный ключ.
Ошибка 2: Использовать естественный ключ там, где он может измениться
Сделать email первичным ключом. А потом пользователь захочет сменить email. Придется обновлять внешние ключи во всех связанных таблицах. Боль и страдания.
Как исправить: Используйте искусственный id как первичный ключ. email пусть будет альтернативным (уникальным, но не первичным).
Ошибка 3: Не объявлять внешние ключи
Логически связь есть (в коде приложения проверяют), но в базе данных внешний ключ не объявлен. СУБД не контролирует целостность. Могут появиться “висячие” записи (заказ без клиента).
Как исправить: Всегда объявляйте внешние ключи в базе данных.
Ошибка 4: Путать первичный и внешний ключ
Думать, что client_id в таблице заказов - это первичный ключ. Нет, это внешний ключ. Первичный ключ в таблице заказов – order_id.
Как исправить: Запомнить: PK – в своей таблице. FK – ссылается на PK другой таблицы.
Ошибка 5: Игнорировать составные ключи
Пытаться вставить в таблицу “Заказы_Товары” один и тот же товар в один и тот же заказ дважды. Без составного первичного ключа это возможно.
Как исправить: В таблицах-связках делайте составной первичный ключ из обеих ссылок.
Резюме для системного аналитика
Ключи – это фундамент реляционных баз данных. Они нужны для идентификации строк и связывания таблиц.
Иерархия ключей: Суперключ -> Потенциальный ключ -> Первичный ключ. Суперключ – самый широкий, первичный – самый конкретный.
Первичный ключ (PK) – главный. У каждой таблицы должен быть первичный ключ. Лучше всего – искусственный
id.Внешний ключ (FK) связывает таблицы. Он ссылается на первичный ключ другой таблицы. Обеспечивает целостность данных.
Альтернативные ключи (AK) – это тоже уникальные поля. Email, телефон, номер паспорта - они уникальны, но не являются первичным ключом.
Составные ключи – из нескольких столбцов. Часто нужны в таблицах для связи “многие-ко-многим”.