Эта статья была написана в 2009 году и остается одной из наших самых популярных публикаций. Если вы хотите больше узнать о MySQL и разработке баз данных, вы можете найти эту более свежую статью интересной.
MySQL — это фантастическая база данных с открытым исходным кодом, используемая многими тысячами веб-приложений. Настольная система MyISAM по умолчанию является одной из самых простых и быстрых, но она не поддерживает внешние ключи (хотя она запланирована для версии 6 ).
К счастью, менее используемый тип таблиц InnoDB поддерживает внешние ключи: эта статья покажет, как они могут уменьшить ваши усилия по написанию кода и повысить целостность данных.
Что такое иностранные ключи?
Внешний ключ устанавливает связь или ограничение между двумя таблицами.
Отказ от ответственности! В этом примере мы создадим две простые таблицы базы данных. Они не очень хорошо разработаны, но продемонстрируют силу внешних ключей!
- employee : таблица сотрудников компании, в которой каждому участнику присвоен уникальный идентификатор
- заимствовано : таблица заимствованных книг. Каждая запись будет ссылаться на идентификатор сотрудника заемщика.
Мы определим отношение внешнего ключа между идентификатором сотрудника в обеих таблицах. Это обеспечивает пару преимуществ:
- Невозможно ввести неверный идентификатор сотрудника в таблицу «заимствовано».
- Изменения сотрудников обрабатываются MySQL автоматически.
Создание примера базы данных
Наш пример базы данных создается следующим образом:
CREATE DATABASE mydb;
USE mydb;
Теперь мы определим наши две таблицы. Обратите внимание, что InnoDB указан в качестве типа таблицы, и мы также добавим индекс для фамилии сотрудника.
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Теперь мы можем указать наш внешний ключ (это может быть обработано в операторе CREATE TABLE, но здесь это показано отдельно):
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
Это говорит MySQL, что мы хотим изменить заимствованную таблицу, добавив ограничение под названием «FK_borrowed». Столбец employeeid будет ссылаться на столбец id в таблице employee — другими словами, сотрудник должен существовать, прежде чем он сможет одолжить книгу.
Последние две строчки, пожалуй, самые интересные. Они утверждают, что если идентификатор сотрудника обновлен или сотрудник удален, изменения должны быть применены к таблице заимствований.
Добавление данных таблицы
Теперь мы будем заполнять таблицы данными. Помните, что наши сотрудники должны быть добавлены в первую очередь:
сотрудник:
Я бы | Имя | фамилия | Дата рождения |
---|---|---|---|
1 | Джон | кузнец | 1976-01-02 |
2 | Лаура | Джонс | 1969-09-05 |
3 | Джейн | зеленый | 1967-07-15 |
заимствованы:
ссылка | EmployeeID | книга |
---|---|---|
1 | 1 | SitePoint просто SQL |
2 | 1 | SitePoint Ultimate HTML-справочник |
3 | 1 | Ссылка на SitePoint Ultimate CSS |
4 | 2 | SitePoint Искусство и Наука JavaScript |
Таблица показывает, что Джон одолжил 3 книги, Лора одолжила 1, а Джейн не одолжила ни одной. Можно выполнить стандартные запросы SQL, чтобы найти полезную информацию, например, «какие книги Джон позаимствовал»:
SELECT book FROM borrowed
JOIN employee ON employee.id=borrowed.employeeid
WHERE employee.lastname='Smith';
Результат:
SitePoint просто SQL
SitePoint Ultimate HTML-справочник
Ссылка на SitePoint Ultimate CSS
Каскадирование в действии
Бухгалтерия звонит нам с проблемой: идентификатор сотрудника Лауры должен быть изменен с 2 на 22 из-за технической ошибки. При использовании стандартных таблиц MyISAM вам необходимо изменить каждую таблицу, которая ссылается на идентификатор сотрудника. Однако наши ограничения InnoDB гарантируют, что изменения каскадируются после одного обновления:
UPDATE employee SET id=22 WHERE id=2;
Если мы посмотрим на нашу заимствованную таблицу, мы обнаружим, что обновление произошло без необходимости запуска дополнительного кода:
заимствованы:
ссылка | EmployeeID | книга |
---|---|---|
1 | 1 | SitePoint просто SQL |
2 | 1 | SitePoint Ultimate HTML-справочник |
3 | 1 | Ссылка на SitePoint Ultimate CSS |
4 | 22 | SitePoint Искусство и Наука JavaScript |
Это напряженный день, и теперь у нас есть отдел кадров по телефону. Джон так много узнал из книг SitePoint, что он покинул компанию, чтобы создать ее самостоятельно (его обыскали у двери, чтобы он вернул их всех). Опять же, нам нужен один оператор SQL:
DELETE FROM employee WHERE id=1;
Удаление каскадно переходит к нашей заимствованной таблице, поэтому все ссылки Джона удаляются:
заимствованы:
ссылка | EmployeeID | книга |
---|---|---|
4 | 22 | SitePoint Искусство и Наука JavaScript |
Хотя это простой пример, он демонстрирует силу внешних ключей. Сохранить целостность данных легко без дополнительного кода или сложной серии команд SQL. Обратите внимание, что в ваших определениях UPDATE и DELETE есть другие альтернативы «CASCADE»:
- НЕТ ДЕЙСТВИЯ или ОГРАНИЧЕНИЯ : обновление / удаление отклоняется, если в таблице ссылок есть одно или несколько связанных значений внешнего ключа, т. Е. Вы не можете удалить сотрудника до тех пор, пока его книги не будут возвращены.
- SET NULL : обновить / удалить строку родительской таблицы, но для столбцов внешнего ключа в нашей дочерней таблице с несовпадающими значениями установить значение NULL (обратите внимание, что столбец таблицы не должен быть определен как NOT NULL).
Те же самые понятия могут быть применены к крупномасштабным базам данных, содержащим десятки таблиц с взаимосвязанными отношениями.
Если вам понравилось читать этот пост, вы полюбите Learnable ; место, чтобы узнать новые навыки и приемы у мастеров. Участники получают мгновенный доступ ко всем электронным книгам и интерактивным онлайн-курсам SitePoint, таким как PHP и MySQL для веб-разработчиков для начинающих .
Комментарии к этой статье закрыты. Есть вопрос о MySQL? Почему бы не спросить об этом на наших форумах ?