国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

MySQL 實現樹的遍歷詳解及簡單實現示例

2024-07-24 12:52:55
字體:
來源:轉載
供稿:網友

MySQL 實現樹的遍歷

經常在一個表中有父子關系的兩個字段,比如empno與manager,這種結構中需要用到樹的遍歷。在Oracle 中可以使用connect by簡單解決問題,但MySQL 5.1中還不支持(據說已納入to do中),要自己寫過程或函數來實現。

一、建立測試表和數據:

DROP TABLE IF EXISTS `channel`; CREATE TABLE `channel` ( `id` int(11) NOT NULL AUTO_INCREMENT, `cname` varchar(200) DEFAULT NULL, `parent_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=19 DEFAULT CHARSET=utf8; /*Data for the table `channel` */ insert into `channel`(`id`,`cname`,`parent_id`) values (13,'首頁',-1), (14,'TV580',-1), (15,'生活580',-1), (16,'左上幻燈片',13), (17,'幫忙',14), (18,'欄目簡介',17);

 二、利用臨時表和遞歸過程實現樹的遍歷(MySQL的UDF不能遞歸調用):

DELIMITER $$ USE `db1`$$ -- 從某節點向下遍歷子節點 -- 遞歸生成臨時表數據 DROP PROCEDURE IF EXISTS `createChildLst`$$ CREATE PROCEDURE `createChildLst`(IN rootId INT,IN nDepth INT) BEGIN DECLARE done INT DEFAULT 0; DECLARE b INT; DECLARE cur1 CURSOR FOR SELECT id FROM channel WHERE parent_id=rootId; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; SET max_sp_recursion_depth=12; INSERT INTO tmpLst VALUES (NULL,rootId,nDepth); OPEN cur1; FETCH cur1 INTO b; WHILE done=0 DO CALL createChildLst(b,nDepth+1); FETCH cur1 INTO b; END WHILE; CLOSE cur1; END$$ -- 從某節點向上追溯根節點 -- 遞歸生成臨時表數據 DROP PROCEDURE IF EXISTS `createParentLst`$$ CREATE PROCEDURE `createParentLst`(IN rootId INT,IN nDepth INT) BEGIN DECLARE done INT DEFAULT 0; DECLARE b INT; DECLARE cur1 CURSOR FOR SELECT parent_id FROM channel WHERE id=rootId; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; SET max_sp_recursion_depth=12; INSERT INTO tmpLst VALUES (NULL,rootId,nDepth); OPEN cur1; FETCH cur1 INTO b; WHILE done=0 DO CALL createParentLst(b,nDepth+1); FETCH cur1 INTO b; END WHILE; CLOSE cur1; END$$ -- 實現類似Oracle SYS_CONNECT_BY_PATH的功能 -- 遞歸過程輸出某節點id路徑 DROP PROCEDURE IF EXISTS `createPathLst`$$ CREATE PROCEDURE `createPathLst`(IN nid INT,IN delimit VARCHAR(10),INOUT pathstr VARCHAR(1000)) BEGIN DECLARE done INT DEFAULT 0; DECLARE parentid INT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT t.parent_id,CONCAT(CAST(t.parent_id AS CHAR),delimit,pathstr) FROM channel AS t WHERE t.id = nid; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; SET max_sp_recursion_depth=12; OPEN cur1; FETCH cur1 INTO parentid,pathstr; WHILE done=0 DO CALL createPathLst(parentid,delimit,pathstr); FETCH cur1 INTO parentid,pathstr; END WHILE; CLOSE cur1; END$$ -- 遞歸過程輸出某節點name路徑 DROP PROCEDURE IF EXISTS `createPathnameLst`$$ CREATE PROCEDURE `createPathnameLst`(IN nid INT,IN delimit VARCHAR(10),INOUT pathstr VARCHAR(1000)) BEGIN DECLARE done INT DEFAULT 0; DECLARE parentid INT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT t.parent_id,CONCAT(t.cname,delimit,pathstr) FROM channel AS t WHERE t.id = nid; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; SET max_sp_recursion_depth=12; OPEN cur1; FETCH cur1 INTO parentid,pathstr; WHILE done=0 DO CALL createPathnameLst(parentid,delimit,pathstr); FETCH cur1 INTO parentid,pathstr; END WHILE; CLOSE cur1; END$$ -- 調用函數輸出id路徑 DROP FUNCTION IF EXISTS `fn_tree_path`$$ CREATE FUNCTION `fn_tree_path`(nid INT,delimit VARCHAR(10)) RETURNS VARCHAR(2000) CHARSET utf8 BEGIN DECLARE pathid VARCHAR(1000); SET @pathid=CAST(nid AS CHAR); CALL createPathLst(nid,delimit,@pathid); RETURN @pathid; END$$ -- 調用函數輸出name路徑 DROP FUNCTION IF EXISTS `fn_tree_pathname`$$ CREATE FUNCTION `fn_tree_pathname`(nid INT,delimit VARCHAR(10)) RETURNS VARCHAR(2000) CHARSET utf8 BEGIN DECLARE pathid VARCHAR(1000); SET @pathid=''; CALL createPathnameLst(nid,delimit,@pathid); RETURN @pathid; END$$ -- 調用過程輸出子節點 DROP PROCEDURE IF EXISTS `showChildLst`$$ CREATE PROCEDURE `showChildLst`(IN rootId INT) BEGIN DROP TEMPORARY TABLE IF EXISTS tmpLst; CREATE TEMPORARY TABLE IF NOT EXISTS tmpLst (sno INT PRIMARY KEY AUTO_INCREMENT,id INT,depth INT); CALL createChildLst(rootId,0); SELECT channel.id,CONCAT(SPACE(tmpLst.depth*2),'--',channel.cname) NAME,channel.parent_id,tmpLst.depth,fn_tree_path(channel.id,'/') path,fn_tree_pathname(channel.id,'/') pathname FROM tmpLst,channel WHERE tmpLst.id=channel.id ORDER BY tmpLst.sno; END$$ -- 調用過程輸出父節點 DROP PROCEDURE IF EXISTS `showParentLst`$$ CREATE PROCEDURE `showParentLst`(IN rootId INT) BEGIN DROP TEMPORARY TABLE IF EXISTS tmpLst; CREATE TEMPORARY TABLE IF NOT EXISTS tmpLst (sno INT PRIMARY KEY AUTO_INCREMENT,id INT,depth INT); CALL createParentLst(rootId,0); SELECT channel.id,CONCAT(SPACE(tmpLst.depth*2),'--',channel.cname) NAME,channel.parent_id,tmpLst.depth,fn_tree_path(channel.id,'/') path,fn_tree_pathname(channel.id,'/') pathname FROM tmpLst,channel WHERE tmpLst.id=channel.id ORDER BY tmpLst.sno; END$$ DELIMITER ;
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 万宁市| 濮阳市| 信宜市| 百色市| 锡林郭勒盟| 崇阳县| 高台县| 博客| 兴隆县| 凤翔县| 板桥市| 梅河口市| 海丰县| 闻喜县| 茌平县| 盐山县| 丹巴县| SHOW| 桂阳县| 封丘县| 安庆市| 田林县| 玉溪市| 沭阳县| 太仆寺旗| 永寿县| 辉南县| 九龙坡区| 沐川县| 红原县| 萨嘎县| 泸水县| 黄山市| 连州市| 手机| 贵州省| 青海省| 广河县| 绥芬河市| 阜新| 交城县|