MySQL при удалении каскада. Пример испытания
Мне интересно об этом тестовом вопросе. Я сам подготовил этот пример и протестировал его, но я все еще чувствую неуверенность в ответе.
Со следующим:
CREATE TABLE foo (
id INT PRIMARY KEY AUTO_INCREMENT,
name INT
)
CREATE TABLE foo2 (
id INT PRIMARY KEY AUTO_INCREMENT,
foo_id INT REFERENCES foo(id) ON DELETE CASCADE
)
Насколько я вижу, ответ:
а. Созданы две таблицы
Хотя есть также:
б. Если строка в таблице foo2 с foo_id из 2 удалена, то строка с id = 2 в таблице foo автоматически удаляется
d. Если строка с id = 2 в таблице foo удалена, все строки с foo_id = 2 в таблице foo2 удаляются
В моем примере я бы использовал синтаксис delete:
DELETE FROM foo WHERE id = 2;
DELETE FROM foo2 WHERE foo_id = 2;
По какой-то причине мне не удалось найти какую-либо связь между таблицами, хотя кажется, что она должна быть такой. Может быть, есть какой-то параметр MySQL или, возможно, ON DELETE CASCADE
не используется должным образом в запросах создания таблицы? Мне осталось интересно...
Ответы
Ответ 1
Ответ d. является правильным, тогда и только тогда, когда механизм хранения фактически поддерживает и принуждает ограничения внешнего ключа.
Если таблицы создаются с помощью Engine=MyISAM
, то ни b. или d. правильно.
Если таблицы создаются с помощью Engine=InnoDB
, то d. является правильным.
Примечание:
Это верно для InnoDB тогда и только тогда, когда FOREIGN_KEY_CHECKS = 1
; если FOREIGN_KEY_CHECKS = 0
, то a DELETE
из родительской таблицы (foo) не удалит строки из дочерней таблицы (foo2), которые ссылаются на строку, удаленную из родительской таблицы.
Проверьте это с помощью выхода SHOW VARIABLES LIKE 'foreign_key_checks'
(1 = ВКЛ, 0 = ВЫКЛ)
(Нормальное значение по умолчанию - для этого.)
Выход из SHOW CREATE TABLE foo
покажет, какой движок использует таблица.
На выходе из SHOW VARIABLES LIKE 'storage_engine'
будет отображаться двигатель по умолчанию, используемый при создании таблицы, и двигатель не указан.
Ответ 2
У вас есть связь между двумя таблицами, это в команде создания foo2:
... foo_id int references foo(id) on delete cascade
.
В соответствии с ссылкой на внешние ограничения MySQL MySQL:
CASCADE: удалить или обновить строку из родительской таблицы и автоматически удалить или обновить соответствующие строки в дочерней таблице. Поддерживаются как ON DELETE CASCADE, так и ON UPDATE CASCADE.
Кроме того, в соответствии с ссылкой на внешние ключи MySQL:
Для систем хранения, отличных от InnoDB, при определении столбца можно использовать предложение LINK tbl_name (col_name), которое не имеет фактического эффекта и служит только как памятка или комментарий к вам, что столбец, который вы сейчас используете определение предназначено для ссылки на столбец в другой таблице.
Так как внешний ключ находится из дочерней таблицы в родительскую таблицу, она делает foo
родительскую таблицу и foo2
дочернюю таблицу, поэтому удаление строки из foo
приведет к каскадной удалению в foo2
, при условии, что вы используете InnoDB или какой-либо другой механизм хранения, который его поддерживает.