MySQL 5.6模拟级联删除存储过程:唯一子节点判断逻辑修复
MySQL 5.6 存储过程实现自定义级联删除逻辑
以下是符合需求的存储过程,解决了原有逻辑的判断错误问题:
DELIMITER // CREATE PROCEDURE delete_s_conf_with_cascade(IN p_conf_id INT) BEGIN -- 创建临时表存储当前父节点关联的所有子节点,避免遍历过程中数据变更影响结果 CREATE TEMPORARY TABLE IF NOT EXISTS temp_child_nodes ( child_id INT PRIMARY KEY ); -- 加载当前父节点的所有子节点 INSERT INTO temp_child_nodes (child_id) SELECT child_conf_id FROM s_conf_cpsc WHERE parent_conf_id = p_conf_id; -- 声明游标与变量,遍历子节点 DECLARE done INT DEFAULT FALSE; DECLARE v_child_id INT; DECLARE v_parent_count INT; DECLARE cur_child CURSOR FOR SELECT child_id FROM temp_child_nodes; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur_child; read_loop: LOOP FETCH cur_child INTO v_child_id; IF done THEN LEAVE read_loop; END IF; -- 统计该子节点关联的父节点总数 SELECT COUNT(*) INTO v_parent_count FROM s_conf_cpsc WHERE child_conf_id = v_child_id; IF v_parent_count = 1 THEN -- 唯一子节点:级联删除关联表与子节点本身 DELETE FROM s_conf_at WHERE conf_id = v_child_id; DELETE FROM s_conf_cpsc WHERE child_conf_id = v_child_id; DELETE FROM s_conf WHERE conf_id = v_child_id; ELSE -- 非唯一子节点:仅删除当前父节点与该子节点的关联 DELETE FROM s_conf_cpsc WHERE parent_conf_id = p_conf_id AND child_conf_id = v_child_id; END IF; END LOOP; CLOSE cur_child; -- 删除父节点自身的关联记录与父节点 DELETE FROM s_conf_at WHERE conf_id = p_conf_id; DELETE FROM s_conf WHERE conf_id = p_conf_id; -- 清理临时表 DROP TEMPORARY TABLE IF EXISTS temp_child_nodes; END // DELIMITER ;
核心逻辑说明
- 临时表预加载子节点:先把当前父节点的所有子节点存入临时表,避免游标遍历过程中因删除操作导致的数据集变化,保证遍历的准确性。
- 子节点父节点数量判断:对每个子节点,统计它在
s_conf_cpsc表中关联的父节点总数:- 若总数为1:说明该子节点仅依赖当前要删除的父节点,因此级联删除其关联的
s_conf_at记录、所有s_conf_cpsc关联记录,最后删除子节点本身。 - 若总数大于1:说明子节点还有其他父节点,仅删除当前父节点与该子节点的关联关系。
- 若总数为1:说明该子节点仅依赖当前要删除的父节点,因此级联删除其关联的
- 父节点收尾删除:处理完所有子节点后,删除父节点自身的
s_conf_at记录和s_conf主表记录。
示例场景验证
当删除s_conf ID=1时:
- 临时表加载子节点2和3。
- 处理子节点2:统计父节点总数为1,执行级联删除,移除子节点2的所有关联记录与自身。
- 处理子节点3:统计父节点总数为2(父1和父4),仅删除
s_conf_cpsc中parent_conf_id=1 AND child_conf_id=3的关联行,保留子节点3。 - 最后删除父节点1的关联记录与自身。
完全符合需求中的预期结果。
内容的提问来源于stack exchange,提问作者BlowFish
相关产品推荐
相关产品推荐

