Към съдържанието
wannacode

Първичен и външен ключ

Накратко: Първичният ключ е колоната, която различава всеки ред на таблицата, а външният ключ е колона, която пази първичния ключ на ред от друга таблица.

Проблем

Чия е поръчката?

В урока „Магазинът“ търсихме с очи кой е поръчал поръчка 60 и какво има в нея. Отговорът беше разпръснат в четири таблици: orders, customers, order_items и products.

Защо магазинът не държи всичко в една голяма таблица? И как една таблица „знае“ кой ред от друга е нейният?

Идеята

Първичен ключ

Почти всяка таблица на магазина има колона id. Изключението, order_items, е в „По-точно“ в края на урока. Числото е различно за всеки ред, не се повтаря и не е празно. По него редът се намира без съмнение:

SQLбаза: магазин

Такава колона се казва първичен ключ (primary key). Имената не стават за това: двама клиенти може да се казват еднакво, а името може да се смени. Числото остава.

SQLite казва коя колона е първичният ключ. Колоната pk е 1 за нея:

SQLбаза: магазин

Идеята

Външен ключ

Поръчката не пише името на клиента. Тя пази само неговото id в колоната customer_id:

customers

  • PKidinteger
  • nametext *
  • emailtext *
  • citytext
  • joined_attext *

orders

  • PKidinteger
  • FKcustomer_idinteger *→ customers
  • ordered_attext *
  • statustext *

orders.customer_id сочи към customers.id. Колона, която пази първичния ключ на ред от друга таблица, се казва външен ключ (foreign key).

Връзките на таблица се виждат с pragma_foreign_key_list:

SQLбаза: магазин

Един ред, една връзка: от колоната customer_id (from) към колоната id (to) на таблицата customers.

Така данните на Мария (име, имейл) са записани веднъж. Ако тя смени имейла си, той се поправя в един ред на customers, а 12-те ѝ поръчки сочат все към същото id.

Пробвай

Редовете на поръчките

Към кои таблици сочи order_items? Покажи връзките ѝ.

SQLбаза: магазин

Виж го

Търсене по номер

С WHERE вече не търсим с очи. Кой е поръчал поръчка 60? Първо поръчката:

SQLбаза: магазин

customer_id е 1. После клиентът с това id:

SQLбаза: магазин

Мария Иванова. Работи, но са две заявки, а числото 1 го пренасяш на ръка. За една поръчка е търпимо. За отчет с 60 поръчки и имената на клиентите им не е. Следващият урок събира двете стъпки в една заявка с JOIN.

Пробвай

Чий е отзивът?

Отзив 13 е с оценка 1. Кой го е писал? Покажи само името на клиента.

SQLбаза: магазин

Упражнение

Две задачи

1. Отзивът сочи към две неща. Покажи връзките на таблицата reviews.

Връзките на reviews:

SQLбаза: магазин

2. Категориите са дърво: „Кухня“ е подкатегория на нещо. Външният ключ parent_id сочи към ред в същата таблица categories. Намери името на родителската категория на „Кухня“.

Родителската категория на „Кухня“:

SQLбаза: магазин
По-точно, за любопитните

Първичният ключ може да е от няколко колони. В order_items той е двойката (order_id, product_id): pk е 1 и 2 за частите му.

SQLбаза: магазин

Външният ключ е и правило: базата отказва поръчка за клиент, който го няма. В SQLite това правило е изключено по подразбиране и се пуска с PRAGMA foreign_keys = ON. Тук в курса е пуснато. В PostgreSQL външните ключове се спазват винаги. Ще ги видиш в действие в модула за промяна на данните.

Тест

Провери се

1. Кое е вярно за първичния ключ на customers?
2. orders.customer_id е 4. Какво значи това?
3. Защо името на клиента не е записано във всяка негова поръчка?
4. Първичният ключ на order_items е (order_id, product_id). Какво забранява това?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·