Збої на зовнішньому ключі помилкових помилок


110

Я отримую це повідомлення про помилку:

ПОМИЛКА 1217 (23000) у рядку 40: Неможливо видалити або оновити батьківський рядок: помилка зовнішнього ключа не вдається

... коли я намагаюся опустити стіл:

DROP TABLE IF EXISTS `area`;

... визначено так:

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

Найсмішніше, що я вже скинув усі інші таблиці в схемі, в яких є сторонні ключі area. Насправді база даних порожня, крім areaтаблиці.

Як це можливо мати дочірні рядки, якщо в базі даних немає жодного іншого об’єкта? Наскільки я знаю, InnoDB не дозволяє сторонні ключі в інших схемах, чи не так?

(Я навіть можу виконати RENAME TABLE area TO something_elseкоманду: -?)


Чи можливо, що таблиця є частиною співвідношення референс-цілісність в іншій схемі?
Raj More

У мене є інші копії програми, тому це завжди можливо. Однак синтаксис, який я використовую, є в основному CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id), тобто не має назви схеми в таблиці посилання: -?
Альваро Гонсалес

Відповіді:


101

Дві можливості:

  1. Існує таблиця в іншій схемі ("база даних" в термінології mysql), яка має посилання на FK
  2. Словник внутрішніх даних innodb не синхронізований з mysql.

Ви можете побачити, на якій таблиці вона була (одна з них, у будь-якому випадку), зробивши "ПОКАЖИТИ СТАТУТ ДЛЯ ДВИГАТЕЛЯ" після краплі.

Якщо це виявиться останнім випадком, я б скидаю і відновлюю весь сервер, якщо можете.

MySQL 5.1 і вище дасть вам назву таблиці з FK в повідомленні про помилку.


1
Я більше не можу відтворити проблему. Неможлива причина виділяється словником синхронізації. Я перевіряю це день і побачу, які SHOW ENGINE INNODB STATUSзвіти.
Альваро Гонсалес

3
Дякую за цю відповідь! У мене була таблиця з багатьма на багато, яка все ще посилається на таблицю, яку ми не могли скинути, тому мені довелося кинути цю таблицю спочатку.
Крістіан Оудар

5
SHOW ENGINE INNODB STATUS відображає останню помилку зовнішнього ключа у розділі "ПОСЛІДНА ПОМИЛКА ІНТЕРНЕТ-КЛЮЧ". Це часова мітка.
bbrame

там може бути таблиця, яка ще містить посилання на предметну таблицю. це було в моєму випадку так.
RT

Економили багато часу. Перекинув db у розділі "ОСТАННЯ ПОМИЛКА
ІНТЕРНЕТ-

121

За запитом, зараз як відповідь ...

Під час використання браузера MySQL Query або phpMyAdmin виявляється, що для кожного запиту відкривається нове з'єднання ( bugs.mysql.com/bug.php?id=8280 ), що робить необхідним записувати всі заяви про падіння в один запит, наприклад.

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

Там, де це SET FOREIGN_KEY_CHECKS=1служить додатковим заходом безпеки ...


2
Для тих, хто створює дамп із використанням phpMyAdmin, є опція "Вимкнути перевірку зовнішніх ключів", яка автоматично додасть SET FOREIGN_KEY_CHECKS=0;до початку дамп.
Майк

Схоже, phpMyAdmin реалізував цю чудову функцію, тепер я чекаю, коли mysqlWorkbench зробить те саме! :)
Карліс Роде

@CodeMed FYI, я прийняв відповідь MarkR, оскільки вона дає пояснення щодо проблеми, яка має сенс - хоча я визнаю, що не могла її перевірити, оскільки я не стикалася з цією ж проблемою протягом 6 наступних років, навіть жодного разу. Цей і більш ранні відповіді дають вирішення (чудово для цього добра), але насправді не вирішуйте саме питання, і оскільки ви можете прийняти лише одну відповідь, яку мені довелося вибрати.
Альваро Гонсалес

1
Попередження: це не рішення, а лише ледачий спосіб вирішення проблеми. Використовуючи це (із записами в деяких інших таблицях, що вказують на випалену таблицю), ви відчуєте звисання сторонніх ключів, що фатально порушує консистенцію ( C у ACID ) вашої бази даних, і ваші програми почнуть викидати винятки в усьому місці. Вас попередили.
bekce

Хоча я впевнений, що попередження Бекче слід розуміти і прислухатися, це рішення спрацювало для мене, в ситуації, коли я був впевнений, що я скидаю всі таблиці, які вказували на таблиці з клопітними зовнішніми ключовими обмеженнями.
користувач1147171

47

Вимкнути перевірку зовнішніх ключів

SET FOREIGN_KEY_CHECKS=0

62
Здається, що правильна команда є, SET FOREIGN_KEY_CHECKS=0і вона виправляє повідомлення про помилку. Чи маєте ви якесь уявлення про те, для чого це потрібно? Чи зберігаються кешовані зовнішні ключі навіть після зникнення таблиць?
Альваро Гонсалес

1
Ну якщо сказати правду, я не маю поняття, чому виникає така проблема, але переконайтеся, що ви відключаєте перевірку ключів щоразу, коли вносите якісь величезні зміни чи оновлення. Це траплялося зі мною кілька разів, залишаючи мене без сну цілими днями.
Flakron Bytyqi

55
Переконайтеся, що SET FOREIGN_KEY_CHECKS=1;після того, як ви закінчите!
pedro_sland

5
Під час використання браузера MySQL Query або phpMyAdmin виявляється, що для кожного запиту відкривається нове з'єднання ( bugs.mysql.com/bug.php?id=8280 ), що робить необхідним записувати всі заяви про падіння в один запит, наприклад. SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; Там, де SET FOREIGN_KEY_CHECKS = 1 є додатковим заходом безпеки ...
Карліс Роде

1
@KarlisRode, Bravo за коментар до phpMyAdmin. Якби ви ставили це як відповідь, я поставив би це +1.
Sablefoste

28

з цього блогу :

Ви можете тимчасово відключити перевірку іноземних ключів:

SET FOREIGN_KEY_CHECKS=0;

Просто не забудьте відновити їх, як тільки ви закінчите возитися:

SET FOREIGN_KEY_CHECKS=1;

Приємна відповідь, коли я розробляв місцеві :)
Аделін

Це дійсне рішення (можу підтвердити, що це працює), але пов'язаний запис в блозі насправді не говорить про сценарій у цьому питанні (база даних, яка вже порожня, збережена для однієї таблиці).
Альваро Гонсалес

6

сподіваємось, його робота

SET Foreign_key_checks = 0; КОРОТКА ТАБЛИЦЯ table name; SET Foreign_key_checks = 1;


Так, це спрацьовує, як уже кілька разів згадувалося раніше ;-)
Альваро Гонсалес

1

На рейках можна зробити наступне rails console:

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

Можливо, ви отримали помилку під час роботи з цією таблицею раніше. Ви можете перейменувати таблицю і спробувати її знову видалити.

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

Я знайшов просте рішення, експортуйте базу даних, відредагуйте її в текстовому редакторі, а потім імпортуйте її. Зроблено


4
Це цікаве рішення, яке, мабуть, насправді не повинно відбуватися. Натомість все, що потрібно змінити, слід робити через СУБД. Редагування дампа бази даних в текстовому редакторі здається стиглою проблемою для проблем.
Брендон Анзалді

1
Я не дуже розумію, у що ти входить. Демпінг бази даних, видалення CREATE TABLEкоду та завантаження дампа знову не змусить MySQL видалити таблицю. І якщо ви маєте на увазі відновлення дампа в новій базі даних ... Якщо ви хочете стерти всі таблиці, як я, новостворена база даних вже буде порожньою. Якщо ви хочете зберегти кілька таблиць, SET FOREIGN_KEY_CHECKS=0вирішення способів, про які йдеться тут, працює чудово і простіше; і вам, мабуть, не потрібно редагувати дамп, так як нова копія ваших даних, можливо, не матиме словник даних, що не синхронізується.
Альваро Гонсалес

-1

Неможливо видалити або оновити батьківський рядок: помилка зовнішнього ключа виходить з ладу ( table1. user_role, CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY ( user_id) REFERENCES user( id))

Що я зробив у два простих кроки. спочатку я видалю дочірній рядок у дочірній таблиці, як

mysql> видалити з table2, де role_id = 2 && user_id = 20;

Запит ОК, 1 ряд вплинув (0,10 сек)

і другий крок як видалення батьківського

видалити з table1 де id = 20;

Запит OK, 1 ряд постраждав (0,12 сек)

Цим я вирішую проблему, що означає «Видалити дитину» та «Видалити батьків»

Я сподіваюся, що ти це отримав. :)


Будь ласка, прочитайте питання ще раз. Ви не можете видалити таблицю, яка не існує.
Альваро Гонсалес

у цьому випадку ми можемо видалити обмеження на зовнішній ключ, а потім спробувати видалити таблицю. ми можемо скинути такий зовнішній ключ, як НАСТІЛЬНА ТАБЛИЦЯ <
TABLE_NAME
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.