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 对同一张表之间的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章
1) 不能在 DELETE SET NULL 或 ON DELETE CASCADE 上创建外键 2) 不能在 DELETE CASCADE 上创建外键