MySQL REPLACE ведет себя не так, как UPDATE, если на PRIMARY KEY ссылается FOREIGN KEY - PullRequest
3 голосов
/ 12 января 2012

У меня есть две таблицы:

CREATE TABLE `category` (
  `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` mediumint(8) unsigned NOT NULL,
  `name` varchar(20) CHARACTER SET ascii NOT NULL,
  `description` varchar(100) DEFAULT NULL,
  `repeat_interval` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `color` mediumint(8) unsigned NOT NULL,
  PRIMARY KEY (`category_id`),
  KEY `id` (`user_id`),
  CONSTRAINT `category_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON  DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `event` (
  `event_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` int(10) unsigned NOT NULL,
  `name` varchar(20) CHARACTER SET ascii NOT NULL,
  `description` varchar(100) DEFAULT NULL,
  `repeat_interval` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `color` mediumint(8) unsigned NOT NULL,
  `priority` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `done` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`event_id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `event_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `category`     (`category_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Если я сделаю REPLACE в таблице категории (одна строка), то все записи в событии таблица, ссылающаяся на измененную строку в таблице категории , будет отброшена.

Но если I UPDATE строка в таблице категории , то записи в событие таблица оставлена ​​нетронутой.

Почему это поведение, почему, когда я REPLACE что-то, все записи, ссылающиеся на этот столбец, отбрасываются?

Я пробовал оба ON UPDATE CASCADEи по умолчанию такое же поведение.

Google не может помочь мне.

Ответы [ 4 ]

6 голосов
/ 12 января 2012

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

Из Mysql Docs:

REPLACE работает точно так же, как INSERT, за исключением того, что если старая строка в таблица имеет то же значение, что и новая строка для PRIMARY KEY или UNIQUE Индекс, старая строка удаляется перед вставкой новой строки. Увидеть Раздел 12.2.5, «Синтаксис INSERT».

Советую прочитать: http://dev.mysql.com/doc/refman/5.0/en/replace.html

Чтобы обойти это, вы, вероятно, захотите использовать ON DUPLICATE KEY UPDATE синтаксис вставки: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

1 голос
/ 12 января 2012

У вас, вероятно, есть УДАЛЕННЫЙ КАСКАД.REPLACE удаляет запись из таблицы category, которая затем удаляет все записи event, назначенные этому category.

1 голос
/ 12 января 2012

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

Полагаю, что при использовании соотношения внешних ключей вы получаете каскад удаления с последующей вставкой в ​​таблицу, но без вставок во внешнюю таблицу.

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

Мне нужно было запустить скрипт однократного обновления, поэтому мой обходной путь должен был:

  1. Отменить ограничения внешнего ключа
  2. Запустите мои операторы "ЗАМЕНИТЬ В"
  3. Повторно добавить ограничения внешнего ключа

Это не сработает как постоянное решение в коде, но работает как быстрый взлом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...