ft+2
于是我们就可以整理出在原有叶子中插入child的公式:
第一步:选取要被插入new child的外面这个圆的lft的值
第二步:原有的数据中所有的rgt如果>第一步中得到的lft的值,那么全部+2
第三步:原有的数据中所有的lft如果>第一步中得到的lft的值,那么全部+2
第四步:将插入的节点的lft与rgt的设计,新节点的lft =第一步中的lft+1,新节点的rgt=第一步中
的lft+2
来看一个具体的例子:
我们要在“报表查询”即menu_id=’101’ 中插入一个新的菜单,叫“周报”,下面是按照上面四步算法的相关SQL语句:
第一步
SELECT lftFROM t_sys_menuwhere menu_id='101';
第二步:这一步我们得到的值为:2
UPDATE t_sys_menuSET rgt = rgt +2WHERE rgt >2;
第三步:
UPDATE t_sys_menuSET lft = lft +2WHERE lft >2;
第四步:
INSERTINTO t_sys_menu(menu_id, menu_descr, menu_url, lft, rgt)VALUES('113','周报','周报的url', (2+1), (2 +2));
插完后我们运行查询SQL:
SELECT
node.menu_id menuId,
node.menu_descr menuDescr,
node.lft,
node.rgt,
node.menu_url menuUrl,
(COUNT(parent.menu_id)-1) menuLevel,
node.menu_pid pid
FROM t_sys_menu node,
t_sys_menu parent
WHERE
node.lft BETWEEN parent.lft AND parent.rgt
AND node.menu_descr!='菜单'
GROUPBY node.menu_id,node.menu_descr,node.lft,node.rgt,node.menu_url,node.menu_pid
ORDERBY node.lft
Look, 数据正确无误,我们来看整个t_sys_menu表里的数据:
Look,整个最外层的“圆”,右边界增加了2,从原有的24变成了26。
4.3 如何插入一个新的节点
上面讲的是在原有的节点中插入一个子节点,现在来讲,如何插入一个新的节点,比如说:
我们现在有:报表查询,系统管理两大菜单,我们还想加一个菜单:保单审核,怎么来做?
我们把4.2节中“如何在现有节点中插入新的子节点”里四步公式,稍稍改动一下
第一步:选取要被插入新的节点左边节点的rgt的值
第二步:原有的数据中所有的rgt如果>第一步中得到的rgt的值,那么全部+2
第三步:原有的数据中所有的lft如果>第一步中得到的rgt的值,那么全部+2
第四步:将插入的节点的lft与rgt的设计,新节点的lft =第一步中的rgt+1,新节点的rgt=第一步中
的rgt+2
下面来看我们在“报表查询”与“系统管理”中间,插入一个菜单叫“保单审核”。
第一步
SELECT rgtFROM t_sys_menuwhere menu_id='101';
这一步我们得到的值为:11
第二步:
UPDATE t_sys_menuSET rgt = rgt +2WHERE rgt >11;
第三步:
UPDATE t_sys_menuSET lft = lft +2WHERE lft >11;
第四步:
INSERTINTO t_sys_menu(menu_id, menu_descr, menu_url, lft, rgt)VALUES('114','保单审核','', (11+1), (11 +2));
运行下面的SQL语句我们来检查一下插入的效果:
SELECT
node.menu_id menuId,
node.menu_descr menuDescr,
node.lft,
node.rgt,
node.menu_url menuUrl,
(COUNT(parent.menu_id)-1) menuLevel,
node.menu_pid pid
FROM t_sys_menu node,
t_sys_menu parent
WHERE
node.lftBETWEEN parent.lftAND parent.rgt
AND node.menu_descr!='菜单'
GROUPBY node.menu_id,node.menu_descr,node.lft,node.rgt,node.menu_url,node.menu_pid
ORDERBY node.lft
怎么样,结果对了吧,呵呵!
看看整个菜单的右边界吧,从原来的26变成了28了,是不是哦?
4.4 如何删除一个节点
来看公式
第一步:选取要被删除的菜单的lft的值,rgt的值,以及宽度(width=rgt-lft+1);
第二步:删除所有的位于第一步中得到的lft与rgt之间的节点;
第三步:将所有的右边界大于第一步中得到的rgt的所有节点的rgt的值减去第一步中得到的width
第四步:将所有的左边界大于第一步中得到的rgt的所有节点的lft的值减去第一步中得到的width
来看实际例子,我们有下面这样的数据:
我们想将menu_id=114的保单审核删除,当然,这是一个父节点,如果把它删了,其子节点115即手工审核也必须被一起删除,要不然它就成为脏数据了是不是?套用上述四步公式:
第一步:
SELECT lft, rgt, (rgt - lft +1) widthFROM t_sys_menuWHERE menu_id ='114'
第二步:
DELETEFROM t_sys_menuWHERE lftBETWEEN12AND15
第三步:
UPDATE t_sys_menuSET rgt = rgt -4WHERE rgt >15
第四部:
UPDATE t_sys_menuSET lft = lft -4WHERE lft >15
全部步骤完成后,我们来运行检验的SQL:
SELECT
node.menu_id menuId,
node.menu_descr menuDescr,
node.lft,
node.rgt,
node.menu_url menuUrl,
(COUNT(parent.menu_id)-1) menuLevel,
node.menu_pid pid
FROM t_sys_menu node,
t_sys_menu parent
WHERE
node.lftBETWEEN parent.lftAND parent.rgt
AND node.menu_descr!='菜单'
GROUPBY node.menu_id,node.menu_descr,node.lft,node.rgt,no