繁体   English   中英

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

[英]Cannot delete or update a parent row: a foreign key constraint fails - 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`);

您收到此错误是因为您要删除的用户在appointments表中具有关联的记录。 您有 2 个选择:

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

  2. 删除级联选项添加到appointments_user_id_foreign _用户appointments_user_id_foreign外键。 当您删除用户的记录时,此选项将自动从appointments表中删除所有关联记录,以便删除用户。

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

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

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

SET FOREIGN_KEY_CHECKS=0; – 禁用它们

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

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

在此处输入图片说明

似乎您在约会表中的外键具有删除时:限制选项。 将约束约会_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;

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

对于您的场景,您可以改进您的数据库设计。 您可以将约会表中的外键列设为可选。 所以如果用户被删除,相应记录的user_id 可以设置为NULL。 但是为那些不再存在于系统中的用户存储约会是没有意义的。 另一种方法是在删除该用户之前,从约会表中删除所有对应的引用,然后从用户表中删除引用

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

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

有几个选项,但最终只有两个主要选项:

  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 而不是完全删除行,在这种情况下,您将使用第一号解决方案,因为实际上永远不需要完全删除用户记录。

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

所以在你的情况下它会是

public class AppointmentsEntity {

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

}

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

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

我通过 Typeorm MysQL 找到了该问题的解决方案:您可以将“createForeignKeyConstraints”设置为 FALSE。

@OneToOne(type => Task, { 
  cascade: true, onDelete: 'CASCADE', createForeignKeyConstraints: false 
})
@JoinColumn()
taskDetails: Task
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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM