无法删除或更新父行:外键约束失败 - MYSQL

时间:2017-04-19 11:02:16

标签: mysql

我在尝试从数据库中删除用户时遇到此错误,我知道这样做是因为我正在尝试删除的用户是约会表中的外键,但我不知道如何纠正它或我出错的地方。不确定它是否会改变,只是因为我使用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`);

8 个答案:

答案 0 :(得分:13)

您收到此错误,因为您要删除的用户在appointments表中包含相关记录。您有两个选择:

  1. 首先使用单独的delete语句从约会表中删除关联的记录。

  2. on delete cascade选项添加到appointments_user_id_foreign外键。当您删除用户的记录时,此选项将自动从appointments表中删除要删除的用户的任何关联记录。

  3. 修改后的fk语句如下所示:

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

    @Nebster提出的解决方案在技术上删除了错误消息,但也允许在appointments表中使用孤立记录 - 与已删除用户相关的约会。因此,在我看来,删除外键不是一个明智的选择。

答案 1 :(得分:4)

SET FOREIGN_KEY_CHECKS=0; - 禁用它们

SET FOREIGN_KEY_CHECKS=1; - 重新启用它们

答案 2 :(得分:1)

有两个选项,但最后实际上只有两个主要选项:

  1. 添加on delete cascade意味着删除用户后,与该用户有关的约会也应按照Shadow(第二点)的建议删除。
  2. 添加on delete set null意味着删除用户后,与该用户相关的约会user_id应设置为null(尽管您必须将user_id int(10) UNSIGNED NOT NULL更改为user_id int(10) UNSIGNED DEFAULT NULL

应该选择哪种解决方案?

可以说这是针对诊所的,诊所收到用户的请求,将其从数据库中删除。很好,一直在发生。但是诊所仍然希望将所有约会的历史记录保留在数据库中。在这种情况下,您将使用解决方案编号2。这样,删除用户时,数据库中仍将保留约会,但是user_id将为null,因为该用户不再存在。如果诊所不关心约会的历史记录,那么您可以采用第一解决方案。尽管也可以将用户字段设置为null而不是完全删除该行,但是在这种情况下,您将使用解决方案编号1,因为实际上并不需要完全删除用户记录。

答案 3 :(得分:0)

似乎您的约会表中的外键有开启删除:限制选项。将约束 appointmentments_user_id_foreign 更改为删除时:级联,您应该能够在保留外键的同时删除用户。

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;

答案 4 :(得分:0)

您不能简单地从表用户中删除用户。它被约会表引用为外键索引。我认为删除用户时应该从其他表中删除所有引用,这是公平的。

对于您的方案,您可以改进数据库设计。您可以使约会表中的外键列可选。因此,如果删除了用户,则相应记录的user_id可以设置为NULL。但是,为系统中不再存在的用户存储约会毫无意义。另一种方法是在删除该用户之前,从约会表中删除所有相应的引用,然后从users表中删除引用

答案 5 :(得分:0)

如果您需要临时解决方案,请尝试以下

SET FOREIGN_KEY_CHECKS=OFF; -- to disable foreign key checks
//drop the table and then
SET FOREIGN_KEY_CHECKS=ON; -- to re-enable foreign key checks

答案 6 :(得分:0)

从phpMyAdmin删除时,只需取消选中底部的enable foreign key checks

enter image description here

答案 7 :(得分:0)

我也有同样的例外。通过在父类中更改为CascadeType.DETACH,可以解决此问题。

所以您的情况应该是

public class AppointmentsEntity {

    @JoinColumn(name = "USER_ID", referencedColumnName = "ID")
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
    private User user;

}

顺便说一句:您最好使用单数名称作为数据库表名称。

实际上,这取决于您的数据模型,您应该问您以下问题:子实体是否应该/可以不存在父实体而存在。这回答了您如何对待子实体。