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

MySQL触发器嵌套问题:删除父表仅需回收站单条记录

问题分析

当前删除父表时,父表触发器会批量更新所有关联子表的is_deleted字段,每一条子表的更新都会触发子表触发器向sn_recycle插入一条子表记录,再加上父表自身插入的记录,导致回收站生成多条冗余记录。核心需求是:父表删除时仅保留父表对应的回收站记录,子表仅在单独被删除时生成回收站记录。

解决方案

通过会话变量控制子表触发器的执行逻辑,区分父表触发的批量更新和子表单独删除的场景:

1. 修改父表触发器

在批量更新子表前设置会话变量,标记当前操作来自父表删除触发,操作完成后重置变量:

DROP TRIGGER IF EXISTS `after_recorditems_update`;
CREATE DEFINER=`root`@`localhost` TRIGGER `after_recorditems_update` 
AFTER UPDATE ON `sn_recorditems` 
FOR EACH ROW BEGIN 
    -- 标记当前为父表触发的子表批量更新
    SET @PARENT_DELETE_TRIGGER = 1;
    
    -- 更新关联子表的删除状态
    UPDATE sn_recordlog SET is_deleted = new.is_deleted WHERE new.id = `recordid`; 
    
    -- 插入父表回收站记录,关联所有子表的log_id
    INSERT INTO sn_recycle(deleted_at,recorditem_id,log_id,from_table_name) 
    VALUES(
        new.time,
        new.id,
        (SELECT GROUP_CONCAT(sn_recordlog.id SEPARATOR ', ') FROM sn_recordlog WHERE new.time = sn_recordlog.time),
        'sn_recorditems'
    ); 
    
    -- 重置会话变量,不影响后续操作
    SET @PARENT_DELETE_TRIGGER = NULL;
END

2. 修改子表触发器

增加会话变量判断,仅当不是父表触发的更新时,才插入子表的回收站记录:

DROP TRIGGER IF EXISTS `after_recordlog_update`;
CREATE DEFINER=`root`@`localhost` TRIGGER `after_recordlog_update` 
AFTER UPDATE ON `sn_recordlog` 
FOR EACH ROW BEGIN 
    -- 仅在单独删除子表时执行插入
    IF @PARENT_DELETE_TRIGGER IS NULL THEN
        INSERT INTO sn_recycle(deleted_at,recorditem_id,log_id,from_table)
        VALUES(new.time, new.recordid, new.id, 'sn_recordlog');
    END IF;
END
验证逻辑
  • 单独删除子表:手动设置子表is_deleted=1时,会话变量不存在,子表触发器正常插入回收站记录。
  • 删除父表:父表触发器先标记会话变量,批量更新子表时,子表触发器检测到变量存在,跳过插入操作,仅父表触发器插入一条关联所有子表的回收站记录,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:00:53