Как обрезать таблицу ограничений по внешнему ключу?

408

Почему не работает TRUNCATE на mygroup? Даже если у меня есть ON DELETE CASCADE SET, я получаю:

ОШИБКА 1701 (42000): не удается обрезать таблицу, на которую ссылается ограничение внешнего ключа (mytest. instance, CONSTRAINT instance_ibfk_1 ИНОСТРАННЫЙ КЛЮЧ (GroupID) ССЫЛКИ mytest. mygroup (ID))

drop database mytest;
create database mytest;
use mytest;

CREATE TABLE mygroup (
   ID    INT NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;

CREATE TABLE instance (
   ID           INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
   GroupID      INT NOT NULL,
   DateTime     DATETIME DEFAULT NULL,

   FOREIGN KEY  (GroupID) REFERENCES mygroup(ID) ON DELETE CASCADE,
   UNIQUE(GroupID)
) ENGINE=InnoDB;
Теги:
foreign-keys
constraints
truncate
dml

7 ответов

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

Вы не можете TRUNCATE таблицу с ограничениями FK, применяемыми к ней (TRUNCATE не совпадает с DELETE).

Чтобы обойти это, используйте любое из этих решений. Оба представляют опасность повреждения целостности данных.

Вариант 1:

  • Удалить ограничения
  • Выполнить TRUNCATE
  • Удалить вручную строки, которые теперь имеют ссылки на нигде
  • Создать ограничения

Вариант 2:, предложенный user447951 в их ответе

SET FOREIGN_KEY_CHECKS = 0; 
TRUNCATE table $table_name; 
SET FOREIGN_KEY_CHECKS = 1;
  • 176
    На самом деле, сэр, нет. user447951 показал нам свет!
  • 37
    @barjonah: на самом деле это может нарушить целостность данных (см. stackoverflow.com/questions/5452760/… ). То, что вы называете «светом» в реальном мире, считается плохой практикой. PS: спасибо за понижение
Показать ещё 19 комментариев
994

Да, вы можете:

SET FOREIGN_KEY_CHECKS = 0;

TRUNCATE table1;
TRUNCATE table2;

SET FOREIGN_KEY_CHECKS = 1;

С этими утверждениями вы рискуете вставить строки в свои таблицы, которые не соответствуют ограничениям FOREIGN KEY.

  • 27
    мы должны установить SET FOREIGN_KEY_CHECKS = 1; снова потом?
  • 1
    Я думаю, что вы должны установить его снова на 1, потому что это значение по умолчанию.
Показать ещё 16 комментариев
98

Я бы просто сделал это с помощью

DELETE FROM mytest.instance;
ALTER TABLE mytest.instance AUTO_INCREMENT = 1;
  • 5
    Умный. Если вы все равно хотите удалить все записи, вы можете сбросить автоприращение.
  • 5
    Это, очевидно, лучший способ сделать это. Нет риска потери ограничений, просто удалить. Стоит отметить, что DELETE работает медленнее, чем TRUNCATE . Но так как это действие обычно выполняется очень редко, это не имеет значения.
Показать ещё 4 комментария
10

Согласно документации mysql, TRUNCATE не может использоваться в таблицах с отношениями внешнего ключа. Нет полной альтернативы AFAIK.

Отбрасывание контраста по-прежнему не вызывает ВКЛ. УДАЛЕНИЕ и ОБНОВЛЕНИЕ. Единственное решение, которое я могу использовать ATM, - это либо:

  • удалять все строки, удалять внешние ключи, обрезать, воссоздавать ключи
  • удалить все строки, reset auto_increment (если используется)

Казалось бы, TRUNCATE в MySQL еще не является полной функцией (он также не вызывает триггеры). См. Комментарий

  • 6
    Замечание о том, что MySQL TRUNCATE является неполным - truncate не должен вызывать триггеры и т. Д. Если это так, то это будет то же самое, что и DELETE ! Он не зависит от строки, поэтому не может выполнять операции, связанные со строками (например, вызывать триггеры или проверять внешние ключи). Аналогичным образом работает в Oracle и Sql Server .
  • 0
    Этот комментарий является лучшим объяснением, которое я нашел о том, почему TRUNCATE не может игнорировать или пропускать ограничения FK. Большое спасибо Саймон MᶜKenzie. Я также не согласен с тем, что TRUNCATE не является «полной функцией»: это всего лишь ожидаемое поведение для обеспечения согласованности.
Показать ещё 1 комментарий
3

вы можете сделать

DELETE FROM `mytable` WHERE `id` > 0
  • 1
    Я попытался, но появилась следующая ошибка: Код ошибки: 1142. Команда DELETE запрещена пользователю 'root' @ 'localhost' для таблицы 'mytable'
2

Хотя этот вопрос был задан более 5 лет назад, и я не знаю, что это средство существовало в MySql, но теперь, если вы используете phpmyadmin, вы можете просто открыть базу данных, а затем выбрать таблицу (ы), которые вы хотите усечь. Внизу есть выпадающее меню со многими опциями. Откройте его и выберите Пустой вариант под заголовком Удалить данные или таблицу. Он автоматически переместит вас на следующую страницу, где есть опция в флажке "Включить проверки внешнего ключа". Просто отмените выбор и нажмите кнопку "Да", и выбранная таблица (таблицы) будет усечена. Может быть, он внутренне выполняет запрос, предложенный в user447951. Но это очень удобно использовать из интерфейса phpmyadmin.

  • 0
    Работал как очарование формы мне спасибо
  • 1
    Очень хороший ответ
0

Ответ действительно тот, который предоставляется zerkms, как указано в Вариант 1:

Вариант 1: это не повредит целостности данных:

  • Удалить ограничения
  • Выполнить TRUNCATE
  • Удалить вручную строки, которые теперь ссылаются на нигде
  • Создать ограничения

Сложная часть Удаление ограничений, поэтому я хочу рассказать вам, как, если кто-то должен знать, как это сделать:

  • Запустите запрос SHOW CREATE TABLE <Table Name>, чтобы узнать, каково ваше имя FOREIGN KEY (красная рамка внизу):

    Изображение 831

  • Запустите ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign Key Name>. Это устранит ограничение внешнего ключа.

  • Отсоедините связанный Индекс (через страницу структуры таблицы), и все готово.

  • 0
    Это помогло мне! Можете ли вы также рассказать мне, как восстановить ограничение после его удаления?

Ещё вопросы

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