Mysql удалить несколько таблиц с левым соединением в одном утверждении вызвало нарушение FK - PullRequest
0 голосов
/ 06 ноября 2018

Mysql удалить несколько таблиц с левым объединением в одном операторе вызвало нарушение FK. Например,

Student       StudentDetail      
--------      ------------------------------
id, name      studentId, birthday, address

100 John       100      1/1/1982   A1
200 Scott      200      1/1/1978   A2
300 Tiger      300      1/1/1988   A3

FullTimeStudent
------------------
studentId, program

200        P1

Столбец studentId StudentDetail и FullTimeStudent - это FK, ссылающийся на столбец id таблицы Student.

Удалить учащегося с id = 200

delete t0, t2, t1 from StudentDetail t1
LEFT join FullTimeStudent t2 on (t1.studentId=t2.studentId) 
LEFT join Student t0 on (t1.studentId=t0.id) where t0.id=200;

Ошибка: нарушение ограничения внешнего ключа.

ЕСЛИ замена левого соединения на внутреннее соединение удаляется успешно. Что не так с левым соединением?

Но нет разницы между левым и внутренним соединением для выбора.

select t0.id, t2.studentId, t1.studentId from StudentDetail t1
LEFT join FullTimeStudent t2 on (t1.studentId=t2.studentId) 
LEFT join Student t0 on (t1.studentId=t0.id) where t0.id=100;

Возвращает одну строку.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Из руководства :

Если вы используете оператор DELETE для нескольких таблиц, включающий таблицы InnoDB для которого есть ограничения внешнего ключа, оптимизатор MySQL может обрабатывать таблицы в порядке, отличающемся от их отношения родитель / ребенок. В этом случае, заявление терпит неудачу и бросает назад. Вместо этого вы должны удалить из одной таблицы и полагаться на Возможности ON DELETE, которые InnoDB предоставляет для вызова других таблиц быть изменены соответствующим образом.

Как сказано в руководстве (и @Barmar), способ обойти это - добавить ON DELETE CASCADE к вашим ограничениям, например. FullTimeStudent и StudentDetail используют:

FOREIGN KEY (studentID) REFERENCES Student(id) ON DELETE CASCADE
0 голосов
/ 06 ноября 2018

Вы делаете LEFT JOIN в неправильном порядке. Первая таблица должна быть основной, а затем вы должны объединиться с таблицами подробностей.

DELETE t0, t1, t2
FROM Student t0
LEFT JOIN FullTimeStudent t1 ON t1.studentID = t0.id
LEFT JOIN StudentDetail t2 ON t2.studentID = t0.id
WHERE t0.id = 200

Тем не менее, правильный дизайн должен использовать опцию ON DELETE CASCADE в ваших ограничениях внешнего ключа. Тогда вам просто нужно удалить из основной таблицы, и соответствующие строки будут удалены автоматически.

DELETE FROM Student
WHERE id = 200
...