Chinaunix首页 | 论坛 | 博客
  • 博客访问: 39592
  • 博文数量: 13
  • 博客积分: 290
  • 博客等级: 二等列兵
  • 技术积分: 145
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-14 11:27
文章分类

全部博文(13)

文章存档

2012年(13)

我的朋友

分类: Mysql/postgreSQL

2012-10-31 16:33:33

今天碰到一个同事需要实现一个递归的方法,用来比较好的实现子节点的查询。
如图,画的太丑,凑合看


查找1的子节点只需要输入 lft between 1 and 16 即可找到他下面所有的子节点

原始数据如下:

点击(此处)折叠或打开

  1. DROP TABLE IF EXISTS `ecms_node`;
  2. CREATE TABLE `ecms_node` (
  3.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  4.   `name` char(30) DEFAULT '',
  5.   `title` char(50) DEFAULT '',
  6.   `level` tinyint(5) unsigned DEFAULT '1' COMMENT '级别:1应用,2:模块,3:方法',
  7.   `status` tinyint(1) unsigned DEFAULT '0' COMMENT '状态:1启用,0停用',
  8.   `pid` tinyint(11) unsigned DEFAULT '1' COMMENT '父id',
  9.   `super` tinyint(1) unsigned DEFAULT '0' COMMENT '是否检查权限,0检查,1不检查',
  10.   `remark` varchar(1000) DEFAULT '',
  11.   `lft` int(11) DEFAULT NULL,
  12.   `rgt` int(10) unsigned DEFAULT NULL,
  13.   PRIMARY KEY (`id`)
  14. ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;



  15. INSERT INTO `ecms_node` VALUES ('1', 'Admin', '后台', '1', '1', '0', '0', '后台管理', '1', null);
  16. INSERT INTO `ecms_node` VALUES ('2', 'Index', '后台', '2', '1', '1', '1', '', null, null);
  17. INSERT INTO `ecms_node` VALUES ('3', 'index', '后台首页', '3', '1', '2', '1', '', null, null);
  18. INSERT INTO `ecms_node` VALUES ('4', 'nav', '导航', '3', '1', '2', '1', '', null, null);
  19. INSERT INTO `ecms_node` VALUES ('5', 'top', '框架顶部', '3', '1', '2', '1', '', null, null);
  20. INSERT INTO `ecms_node` VALUES ('6', 'welcome', '欢迎页', '3', '1', '2', '1', '', null, null);
  21. INSERT INTO `ecms_node` VALUES ('7', 'Sys', '网站设置', '2', '1', '1', '0', '', null, null);
  22. INSERT INTO `ecms_node` VALUES ('8', 'node', '节点管理', '3', '1', '7', '0', '', null, null);
  23. INSERT INTO `ecms_node` VALUES ('9', 'nav', '导航', '3', '1', '7', '0', '', null, null);
  24. INSERT INTO `ecms_node` VALUES ('10', 'User', '用户', '2', '1', '1', '0', '', null, null);
  25. INSERT INTO `ecms_node` VALUES ('11', 'role', '角色', '3', '1', '10', '0', '', null, null);
  26. INSERT INTO `ecms_node` VALUES ('14', 'Contents', '前台', '1', '1', '0', '0', '前台内容', null, null);
  27. INSERT INTO `ecms_node` VALUES ('15', 'index', '用户', '3', '1', '10', '0', '网站用户', null, null);
  28. INSERT INTO `ecms_node` VALUES ('16', 'edituser', '编辑用户', '4', '1', '10', '0', '修改用户信息', null, null);
  29. INSERT INTO `ecms_node` VALUES ('17', 'userrole', '用户角色', '4', '1', '10', '0', '设置用户角色', null, null);
  30. INSERT INTO `ecms_node` VALUES ('18', 'editrole', '编辑角色', '4', '1', '10', '0', '编辑角色信息', null, null);
  31. INSERT INTO `ecms_node` VALUES ('19', 'rolenode', '角色权限', '4', '1', '10', '0', '设置角色权限', null, null);
  32. INSERT INTO `ecms_node` VALUES ('20', 'editnode', '编辑节点', '4', '1', '7', '0', '编辑节点信息', null, null);
思路是从开始的节点往下找,找到最后一个之后再返回倒数第2层再往下找,一直重复,直到完结



点击(此处)折叠或打开

  1. DROP procedure IF EXISTS test_lft;
  2. create procedure test_lft(
  3.  f_pid INT,
  4.  f_left INT,
  5.  OUT f_id int,
  6.  out f_rowid int
  7. )
  8. BEGIN
  9.   declare _rowid int;
  10.   declare _tid int;
  11.   declare _sid int DEFAULT 0;

  12.   SET _rowid=f_left+1;
  13.  
  14.   SELECT min(id) into _tid FROM ecms_node WHERE pid=f_pid and lft=0;
  15.    
  16.   IF _tid>0 THEN

  17.         WHILE _tid > 0 DO

  18.             UPDATE ecms_node SET lft=_rowid WHERE id=_tid and lft=0 ;

  19.             SET _sid=_tid;

  20.             SELECT min(id) into _tid FROM ecms_node WHERE pid=_tid and lft=0 ;

  21.             SET _rowid=_rowid+1;
  22.          END WHILE;
  23.         
  24.     UPDATE ecms_node SET rgt=_rowid WHERE id=_sid;
  25.     SELECT pid,rgt into f_id,f_rowid FROM ecms_node WHERE id=_sid;

  26.     ELSE
  27.      UPDATE ecms_node SET rgt=_rowid WHERE id=f_pid;
  28.      SELECT pid,rgt into f_id,f_rowid FROM ecms_node WHERE id=f_pid;
  29.     END IF;
  30. END;

  31. DROP procedure IF EXISTS test_row;
  32. create procedure test_row(
  33.  f_pid INT,
  34.  f_left INT
  35. )
  36. BEGIN
  37.   declare _row int default 0;

  38.   UPDATE ecms_node SET lft=0 WHERE lft>f_left or lft is null;
  39.   UPDATE ecms_node SET rgt=0 WHERE rgt>f_left or rgt is null;
  40.   UPDATE ecms_node SET lft=f_left where id=f_pid;


  41.   CALL test_lft(f_pid,f_left,@a,@b);

  42.   SELECT count(*) into _row FROM ecms_node where lft=0 or rgt=0;

  43.   WHILE _row >0 DO
  44.     SET f_pid=@a,f_left=@b;
  45.     CALL test_lft(f_pid,f_left,@a,@b);
  46.     SELECT count(*) into _row FROM ecms_node where lft=0 or rgt=0;
  47.   END WHILE;

  48. END;

  49. CALL test_row(1,1);

这种存储的好处在于能够很快的找出节点下面的子节点,缺点在于如果有节点变动,需要更新后面所有的节点。



阅读(1785) | 评论(0) | 转发(0) |
0

上一篇:ORACLE rman入门篇

下一篇:ORACLE -临时表

给主人留下些什么吧!~~