Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не работает - MYSQL

Я получаю эту ошибку при попытке удалить пользователя из базы данных, я знаю, что это происходит потому, что пользователь, которого я пытаюсь удалить, является внешним ключом в таблице appointments, но я не знаю, как это исправить или где я ошибся. Не уверен, что это что-то изменит, но на всякий случай я создал таблицы с помощью laravel

Таблица "Пользователи

CREATE TABLE `users` (
  `id` int(10) UNSIGNED NOT NULL,
  `firstname` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `surname` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `address` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `postcode` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `password` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `dateofbirth` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `role` tinyint(4) NOT NULL,
  `remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Таблица назначений

 CREATE TABLE `appointments` (
      `id` int(10) UNSIGNED NOT NULL,
      `time` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
      `date` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL,
      `doctor_id` int(10) UNSIGNED NOT NULL,
      `user_id` int(10) UNSIGNED NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

    ALTER TABLE `appointments`
      ADD PRIMARY KEY (`id`),
      ADD KEY `appointments_doctor_id_foreign` (`doctor_id`),
      ADD KEY `appointments_user_id_foreign` (`user_id`);

    ALTER TABLE `appointments`
      ADD CONSTRAINT `appointments_doctor_id_foreign` FOREIGN KEY (`doctor_id`) REFERENCES `doctors` (`id`),
      ADD CONSTRAINT `appointments_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
Решение

Вы получаете эту ошибку, потому что пользователь, которого вы хотите удалить, имеет связанные с ним записи в таблице appointments. У вас есть 2 варианта:

  1. Сначала удалить связанные записи из таблицы appointments с помощью отдельного оператора delete.

  2. Добавьте опцию on delete cascade к внешнему ключу appointments_user_id_foreign. Эта опция автоматически удалит все связанные записи из таблицы appointments для удаляемого пользователя, когда вы удалите его запись.

Модифицированный оператор fk выглядит следующим образом:

... ADD CONSTRAINT `appointments_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;

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

Комментарии (0)

Похоже, что ваш внешний ключ в таблице Appointments имеет параметр On delete: Restrict. Измените ограничение appointments_user_id_foreign на On delete: Cascade, и вы сможете удалять пользователей с сохранением внешнего ключа.

ALTER TABLE "appointments" DROP FOREIGN KEY "appointments_user_id_foreign";

ALTER TABLE "appointments" ADD CONSTRAINT "appointments_user_id_foreign" FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE CASCADE;
Комментарии (1)

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

Для вашего сценария можно улучшить дизайн базы данных. Вы можете сделать столбец внешнего ключа в таблице appointments необязательным. Таким образом, при удалении пользователя соответствующая запись user_id может быть установлена как NULL. Но хранить записи о встречах для пользователей, которые больше не существуют в системе, бессмысленно. Другой подход заключается в том, чтобы перед удалением пользователя удалить все соответствующие ему ссылки из таблицы appointments, а затем удалить ссылку из таблицы users.

Комментарии (0)