ON CASCADE DELETE 对同一张表之间的多对多关系

Posted

技术标签:

【中文标题】ON CASCADE DELETE 对同一张表之间的多对多关系【英文标题】:ON CASCADE DELETE on a many to many relationship between the same table 【发布时间】:2018-12-01 16:47:54 【问题描述】:

在我的 SQL 数据库中,我为 M-to-M 关系创建了以下表格

User
ID username userpass

User_Relationship
ID user1ID, user2ID

所以 user1ID 是用户 ID 的外键,对于 user2ID 也是如此。我想要做的是,当我从 ID 为 1 的用户中删除一行时,我还想从 User_Relationship 中删除 user1ID 或 user2ID 为 1 的行,但仅此而已,而不是任何其他行。我已经尝试将 ON CASCADE DELETE 设置为 User_Relationship 表中的两个外键,但收到以下错误:

Introducing FOREIGN KEY constraint on table 'User_Relationship' may cause
cycles or multiple cascade paths

那么,如何从 User 表中删除一个值并删除 User_Relationship 中 user1ID 或 user2ID 的外键设置为用户 ID 的每一行?我正在使用 SQL 管理工作室。谢谢。

【问题讨论】:

一种方法是使用触发器,但我不确定是否有更好的选择。 好吧,我做了一个触发器,它起作用了。不是直接的方式,但它仍然可以完成工作。谢谢。 触发器是最好的方法。您可以根据需要对其进行自定义,并且它仍然像级联删除一样被数据库触发。 我个人讨厌触发器并尽可能避免它们。外键级联也是如此。我将明确执行删除User_Relationship 中记录的查询。或者创建一个存储过程。 @BartHofland 你讨厌触发器但使用存储过程?有趣! 【参考方案1】:

我得到了这个工作:表:A=> PK a_id B=> PK b_id A_B =>

CREATE TABLE [dbo].[A_B](
    [a_id] [int] NOT NULL,
    [b_id] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_A_B] PRIMARY KEY CLUSTERED 
(
    [a_id] ASC,
    [b_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[A_B]  WITH CHECK ADD  CONSTRAINT [FK_a_b_b] FOREIGN KEY([A_Id])
REFERENCES [dbo].[A] ([a_id]) on delete cascade
GO

ALTER TABLE [dbo].[A_B] CHECK CONSTRAINT [FK_a_b_b]
GO

ALTER TABLE [dbo].[A_B]  WITH CHECK ADD  CONSTRAINT [FK_a_b_a] FOREIGN KEY([B_Id])
REFERENCES [dbo].[B] ([b_Id]) on delete cascade
GO

ALTER TABLE [dbo].[A_B] 检查约束 [FK_a_b_a] 去吧

【讨论】:

【参考方案2】:

根据这些文章:

Solving the SQL Server Multiple Cascade Path Issue with a Trigger SQL Server CREATE TRIGGER

您应该使用trigger 并删除on delete cascade 以达到预期的效果。

您的问题的示例解决方案如下所示:

CREATE TABLE User ( -- consider changing name of this table to `Users` instead of `User`
    ID INT PRIMARY KEY IDENTITY(1,1), -- probably `Id` would be better name instead of `ID` because `ID` looks like SQL reserved keyword
    username VARCHAR(MAX), 
    userpass VARCHAR(MAX) -- please consider hash passwords before saving to database
)

CREATE TABLE User_Relationship ( -- here `User_Relationships` instead of `User_Relationship` as well
    user1ID INT NOT NULL,
    user2ID INT NOT NULL,
    CONSTRAINT ID PRIMARY KEY (user1ID, user2ID), -- here `Id` instead of `ID` as well
    CONSTRAINT fk_user1ID FOREIGN KEY (user1ID) REFERENCES User (ID),
    CONSTRAINT fk_user2ID FOREIGN KEY (user2ID) REFERENCES User (ID)
)

CREATE TRIGGER Delete_User_Relationships
   ON User
   INSTEAD OF DELETE
AS 
BEGIN
 SET NOCOUNT ON;
 DELETE FROM User_Relationship WHERE (user1ID IN (SELECT ID FROM DELETED)) OR (user2ID IN (SELECT ID FROM DELETED))
 DELETE FROM User WHERE ID IN (SELECT ID FROM DELETED)
END

【讨论】:

以上是关于ON CASCADE DELETE 对同一张表之间的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章

Django -- 多表操作

1) 不能在 DELETE SET NULL 或 ON DELETE CASCADE 上创建外键 2) 不能在 DELETE CASCADE 上创建外键

为啥我的模型的“on_delete=models.CASCADE”不生成级联外键约束?

on_delete=models.CASCADE级联删除

on_delete=models.CASCADE级联删除

如何在 JPA 中获取外键引用以具有“ON UPDATE CASCADE ON DELETE CASCADE”功能?