Я обновляю базу данных, чтобы исправить поведение внешнего ключа при обновлении и удалении. Однако, в частности, на одном столе это было неожиданно сложно.
На большинстве таблиц я без проблем выполняю следующее:
- Отменить ограничение внешнего ключа
- Отбросить соответствующий индекс
- Добавить новый, обновленный внешний ключ
Одна таблица, однако, вызывает некоторые проблемы, которые я не совсем понимаю. Попытка выполнить описанный выше процесс возвращает следующую ошибку (я отредактировал имя БД на 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: Я просто не могу изменить поведение внешнего ключа таблицы при обновлении / удалении, несмотря на то, что это было успешно сделано для других таблиц в той же БД. Я попробовал два совершенно разных подхода к его исправлению, и оба вернули (разные) ошибки, решения которых я нигде не смог найти. Это ошибка или я что-то упустил?