简体   繁体   English

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

[英]Cannot delete or update a parent row: a foreign key constraint fails - MYSQL

I'm getting this error when trying to delete a user from the database, I know it's doing this because the user I'm trying to delete is a foreign key in the appointments table, but I don't know how to correct it or where I have gone wrong.我在尝试从数据库中删除用户时遇到此错误,我知道这样做是因为我要删除的用户是约会表中的外键,但我不知道如何更正它或我哪里出错了。 Not sure if it changes anything but just incase I created the tables using laravel不确定它是否有任何改变,只是以防万一我使用 laravel 创建了表

Users table用户表

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;

Appointments table约会表

 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`);

You get this error because the user you would like to delete has associated records within the appointments table.您收到此错误是因为您要删除的用户在appointments表中具有关联的记录。 You have 2 options:您有 2 个选择:

  1. Delete the associated records from the appointments table first with a separate delete statement.首先使用单独的delete语句从约会表中删除关联的记录。

  2. Add on delete cascade option to appointments_user_id_foreign foreign key.删除级联选项添加到appointments_user_id_foreign _用户appointments_user_id_foreign外键。 This option will automatically remove any associated records from the appointments table for the user to be deleted when you delete the user's record.当您删除用户的记录时,此选项将自动从appointments表中删除所有关联记录,以便删除用户。

The modified fk statement looks like as follows:修改后的 fk 语句如下所示:

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

The solution proposed by @Nebster technically removes the error message, but also enables having orphan records within the appointments table - appointments related to deleted users. @Nebster 提出的解决方案在技术上删除了错误消息,但也允许在appointments表中拥有孤立记录 - 与已删除用户相关的appointments Therefore, removing the foreign key is not a sensible option in my opinion.因此,在我看来,删除外键不是一个明智的选择。

SET FOREIGN_KEY_CHECKS=0; – to disable them – 禁用它们

SET FOREIGN_KEY_CHECKS=1; – to re-enable them – 重新启用它们

When you're deleting from phpMyAdmin, just uncheck enable foreign key checks at bottom当您从 phpMyAdmin 中删除时,只需取消选中底部的enable foreign key checks

在此处输入图片说明

Seems like your Foreign key in Appointments table has On delete: Restrict option.似乎您在约会表中的外键具有删除时:限制选项。 Change the Constraint appointments_user_id_foreign to On delete: Cascade and you should be able to delete Users while preserving Foreign key.将约束约会_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;

You cannot simply delete a user from table users.您不能简单地从表 users 中删除用户。 It is being referenced by the appointments table as foreign key index.它被约会表引用为外键索引。 I think it is fair enough that when a user is deleted all his references should be deleted from other tables.我认为当一个用户被删除时,他的所有引用都应该从其他表中删除是很公平的。

For your scenario, you can improve your database design.对于您的场景,您可以改进您的数据库设计。 You can make the foreign key column in appointments table optional.您可以将约会表中的外键列设为可选。 So if user is deleted the corresponding record's user_id can be set as NULL.所以如果用户被删除,相应记录的user_id 可以设置为NULL。 But it is meaningless to store appointments for those users who no longer exist in the system.但是为那些不再存在于系统中的用户存储约会是没有意义的。 Another approach be to before deleting that user, delete all his corresponding references from appointments table and then delete the reference from users table另一种方法是在删除该用户之前,从约会表中删除所有对应的引用,然后从用户表中删除引用

If you want a temporary solution, then try the following如果您想要临时解决方案,请尝试以下操作

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

There are a couple of options, but in the end there are really only two main options:有几个选项,但最终只有两个主要选项:

  1. Add on delete cascade meaning that when user is deleted appointments relating to that user should also be deleted as suggested by Shadow (point number two)添加on delete cascade意味着当用户被删除时,与该用户相关的约会也应该按照Shadow 的建议删除(第二点)
  2. Add on delete set null meaning that when user is deleted appointments user_id relating to that user should be set to null (though you will have to change user_id int(10) UNSIGNED NOT NULL to user_id int(10) UNSIGNED DEFAULT NULL添加on delete set null意味着当用户被删除时,与该用户相关的约会 user_id 应设置为 null(尽管您必须将user_id int(10) UNSIGNED NOT NULL更改为user_id int(10) UNSIGNED DEFAULT NULL

Which solution should one choose?应该选择哪种解决方案?

Lets say this is for a clinic and the clinic gets a request from a user to delete him from the db.假设这是一个诊所,诊所收到用户的请求,要求将他从数据库中删除。 That is fine, happens all the time.那很好,一直发生。 But the clinic still wants to keep history of all the appointments in the db.但是诊所仍然希望保留数据库中所有约会的历史记录。 In this case you would go with solution number 2. In this way when user is deleted you will still have the appointment in the db, but the user_id will be null as that user does not exist anymore.在这种情况下,您将使用解决方案编号 2。这样,当用户被删除时,您仍将在数据库中拥有约会,但 user_id 将为空,因为该用户不再存在。 If the clinic does not care about history of the appointments then you can go with solution number one.如果诊所不关心约会的历史,那么您可以使用第一解决方案。 Though one can also set user fields to null instead of deleting the row completely, and in that case you would go with solution number one as one would never actually need to fully delete a user record.虽然也可以将用户字段设置为 null 而不是完全删除行,在这种情况下,您将使用第一号解决方案,因为实际上永远不需要完全删除用户记录。

I had the same exception.我有同样的例外。 I could solve the issue with changing to CascadeType.DETACH in my parent class.我可以通过在我的父类中更改为CascadeType.DETACH来解决这个问题。

So in your case it would be所以在你的情况下它会是

public class AppointmentsEntity {

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

}

Btw: You better use singular names for database table names.顺便说一句:您最好对数据库表名使用单数名称。

Actually, it depends on your Data-Model and you should ask you the question whether the child entity should/can exist without the parent.实际上,这取决于您的数据模型,您应该问您子实体是否应该/可以在没有父实体的情况下存在的问题。 This answers how you have the treat the child entity.这回答了您如何对待子实体。

I found a solution for that issue with Typeorm MysQL: You can set 'createForeignKeyConstraints' to FALSE.我通过 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