You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite实现反向级联删除:删除全部关联歌曲时自动删除电影条目

在SQLite实现一对多关系的反向级联删除

SQLite本身没有原生支持这种“当子表所有关联记录删除后自动删除父表记录”的反向级联,但用**触发器(Trigger)**就能完美实现这个需求,操作起来和常规级联删除一样简便。下面一步步来:

1. 先确认你的表结构(示例)

假设你的表结构大概是这样的(如果和实际有出入,调整字段名即可):

-- 创建movies表(父表)
CREATE TABLE movies (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL
);

-- 创建songs表(子表),movie_id是关联movies的外键
CREATE TABLE songs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    movie_id INTEGER NOT NULL,
    FOREIGN KEY (movie_id) REFERENCES movies(id) ON DELETE CASCADE -- 可选:如果需要删电影时自动删歌曲,保留这个;不需要就去掉
);

2. 开启SQLite外键约束

SQLite默认是关闭外键约束的,所以先执行这条语句确保外键生效(不然你的外键关联可能不起作用):

PRAGMA foreign_keys = ON;

3. 创建核心触发器

我们需要在songs表上创建一个AFTER DELETE触发器,每次删除歌曲后,检查对应的电影是否还有关联的歌曲。如果没有,就自动删除该电影记录:

CREATE TRIGGER delete_movie_when_no_songs_left
AFTER DELETE ON songs
FOR EACH ROW
BEGIN
    -- 检查当前电影是否还有剩余的歌曲
    SELECT COUNT(*) INTO @song_count FROM songs WHERE movie_id = OLD.movie_id;
    -- 如果歌曲数量为0,删除对应的电影
    IF @song_count = 0 THEN
        DELETE FROM movies WHERE id = OLD.movie_id;
    END IF;
END;

触发器逻辑解释:

  • AFTER DELETE ON songs:指定触发时机是在songs表的记录被删除之后
  • FOR EACH ROW:每删除一条歌曲记录就执行一次触发器逻辑
  • OLD.movie_id:代表被删除的那条歌曲记录关联的电影ID
  • 先统计该电影剩余的歌曲数量,若为0则删除对应的电影记录

4. 测试验证

举个简单的测试流程:

  1. 插入一部电影和两首歌曲:
INSERT INTO movies (title) VALUES ('肖申克的救赎');
INSERT INTO songs (name, movie_id) VALUES ('主题音乐', 1), ('片尾插曲', 1);
  1. 删除其中一首歌曲:
DELETE FROM songs WHERE name = '主题音乐';

此时songs表还剩一首关联歌曲,movies表的记录会保留。
3. 删除最后一首歌曲:

DELETE FROM songs WHERE name = '片尾插曲';

此时触发器会检测到该电影没有剩余歌曲,自动删除movies表中对应的记录。

补充说明

  • 如果是批量删除同一电影的所有歌曲,触发器会在每条记录删除后执行检查,最后一次检查时歌曲数量为0,同样会触发电影删除,逻辑依然有效。
  • 如果你不需要“删电影自动删歌曲”的正向级联,可以去掉songs表外键定义里的ON DELETE CASCADE,不影响反向触发器的功能。

内容的提问来源于stack exchange,提问作者Nandu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:57:49