Spec-Zone.ru › MySQL 5.7

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.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/ansi-diff-foreign-keys.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API