MySQL - Ошибка 1823: не удалось добавить ограничение внешнего ключа в системные таблицы - PullRequest
0 голосов
/ 10 ноября 2018

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

На большинстве таблиц я без проблем выполняю следующее:

  1. Отменить ограничение внешнего ключа
  2. Отбросить соответствующий индекс
  3. Добавить новый, обновленный внешний ключ

Одна таблица, однако, вызывает некоторые проблемы, которые я не совсем понимаю. Попытка выполнить описанный выше процесс возвращает следующую ошибку (я отредактировал имя БД на db_name):

SQLSTATE[HY000]: General error: 1025 Error on rename of 
'./<db_name>/#sql-5e1_1c5' to './<db_name>/doctors' 
(errno: 150 - Foreign key constraint is incorrectly formed)
(SQL: alter table `doctors` drop index `doctors_id_unique`)

Соответствующая часть таблицы выглядит следующим образом:

  UNIQUE KEY `doctors_id_unique` (`id`),
  UNIQUE KEY `doctors_code_unique` (`code`),
  KEY `doctors_updated_by_foreign` (`updated_by`),
  CONSTRAINT `doctors_id_foreign` FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
  CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Я хочу изменить id на первичный ключ и внешний ключ, поэтому я делаю следующее:

ALTER TABLE doctors DROP FOREIGN KEY doctors_id_foreign;
ALTER TABLE doctors DROP INDEX doctors_code_unique;
ALTER TABLE doctors DROP INDEX doctors_id_unique;

Однако в этом третьем утверждении я получаю следующую ошибку:

Error on rename of './<db_name>/#sql-5e1_2' to './<db_name>/doctors' 
(errno: 150 - Foreign key constraint is incorrectly formed)

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

Я пытаюсь изменить дамп SQL, который я использовал для тестов. Если изменить его на следующее, то все заработало, как я и предполагал, по крайней мере, на первый взгляд:

  PRIMARY KEY (`id`),
  UNIQUE KEY `doctors_code_unique` (`code`),
  KEY `doctors_updated_by_foreign` (`updated_by`),
  CONSTRAINT `doctors_id_foreign` FOREIGN KEY (`id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

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

SET FOREIGN_KEY_CHECKS=0;
RENAME TABLE `doctors` TO `old_doctors`;
CREATE TABLE `doctors` SELECT * FROM `old_doctors`;
ALTER TABLE `doctors` ADD PRIMARY KEY (`id`);
ALTER TABLE `doctors` ADD UNIQUE INDEX `doctors_code_unique` (`code`);
ALTER TABLE `doctors` ADD CONSTRAINT `doctors_id_foreign` FOREIGN KEY `doctors_id_foreign` (`id`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE `doctors` ADD CONSTRAINT `doctors_updated_by_foreign` FOREIGN KEY `doctors_updated_by_foreign` (`updated_by`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE SET NULL;
SET FOREIGN_KEY_CHECKS=1;

И теперь я получаю следующую ошибку:

SQLSTATE[HY000]: General error: 1823 Failed to add the foreign key constraint
'<db_name>/doctors_id_foreign' to system tables (SQL: ALTER TABLE `doctors`
ADD CONSTRAINT `doctors_id_foreign` FOREIGN KEY `doctors_id_foreign` (`id`) 
REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE)

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

Это заняло так много времени, что я, вероятно, собираюсь отключить серверы, вывести дамп БД, исправить дамп вручную и импортировать фиксированный дамп обратно; Тем не менее, я бы очень хотел знать, если это какая-то ошибка или я просто что-то упустил Что весьма вероятно, потому что я вряд ли опытный программист.

Для контекста: это все в проекте Laravel (5.7.13), но ошибки происходят как при миграции Laravel (со схемой и планом), так и непосредственно через консоль SQL. MySQL версия 5.7.22.

tl; dr: Я просто не могу изменить поведение внешнего ключа таблицы при обновлении / удалении, несмотря на то, что это было успешно сделано для других таблиц в той же БД. Я попробовал два совершенно разных подхода к его исправлению, и оба вернули (разные) ошибки, решения которых я нигде не смог найти. Это ошибка или я что-то упустил?

1 Ответ

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

Убедитесь, что никакие другие таблицы не ссылаются на столбец doctors.id в своих внешних ключах.

Если они есть, удалите эти внешние ключи, прежде чем сбросить индекс doctors_id_unique.

Затем восстановите внешние ключи после того, как вы сделали doctors.id первичным ключом.

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