我已经阅读了一些关于Bill Karwin's的single table inheritance个答案,并认为这种方法对我正在考虑的设置有好处:
Playlist
--------
id AUTO_INCREMENT
title
TeamPlaylist
------------
id REFERENCES Playlist.id
teamId REFERENCES Team.id
UserPlaylist
------------
id REFERENCES Playlist.id
userId REFERENCES User.id
PlaylistVideo
-------------
id
playlistId REFERENCES Playlist.id
videoId REFERENCES Video.id
所有CASCADE
选项都设置为DELETE
,这可以在删除Playlist
时正常工作,但是,User
或{{1}会发生什么情况被删除了吗?
即。如果删除Team
,则User
中的行将被删除,但UserPlaylist
和Playlist
中的引用行仍将保留。我考虑将其强制为PlaylistVideo
,但无法知道删除请求是否因为TRIGGER AFTER DELETE
已删除或Playlist
已被删除而发生。
在这种情况下,强制执行诚信的最佳方法是什么?
编辑(提供ERD)
答案 0 :(得分:11)
您可以做的是在Users
和Team
表上实施触发器,每当从以下任何一行删除行时执行这些触发器:
用户表:
DELIMITER $$
CREATE TRIGGER user_playlist_delete
BEFORE DELETE ON User FOR EACH ROW
BEGIN
DELETE a FROM Playlist a
INNER JOIN UserPlaylist b ON a.id = b.id AND b.userId = OLD.id;
END$$
DELIMITER ;
团队表:
DELIMITER $$
CREATE TRIGGER team_playlist_delete
BEFORE DELETE ON Team FOR EACH ROW
BEGIN
DELETE a FROM Playlist a
INNER JOIN TeamPlaylist b ON a.id = b.id AND b.teamId = OLD.id;
END$$
DELIMITER ;
这些触发器将执行的操作是每次从其中一个表中删除记录时,DELETE
操作将使用即将成为Playlists
的{{1}}表自动执行删除(通过内连接)。
我已对此进行了测试,效果很好。
答案 1 :(得分:4)
好的,我在这里看到你想要的......你想要做的就是运行像
这样的查询DELETE FROM playlist
WHERE id
NOT IN (
SELECT id
FROM UserPlayList
UNION
SELECT id
FROM TeamPlayList
)
从用户或团队中删除任何一行后
答案 2 :(得分:3)
在我看来,问题是你的User
和Team
表应该有一个超类型表(例如Party
),而不是播放列表表。
正如您所指出的那样,在播放列表中执行“表继承”会在尝试找出删除内容时受到惩罚。将继承移动到用户/团队级别时,所有这些问题都会消失。
您可以看到this answer for more detail about supertyping/subtyping。
我很抱歉不提供代码,因为我不清楚MySQL的语法。
基本概念是超类型表允许您实现数据库类型的多态。当您正在使用的表需要链接到一组子类型中的任何一个时,您只需将FK指向超类型,这将自动获得所需的“只有一个这些都是“商业约束”。超类型与每个子类型表具有“一对一或一”关系,并且每个子类型表在其PK中使用与超类型表中的PK相同的值。
在您的数据库中,通过只有一个Playlist
表格,其FK为Party (PartyID)
,您可以轻松地在数据库级别强制执行业务规则而无需触发器。
答案 3 :(得分:1)
Zane Bien的回答非常明显&但是我有一个想法,不使用触发器这样做,因为触发器有很多问题。
您使用的是任何编程语言吗?如果是,那么,
使用一个transaction
并制作数据库auto commit false
为播放列表和PlaylistVideo中的引用行编写删除查询。手动,您必须首先使用该引用ID(使用where condition)编写此查询并运行它。
现在为您的主要任务准备另一个查询,即删除用户,UserPlaylist中的行将被自动删除(由于CASCADE DELETE
选项)。现在运行您的第二个查询commit
。
最后进行交易auto commit true
。
它运作成功,希望它会有所帮助。