没有相关项目时,在多对多关系中级联删除

时间:2018-11-25 17:16:08

标签: sql sqlite triggers cascading-deletes

我有一个大致如下所示的模式:

CREATE TABLE posts(
    id INTEGER PRIMARY KEY,
    txt TEXT,
);
CREATE TABLE tags(
    id INTEGER PRIMARY KEY,
    tag TEXT
);

CREATE TABLE posts_tags(
    id INTEGER PRIMARY KEY,
    tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE
);

我想删除具有指定ID的帖子,但我也想删除与该帖子相关的所有标签,这些标签没有其他任何关联的帖子。

因此,假设只有一篇关于编程的文章,那么删除该文章时,"programming"标签应该消失了。但是,如果有多个关于sports的帖子,则删除一个帖子应保持标记完整,并且仅从posts_tags表中删除适当的关系(我假设这是由层叠自动完成的)。

我知道我可以选择所有标签,使用我选择的编程语言在它们之间循环,验证它们是否只有一个关联的帖子并删除它们,但是我正在寻找一种更简单的可与SQL配合使用的解决方案。

我将需要对多个表执行此操作,因此多次复制/粘贴代码效率低下。

有没有办法做到这一点?

我研究了很多到很多的关系并删除了这些关系,但发现的只是提及使用触发器。但是,我对应该使用哪个触发器并没有真正的了解。

1 个答案:

答案 0 :(得分:0)

该模式似乎是您的问题,基本上 post_tags 表似乎毫无用处,但是具有用于引用/关联/映射该帖子的列,它成为非常有用的功能映射/参考/关系表。

我认为您想要一个类似:-

的架构
CREATE TABLE posts(
    id INTEGER PRIMARY KEY,
    txt TEXT,
);
CREATE TABLE tags(
    id INTEGER PRIMARY KEY,
    tag TEXT
);

CREATE TABLE posts_tags(
    id INTEGER PRIMARY KEY,
    tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
    post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE
);

然后您将标签绑定到帖子,如果删除了帖子,则该帖子的所有行将被删除,其他使用该标签的帖子将保留。如果删除了标签,则使用该标签的所有行都将被删除。

P.S。您可以删除id列,然后希望将PRIMARY KEY作为两个列的组合,从而消除无用/混乱的重复行。

所以也许(与其他拖曳桌一起使用):-

CREATE TABLE posts_tags(
    tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
    post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
    PRIMARY KEY (tag_id,post_id)
);

或者如果sqlite版本支持(3.8.2 +):-

CREATE TABLE  posts_tags(
        tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
        post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
        PRIMARY KEY (tag_id,post_id) 
        )
    WITHOUT ROWID
    ;