Как временно отключить ограничение внешнего ключа в MySQL?

485

Можно ли временно отключить ограничения в MySQL?

У меня две модели Django, каждая из которых имеет ForeignKey для другой. Удаление экземпляров модели возвращает ошибку из-за ограничения ForeignKey:

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()  #a foreign key constraint fails here

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

Можно ли временно отключить ограничения и удалить?

  • 3
    Либо я не понимаю, что вы хотите сделать, либо то, что вы пытаетесь сделать, очень, очень, очень уродливо . Даже если вы можете сделать это, вы, вероятно, не должны.
  • 3
    Удаление и повторное FK меняет свой дб. Вы пытаетесь бросить вызов тем самым ограничениям, которые позволяют системе видеть какой-то смысл, она не учитывает, что ФК может быть временным явлением, и если бы она это знала, она бы запаниковала.
Показать ещё 5 комментариев
Теги:

10 ответов

1141
Лучший ответ

Попробуйте DISABLE KEYS или

SET FOREIGN_KEY_CHECKS=0;

убедитесь, что

SET FOREIGN_KEY_CHECKS=1;

после.

  • 10
    Это то, что установлено для MySQL в целом или только для этой сессии?
  • 17
    Я считаю, что это за сессию.
Показать ещё 5 комментариев
107

Чтобы отключить ограничение внешних ключей по всему миру, выполните следующие действия:

SET GLOBAL FOREIGN_KEY_CHECKS=0;

и не забудьте установить его, когда закончите.

SET GLOBAL FOREIGN_KEY_CHECKS=1;

ПРЕДУПРЕЖДЕНИЕ. Вы должны делать это только в том случае, если вы выполняете однопользовательский режим. Так как это может привести к несогласованности данных. Например, это будет очень полезно, когда вы загружаете большой объем данных с помощью вывода mysqldump.

  • 1
    это то, что мне нужно было знать, так что это не очень хорошая практика, но этот ответ ребят должен быть выше ...
  • 1
    Это сработало для меня после попытки «лучший ответ» не сработало для меня. Возможно, объяснение разницы может быть добавлено.
Показать ещё 7 комментариев
39

Обычно я отключу ограничения внешнего ключа, когда хочу обрезать таблицу, и поскольку я возвращаюсь к этому ответу, это для меня в будущем:

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;
23

Вместо того, чтобы отключить ваше ограничение, надолго измените его на ON DELETE SET NULL. Это выполнит аналогичную вещь, и вам не придется включать и выключать проверку ключа. Например:

ALTER TABLE tablename1 DROP FOREIGN KEY fk_name1; //get rid of current constraints
ALTER TABLE tablename2 DROP FOREIGN KEY fk_name2;

ALTER TABLE tablename1 
  ADD FOREIGN KEY (table2_id) 
        REFERENCES table2(id)
        ON DELETE SET NULL  //add back constraint

ALTER TABLE tablename2 
  ADD FOREIGN KEY (table1_id) 
        REFERENCES table1(id)
        ON DELETE SET NULL //add back other constraint

Прочитайте это (http://dev.mysql.com/doc/refman/5.5/en/alter-table.html) и это (http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html).

  • 5
    Остерегайтесь изменения таблицы может занять много времени, лучше установить глобальный сервер для FOREIGN_KEY_CHECKS в 0 и вернуть его, как только грязная работа будет выполнена. Кроме того, это может заблокировать для записи ваших таблиц.
  • 0
    Не нарушит ли это ссылку при изменении типа удаленного столбца? (Кажется, мой клиент переименовывает измененную временную таблицу в исходное имя таблицы.)
7

Чтобы отключить ограничение внешних ключей во всем мире:

SET GLOBAL FOREIGN_KEY_CHECKS = 0;

и для ограничения активного внешнего ключа

SET GLOBAL FOREIGN_KEY_CHECKS = 1;
5

Очень простое решение с phpmyadmin: в вашей таблице перейдите на вкладку SQL, после редактирования команды SQL, которую вы хотите запустить, рядом с GO есть флажок "Включить проверку внешнего ключа". Отметьте этот флажок и запустите ваш SQL. Затем он будет автоматически повторно проверен.

  • 2
    Спасибо! Действительно решение SET FOREIGN_KEY_CHECKS=0; ..... SET FOREIGN_KEY_CHECKS=1; у меня не работал в PHPMyAdmin, потому что я забыл снять флажок «Включить проверки внешнего ключа». В PHPMyAdmin вы можете пропустить эти команды SET и просто снять флажок.
2

Если поле ключа имеет значение NULL, вы также можете установить значение null перед тем, как его удалить:

cursor.execute("UPDATE myapp_item SET myapp_style_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed() 

cursor.execute("UPDATE myapp_style SET myapp_item_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()
0

Для меня просто SET FOREIGN_KEY_CHECKS=0; было недостаточно. У меня все еще было com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException.

Мне пришлось добавить ALTER TABLE myTable DISABLE KEYS; ,

Так:

SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE myTable DISABLE KEYS;
DELETE FROM myTable;
ALTER TABLE myTable ENABLE KEYS;
SET FOREIGN_KEY_CHECKS=1;
  • 0
    К вашему сведению, MySQL 5.7 выдает предупреждение, движок InnoDB не имеет этой опции при запуске команды DISABLE KEYS.
0

В phpMyAdmin вы можете выбрать несколько строк, а затем щелкнуть действие удаления. Вы войдете на экран с списком запросов на удаление, вы можете снять флажок с проверки внешнего ключа и нажать "Да", чтобы выполнить их.

Это позволит вам удалять строки, даже если существует ограничение ограничения DELETE.

0

Не рекомендуется устанавливать ограничение внешнего ключа на 0, потому что если вы это сделаете, ваша база данных не гарантирует, что она не нарушает ссылочную целостность. Это может привести к неточным, вводящим в заблуждение или неполным данным.

Вы делаете внешний ключ по какой-либо причине: потому что все значения в дочернем столбце должны совпадать со значением в родительском столбце. Если ограничений внешнего ключа нет, дочерняя строка может иметь значение, которое не находится в родительской строке, что приведет к неточным данным.

Например, скажем, у вас есть сайт для входа в систему, и каждый студент должен зарегистрироваться для учетной записи в качестве пользователя. У вас есть одна таблица для идентификаторов пользователей, с идентификатором пользователя в качестве первичного ключа; и другая таблица для учетных записей учащихся, с идентификатором студента в качестве столбца. Поскольку каждый студент должен иметь идентификатор пользователя, имеет смысл сделать идентификатор студента из таблицы учетных записей учеников внешним ключом, который ссылается на идентификатор пользователя первичного ключа в таблице идентификаторов пользователей. Если проверки внешнего ключа отсутствуют, студент может иметь идентификатор студента и идентификатор пользователя, что означает, что учащийся может получить учетную запись, не будучи пользователем, что неверно.

Представьте, если это произойдет с большим количеством данных. Вот почему вам нужна проверка внешнего ключа.

Лучше всего выяснить, что вызывает ошибку. Скорее всего, вы пытаетесь удалить из родительской строки без удаления из дочерней строки. Попробуйте удалить из дочерней строки перед удалением из родительской строки.

  • 0
    Правда, всегда есть компромисс.
  • 15
    Никто не говорит, чтобы это продолжалось вечно. Вы отключаете ограничения, загружаете некоторые данные и снова включаете их. Ничего страшного, люди делают это все время.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню