怎么样删除单表的级联

图片说明

RT 像这么一张表的级联,这时候我删除广东省的话 ,就要把广东省下面的如广州市,荔湾区,越秀区.....这些全删掉,也包括广东下面其他市和县都要删掉,想了很久、如果只是删他的下级的话、还是很容易的、一条SQL就行、但是如果要删三级呢?同事说用递归、想了很久都不会、也搜索了全网、都没有找到、有大佬知道怎么写吗、谢谢。(当然实际上不是这张表,用这张表只是觉得比较经典,大家一看就明白)

下面是一个递归查询某个 area_id 对应的所有子节点的递归函数,它会返回一个数组,然后用 IN 条件来删除,可以试试:

-- 自定义函数查询子节点
delimiter $$
create function `getChildLst`(`rootId` varchar(64)) returns varchar(1000)
BEGIN
  DECLARE sTemp VARCHAR(1000);
  DECLARE sTempChd VARCHAR(1000);
  SET sTemp = '$';
  SET sTempChd = rootId;
  WHILE sTempChd is not null DO
    SET sTemp = concat(sTemp,',',sTempChd);
    SELECT group_concat(area_id) INTO sTempChd FROM t_area
    where FIND_IN_SET(pid,sTempChd)>0;
  END WHILE;
  RETURN sTemp;
END

$$
delimiter ;

说明:这是分组递归查询的函数,参数为当前顶级groupId
使用: select g2.area_id from t_area g2 where find_in_set(g2.area_ID, getChildLst(#{groupId}));
该sql可以返回此groupId和以此groupId为根节点的所有结点

我使用的是mysql,不知道你的可不可以,用我的mysql替换了你的表名,没测试,自己去测试一下可不可以。这里的select @pv := 1 中的1是父id,然后会去递归查询父id下的所有子id,包括子id的子id。

delete from area where area_id in ( select  area_id
        from    (select * from t_area
                 order by area_id, parent_id) m,
                (select @pv := 1 ) initialisation
        where   find_in_set(parent_id, @pv)
        and     length(@pv := concat(@pv, ',', area_id)))

我原本的写法

delete from menu where m_id in ( select  m_id
        from    (select * from menu
                 order by m_fid, m_id) m,
                (select @pv := 1 ) initialisation
        where   find_in_set(m_fid, @pv)
        and     length(@pv := concat(@pv, ',', m_id)))