注意:此问题似乎是在Cascade delete on many-to-many between same table之前提出的,但没有得到满意的答复。
我有一张桌子,友谊(MemberId,FriendId),允许会员将另一位会员添加为朋友。
CREATE TABLE dbo.FRIENDSHIP(
MemberId INT NOT NULL
, FriendId INT NOT NULL
, DateCreated DATE NOT NULL DEFAULT CURRENT_TIMESTAMP
CONSTRAINT pk_friendship PRIMARY KEY( MemberId, FriendId ),
CONSTRAINT fk_friendship_member FOREIGN KEY( MemberId ) REFERENCES Member( MemberId ) ON DELETE CASCADE,
CONSTRAINT fk_friendship_friend FOREIGN KEY( FriendId ) REFERENCES Member( MemberId ) ON DELETE CASCADE
);
当我运行此脚本时,我看到以下错误:
在表格上引入FOREIGN KEY约束'fk_friendship_friend' 'FRIENDSHIP'可能导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY 约束
显然,每当 成员被删除时,我都希望删除友谊中的记录;我也不希望任何一个字段都可以为空。
经过一番研究,我看到有人建议使用触发器。所以我创建了一个:
CREATE OR ALTER TRIGGER friendship_cascade_delete
ON Member
FOR DELETE
AS
DELETE FROM Friendship
WHERE MemberId IN( SELECT MemberId
FROM deleted )
OR FriendId IN( SELECT MemberId
FROM deleted );
但是当我去删除会员时,我仍然会收到错误:
DELETE语句与REFERENCE约束冲突 “fk_friendship_member”。冲突发生在数据库“CVGS”中, 表“dbo.FRIENDSHIP”,列'MemberId'。
所以它甚至没有达到触发触发器的程度。如果我删除fk_friendship_member和fk_friendship_friend,则触发器正常工作 - 但我不确定是否要删除这些约束。
有没有办法获得我想要的行为,而不会冒失败表中的无效行或不必要的SQL错误?我错过了一些明显的东西吗?
答案 0 :(得分:2)
使用INSTEAD OF触发器,而不是AFTER触发器。 EG
--DROP TABLE IF EXISTS FRIENDSHIP
--DROP TABLE IF EXISTS MEMBER
GO
CREATE TABLE MEMBER(MemberID int primary key);
CREATE TABLE dbo.FRIENDSHIP(
MemberId INT NOT NULL
, FriendId INT NOT NULL
, DateCreated DATE NOT NULL DEFAULT CURRENT_TIMESTAMP
CONSTRAINT pk_friendship PRIMARY KEY( MemberId, FriendId ),
CONSTRAINT ak_friendship UNIQUE( FriendId, MemberId ),
CONSTRAINT fk_friendship_member FOREIGN KEY( MemberId ) REFERENCES Member( MemberId ),
CONSTRAINT fk_friendship_friend FOREIGN KEY( FriendId ) REFERENCES Member( MemberId )
);
GO
CREATE OR ALTER TRIGGER friendship_cascade_delete
ON Member
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Friendship
WHERE MemberId IN( SELECT MemberId FROM deleted );
DELETE FROM Friendship
WHERE FriendId IN( SELECT MemberId FROM deleted );
DELETE FROM MEMBER
WHERE MemberId IN( SELECT MemberId FROM deleted );
END
GO
INSERT INTO MEMBER(MemberID) values (1),(2),(3)
INSERT INTO FRIENDSHIP(MemberID, FriendId) values (1,2), (1,3), (3,2)
go
select *
from FRIENDSHIP
delete from member where MemberID = 1
select *
from FRIENDSHIP