1.6.2.3 Различия в ограничениях FOREIGN KEY
Реализация ограничений внешнего ключа в MySQL отличается от стандарта SQL в следующих ключевых аспектах:
Если в родительской таблице есть несколько строк с одинаковым значением связанного ключа,
InnoDBвыполняет проверку внешнего ключа так, как если бы другие строки родительской таблицы с одинаковым значением ключа не существовали. Например, если вы определили ограничение типаRESTRICT, и есть строка дочерней таблицы с несколькими строками родительской таблицы,InnoDBне позволит удалить ни одну из строк родительской таблицы.Если
ON UPDATE CASCADEилиON UPDATE SET NULLвыполняет рекурсивное обновление той же таблицы, которую уже обновил ранее в ходе каскадирования, он действует какRESTRICT. Это означает, что вы не можете использовать самоссылочныеON UPDATE CASCADEилиON UPDATE SET NULLоперации. Это предотвращает бесконечные циклы, возникающие из-за каскадных обновлений. СамоссылочныеON DELETE SET NULL, в свою очередь, возможны, как и самоссылочныеON DELETE CASCADE. Глубина вложенных каскадных операций не может превышать 15 уровней.В операторе SQL, который вставляет, удаляет или обновляет множество строк, ограничения внешних ключей (как и ограничения уникальности) проверяются построчно. При проверке ограничений внешних ключей
InnoDBустанавливает общие блокировки на уровне строк для дочерних или родительских записей, которые необходимо проверить. MySQL проверяет ограничения внешних ключей немедленно; проверка не откладывается до завершения транзакции. Согласно стандарту SQL, поведение по умолчанию должно быть отложенной проверкой. То есть, ограничения проверяются только после обработки всего оператора SQL. Это означает, что нельзя удалить строку, которая ссылается на себя с помощью внешнего ключа.-
Ни один из двигателей хранения, включая
InnoDB, не распознает или не выполняет ограничениеMATCH, используемое в определениях ограничений целостности. Использование явногоMATCHпредложения не имеет указанного эффекта, и приводит к игнорированиюON DELETEиON UPDATEпредложений. Следует избегать указанияMATCH.Предложение
MATCHв стандарте SQL управляет тем, как обрабатываются значенияNULLв составном (многоколонном) внешнем ключе при сравнении с первичным ключом в таблице ссылок. MySQL по сути реализует семантику, определеннуюMATCH SIMPLE, которая позволяет внешнему ключу быть полностью или частичноNULL. В этом случае строка (дочерней таблицы), содержащая такой внешний ключ, может быть вставлена, даже если она не соответствует никакой строке в таблице ссылок (родительской). (Можно реализовать другую семантику с помощью триггеров). -
MySQL требует, чтобы столбцы ссылок были индексированы по соображениям производительности. Однако MySQL не требует, чтобы столбцы ссылок были
UNIQUEили были объявленыNOT NULL.Ограничение
FOREIGN KEY, которое ссылается на не-UNIQUEключ, не является стандартным SQL, а скорее расширениемInnoDB. Двигатель храненияNDB, с другой стороны, требует явного уникального ключа (или первичного ключа) на любом столбце, на который ссылается внешний ключ.Обработка ссылок внешних ключей на неуникальные ключи или ключи, содержащие
NULLзначения, не определена для операций, таких какUPDATEилиDELETE CASCADE. Вам рекомендуется использовать внешние ключи, которые ссылаются только наUNIQUE(включаяPRIMARY) иNOT NULLключи. Для двигателей хранения, которые не поддерживают внешние ключи (таких как
MyISAM), MySQL Server анализирует и игнорирует спецификации внешних ключей.-
MySQL анализирует, но игнорирует “встроенные
REFERENCESспецификации” (как определено в стандарте SQL), где ссылки определены как часть спецификации столбца. MySQL принимаетREFERENCESпредложения только в случае, если они указаны как часть отдельнойFOREIGN KEYспецификации.Определение столбца с использованием
REFERENCESпредложения не оказывает реального воздействия и служит только заменой или комментарием для вас, что столбец, который вы сейчас определяете, предназначен для ссылки на столбец в другой таблице. Важно понимать при использовании этого синтаксиса, что:tbl_name(col_name)MySQL не выполняет никаких проверок, чтобы убедиться, что
col_nameфактически существует вtbl_name(или даже чтоtbl_nameсамо существует).MySQL не выполняет никаких действий по
tbl_name, таких как удаление строк в ответ на действия, выполненные со строками в таблице, которую вы определяете; другими словами, этот синтаксис не вызываетON DELETEилиON UPDATEповедения. (Хотя вы можете написатьON DELETEилиON UPDATEпредложение в рамкахREFERENCESпредложения, оно также игнорируется).Этот синтаксис создает столбец; он не создает никаких индексов или ключей.
Вы можете использовать созданный таким образом столбец в качестве столбца для соединения, как показано здесь:
CREATE TABLE person ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE shirt ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('t-shirt', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), PRIMARY KEY (id) ); INSERT INTO person VALUES (NULL, 'Antonio Paz'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'polo', 'blue', @last), (NULL, 'dress', 'white', @last), (NULL, 't-shirt', 'blue', @last); INSERT INTO person VALUES (NULL, 'Lilliana Angelovska'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'dress', 'orange', @last), (NULL, 'polo', 'red', @last), (NULL, 'dress', 'blue', @last), (NULL, 't-shirt', 'white', @last); SELECT * FROM person; +----+---------------------+ | id | name | +----+---------------------+ | 1 | Antonio Paz | | 2 | Lilliana Angelovska | +----+---------------------+ SELECT * FROM shirt; +----+---------+--------+-------+ | id | style | color | owner | +----+---------+--------+-------+ | 1 | polo | blue | 1 | | 2 | dress | white | 1 | | 3 | t-shirt | blue | 1 | | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | | 7 | t-shirt | white | 2 | +----+---------+--------+-------+ SELECT s.* FROM person p INNER JOIN shirt s ON s.owner = p.id WHERE p.name LIKE 'Lilliana%' AND s.color <> 'white'; +----+-------+--------+-------+ | id | style | color | owner | +----+-------+--------+-------+ | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | +----+-------+--------+-------+При использовании в таком формате предложение
REFERENCESне отображается в выходных данныхSHOW CREATE TABLEилиDESCRIBE:SHOW CREATE TABLE shirt\G *************************** 1. row *************************** Table: shirt Create Table: CREATE TABLE `shirt` ( `id` smallint(5) unsigned NOT NULL auto_increment, `style` enum('t-shirt','polo','dress') NOT NULL, `color` enum('red','blue','orange','white','black') NOT NULL, `owner` smallint(5) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1
Дополнительную информацию об ограничениях внешних ключей см. в разделе 13.1.18.5, «Ограничения FOREIGN KEY».
© 2025 Oracle
Licensed under the GPLv2 License.