Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL външни ключове

Външните ключове са неразделна част от създаването на връзка в релационни бази данни. Ето защо и как да ги създадете.

Така че установихме, че първичният ключ предоставя уникален идентификатор за таблицата. Но първичните ключове не са единственият тип "ключ". Нашата база данни може да съдържа и външни ключове.

Какво е външен ключ?

външен ключ е колона (или колекция от колони) в една таблица, която уникално идентифицира ред от друга таблица. Това определя връзка между двете таблици.

Външният ключ ви позволява да правите кръстосани препратки към свързани данни в таблици. Това е полезно, когато колона съдържа данни, които са представени в друга таблица.

Пример

Ето диаграма на нашия FruitShop база данни, показваща връзката между Плодове таблица и Единици маса.

Черната линия, която свързва двете таблици, показва външен ключ. UnitId полето в Плодове таблицата е външен ключ към UnitId полето в Единици маса. Следователно стойността, която вмъкваме в Fruit.UnitId трябва да съответства на стойност в Units.UnitId . Това активира Fruit.UnitId за справка с данните в другите колони за този запис (т.е. записът, който има съответния UnitId ).

Данните

Така че, ако нашите Плодове таблицата съдържа запис като този:

FruitId FruitName Инвентар UnitId Въведена дата Дата е актуализирана
1 Ябълка 10 3 27.11.2012 г. 12:42:10 27.11.2012 г. 12:42:10

И нашите Единици таблицата съдържа следните записи:

UnitId Име на единица Въведена дата Дата е актуализирана
1 Парче 30.12.2011 12:46:15 30.12.2011 12:46:15
2 Груп 30.12.2011 12:46:15 30.12.2011 12:46:15
3 Килограм 30.12.2011 12:46:15 30.12.2011 12:46:15
4 Контейнер 30.12.2011 12:46:15 30.12.2011 12:46:15
5 Паунд 30.12.2011 12:46:15 30.12.2011 12:46:15
6 Унция 30.12.2011 12:46:15 30.12.2011 12:46:15

Можете да видите, че Fruit.UnitId полето съдържа 3 . Сега погледнете Единиците таблица за записа, който съдържа 3 в UnitId поле. Можете да видите, че този запис представлява килограм . Затова вече знаем, че ябълките се измерват в килограми.

Хубавото на настройката на базата данни по този начин е, че не е необходимо да повтаряме "килограми" за всеки запис, който използва тази единица. Намаляването на дублирането е ключово предимство на системите за управление на релационни бази данни.

Виждам толкова много записи в Плодове таблицата ще споделя едно и също име на единица (например, "Килограми", "Контейнер", "Куп" и т.н.), трябва да помислим внимателно, преди да добавим дубликати към нашата база данни. Без да използваме връзка с външен ключ, бихме могли просто да напишем имената на единиците направо в Fruit таблица (и може би извикайте колоната "Unit", "UnitType" или "UnitName"). Тогава ще се окажем с много записи, споделящи една и съща стойност за колоната с име на единица. Ще видим "Kilogram" да се повтаря отново и отново срещу много записи. Също така ще видим повторение на „Bunch“ и всеки друг популярен тип единица.

Въпреки че не е непременно „грешно“ да се прави това, обикновено е по-ефективно да се съхранява по един запис за всяко от тези имена на единици в отделна таблица, след което да се препраща към тази таблица чрез UnitId колона. Правенето на това е по-ефективно от повтарянето на тези имена на единици отново и отново за всеки запис, създаден в Плодове маса. Също така улеснява, ако някога решим да актуализираме име на единица (например да променим „Kilograms“ на „Kilos“). Ако актуализираме име на единица, това няма да засегне Плодовете таблица, защото UnitId ще остане същото. Освен това помага да се предотврати появата на непоследователни данни в нашата база данни.

Ограничение на външния ключ

Ограничението за външен ключ е обект на база данни, който помага за поддържането на последователност на данните за външния ключ. Създавате ограничение за външен ключ, за да поддържате референтната цялост. Създавайки ограничение за външен ключ, вие казвате на MySQL да наложи определени правила върху данните. Когато данните се вмъкнат, изтрият или актуализират, MySQL ще провери дали се придържат към външния ключ, който сте създали между таблиците. Ако не, това ще предотврати записването/презаписването/изтриването на данните, като по този начин ще поддържа референтната цялост.

Например, ако потребител се опита да въведе стойност на UnitId в Fruit.UnitId колона, но няма съответен запис в Units.UnitId колона, тогава MySQL ще попречи на потребителя да въведе тази стойност.

Когато създадохме нашите две таблици, добавихме ограничение за външен ключ към Fruit маса. Ето кода, който използвахме за създаване на ограничението:

CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE

Когато разширите възлите в левия СХЕМИ раздел, можете да видите външния ключ, който създадохме (както и първичните ключове):

Ако се опитате да вмъкнете данни, които не отговарят на ограничението на външния ключ, трябва да получите грешка.

Например, ако се опитам да вмъкна запис в Fruit таблица с помощта на UnitId стойност, която не съществува в Единици таблица получавам следната грешка:

Това се случва, защото се опитвам да вмъкна стойност от 5 в UnitId колона, когато няма съответна стойност в Units.UnitId поле.

За да успея, трябва да се уверя, че има запис в Единици таблица с UnitId от 5 .

Външният ключ не работи?

Може да срещнете случайна ситуация, в която изглежда, че външният ключ не работи. Например, можете успешно да вмъкнете данни в таблица, въпреки че има външен ключ, който трябва да предотврати вмъкването на тези данни.

Има няколко неща, които можете да проверите в тази ситуация.

  • Уверете се, че сте добавили ON DELETE и ON UPDATE клаузи във вашия код. Например ON DELETE RESTRICT ON UPDATE CASCADE . Вижте нашия пример CREATE TABLE за това кога да поставите този код.
  • Уверете се, че таблицата е InnoDB . Можете да направите това, като добавите ENGINE=InnoDB до края на вашия CREATE TABLE изявление (вижте моя пример от времето, когато създадохме нашите таблици). Някои двигатели (като MyISAM ) не поддържат ограничения за външен ключ, но не предоставят никакво предупреждение за това, когато се опитвате да създадете ограничение за външен ключ. Ако вашата машина по подразбиране не е InnoDB тогава е вероятно вашите външни ключове да не се поддържат.
  • Уверете се, че MySQL действително проверява външни ключове. Можете да направите това, като изпълните следния код:SET FOREIGN_KEY_CHECKS=1 .

Деактивирайте проверката на чужд ключ

Възможно е да има моменти, когато ограниченията на външния ключ могат да станат ненужно ограничаващи - до точката, в която сериозно възпрепятстват усилията ви при зареждане на данни. Например, когато току-що сте създали база данни и трябва да заредите първоначалните данни. Или ако трябва да пуснете куп таблици и да презаредите данните.

Ако не заредите данните в правилния ред, вероятно ще продължите да получавате грешки във външния ключ поради това, че данните се зареждат в грешен ред (т.е. опитвате се да заредите дъщерните таблици, преди родителските таблици да имат своите заредени данни).

Това не е проблем само при зареждане информацията. Можете също да срещнете този проблем, когато създавате базата данни на първо място. Ако не създадете таблиците в правилния ред, може да срещнете грешки поради ограничения на външния ключ.

Ако не знаете правилния ред родител-дете, може да отнеме много време и усилия за установяване на правилния ред за създаване на база данни или зареждане на данните. В случаи като тези може би е по-добре да кажете на MySQL временно да не проверява външните ключове засега.

Можете да деактивирате проверката на външния ключ със следния код:

FOREIGN_KEY_CHECKS=0

За да го активирате отново, направете това:

FOREIGN_KEY_CHECKS=1

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Може ли Mysql да раздели колона?

  2. Какво е кардиналност в MySQL?

  3. Как да инсталирам MySQLdb (библиотека за достъп до данни на Python към MySQL) на Mac OS X?

  4. Прехвърляне от VARCHAR към INT - MySQL

  5. Как да преброите всички редове, когато използвате SELECT с LIMIT в MySQL заявка?