1.7.2.3 Отличия в ограничении FOREIGN KEY
Реализация ограничений внешнего ключа в MySQL отличается от стандарта SQL в следующих ключевых аспектах:
-
Если в родительской таблице несколько строк имеют одинаковое значение связанного ключа,
InnoDBвыполняет проверку внешнего ключа так, как будто другие родительские строки с одинаковым значением ключа не существуют. Например, если вы определили ограничение типаRESTRICT, и есть дочерняя строка со множеством родительских строк,InnoDBне позволяет удалить ни одну из родительских строк. Это показано в следующем примере:mysql>
CREATE TABLE parent (->id INT,->INDEX (id)->) ENGINE=InnoDB;Query OK, 0 rows affected (0.04 sec) mysql>CREATE TABLE child (->id INT,->parent_id INT,->INDEX par_ind (parent_id),->FOREIGN KEY (parent_id)->REFERENCES parent(id)->ON DELETE RESTRICT->) ENGINE=InnoDB;Query OK, 0 rows affected (0.02 sec) mysql>INSERT INTO parent (id)->VALUES ROW(1), ROW(2), ROW(3), ROW(1);Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql>INSERT INTO child (id,parent_id)->VALUES ROW(1,1), ROW(2,2), ROW(3,3);Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql>DELETE FROM parent WHERE id=1;ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE RESTRICT) Если
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. В этом случае строка (таблица потомков) содержащая такой внешний ключ может быть вставлена, даже если она не соответствует никакой строке в связанной (родительской) таблице. (Возможно реализовать другую семантику с помощью триггеров.) -
Ограничение
FOREIGN KEY, ссылающееся на не-UNIQUEключ, не является стандартным SQL, а скорее расширениемInnoDB, которое теперь устарело и должно быть включено, установивrestrict_fk_on_non_standard_key. Вы должны ожидать, что поддержка использования нестандартных ключей будет удалена в будущих версиях MySQL, и перейти от них сейчас.Двигатель хранилища
NDBтребует явного уникального ключа (или первичного ключа) для любого столбца, на который ссылается внешний ключ, согласно стандарту SQL. Для двигателей хранилища, которые не поддерживают внешние ключи (такие как
MyISAM), MySQL Server анализирует и игнорирует спецификации внешних ключей.-
Предыдущие версии MySQL анализировали, но игнорировали “встроенные
REFERENCESспецификации” (как определено в стандарте SQL), где ссылки были определены как часть спецификации столбца. MySQL 9.2 принимает такиеREFERENCESпредложения и применяет созданные таким образом внешние ключи. Кроме того, MySQL 9.2 допускает неявные ссылки на первичный ключ родительской таблицы. Это означает, что следующий синтаксис допустим: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('tee', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'yellow', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person, PRIMARY KEY (id) );Вы можете убедиться в этом, проверив вывод
SHOW CREATE TABLEилиDESCRIBE, например так:mysql>
SHOW CREATE TABLE shirt\G*************************** 1. row *************************** Table: shirt Create Table: CREATE TABLE `shirt` ( `id` smallint unsigned NOT NULL AUTO_INCREMENT, `style` enum('tee','polo','dress') NOT NULL, `color` enum('red','blue','yellow','white','black') NOT NULL, `owner` smallint unsigned NOT NULL, PRIMARY KEY (`id`), KEY `owner` (`owner`), CONSTRAINT `shirt_ibfk_1` FOREIGN KEY (`owner`) REFERENCES `person` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Для получения дополнительной информации об ограничениях внешнего ключа, см. Раздел 15.1.21.5, «Ограничения FOREIGN KEY».
© 2025 Oracle
Licensed under the GPLv2 License.