如何在单表继承上强制引用完整性?

Mat*_*ick 13 mysql referential-integrity single-table-inheritance polymorphic-associations cascading-deletes

我已经阅读了Bill Karwin关于单表继承的一些答案,并认为这种方法对我正在考虑的设置有好处:

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
Run Code Online (Sandbox Code Playgroud)

所有CASCADE选项都设置DELETE为在Playlist删除a时正常工作,但是,如果删除UserTeam删除会发生什么?

即.如果User被删除,在行UserPlaylist会被删除,但被引用的行中Playlist,并PlaylistVideo仍将保留.我考虑过强制执行此操作,TRIGGER AFTER DELETE但无法知道删除请求是否因为Playlist已删除或删除而导致User.

在这种情况下,强制执行诚信的最佳方法是什么?

编辑(提供ERD)

在此输入图像描述

Zan*_*ien 11

您可以做的是在您UsersTeam表上执行触发器,每当从以下任何一行删除行时执行触发器:

用户表:

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 ;
Run Code Online (Sandbox Code Playgroud)

团队表:

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 ;
Run Code Online (Sandbox Code Playgroud)

这些触发器将执行的操作是每次从其中一个表中删除记录时,DELETE操作将Playlists使用id即将删除的操作(通过内部联接)自动执行.

我测试了这个并且效果很好.


Eri*_*ikE 3

在我看来,问题在于您的UserTeam表应该具有超类型表(例如Party),而不是播放列表表。

正如您所指出的,在尝试找出要删除的内容时,在播放列表上执行“表继承”会带来惩罚。当您将继承提升到用户/团队级别时,所有这些问题都会消失。

您可以查看此答案以获取有关 supertyping/subtyping 的更多详细信息

很抱歉没有提供代码,因为我不记得 MySQL 语法。

基本概念是超类型表允许您实现数据库类型的多态性。当您正在使用的表需要链接到一组子类型中的任何一个时,您只需使 FK 指向超类型即可,这会自动为您提供所需的“一次仅其中一个”业务约束。超类型与每个子类型表具有“一对零或一”关系,并且每个子类型表在其 PK 中使用与来自超类型表的 PK 相同的值。

在您的数据库中,通过只有一个Playlist带有 FK to 的表Party (PartyID),您可以轻松地在数据库级别强制执行业务规则,而无需触发器。