我在尝试从数据库中删除用户时遇到此错误,我知道这样做是因为我正在尝试删除的用户是约会表中的外键,但我不知道如何纠正它或我出错的地方。不确定它是否会改变,只是因为我使用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`);
答案 0 :(得分:13)
您收到此错误,因为您要删除的用户在appointments
表中包含相关记录。您有两个选择:
首先使用单独的delete
语句从约会表中删除关联的记录。
将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
表中使用孤立记录 - 与已删除用户相关的约会。因此,在我看来,删除外键不是一个明智的选择。
答案 1 :(得分:4)
SET FOREIGN_KEY_CHECKS=0;
- 禁用它们
SET FOREIGN_KEY_CHECKS=1;
- 重新启用它们
答案 2 :(得分:1)
有两个选项,但最后实际上只有两个主要选项:
on delete cascade
意味着删除用户后,与该用户有关的约会也应按照Shadow(第二点)的建议删除。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)
答案 7 :(得分:0)
我也有同样的例外。通过在父类中更改为CascadeType.DETACH
,可以解决此问题。
所以您的情况应该是
public class AppointmentsEntity {
@JoinColumn(name = "USER_ID", referencedColumnName = "ID")
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH)
private User user;
}
顺便说一句:您最好使用单数名称作为数据库表名称。
实际上,这取决于您的数据模型,您应该问您以下问题:子实体是否应该/可以不存在父实体而存在。这回答了您如何对待子实体。