最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL 實現(xiàn)樹的遍歷詳解及簡單實現(xiàn)示例

 更新時間:2017年01月05日 08:53:23   投稿:lqh  
這篇文章主要介紹了MySQL 實現(xiàn)樹的遍歷詳解及簡單實現(xiàn)示例的相關資料,這里提供了示例代碼及測試結果,需要的朋友可以參考下

MySQL 實現(xiàn)樹的遍歷

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

一、建立測試表和數(shù)據(jù):


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); 

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


DELIMITER $$ 
 
USE `db1`$$ 
 
 
-- 從某節(jié)點向下遍歷子節(jié)點 
-- 遞歸生成臨時表數(shù)據(jù) 
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$$ 
 
 
-- 從某節(jié)點向上追溯根節(jié)點 
-- 遞歸生成臨時表數(shù)據(jù) 
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$$ 
 
 
-- 實現(xiàn)類似Oracle SYS_CONNECT_BY_PATH的功能 
-- 遞歸過程輸出某節(jié)點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$$ 
 
 
-- 遞歸過程輸出某節(jié)點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$$ 
 
 
-- 調用函數(shù)輸出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$$ 
 
 
-- 調用函數(shù)輸出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$$ 
 
 
-- 調用過程輸出子節(jié)點 
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$$ 
 
-- 調用過程輸出父節(jié)點 
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 ; 

三、測試


CALL showChildLst(-1); 
CALL showChildLst(13); 
CALL showChildLst(14); 
CALL showChildLst(17); 
CALL showChildLst(18); 
 
CALL showParentLst(-1); 
CALL showParentLst(13); 
CALL showParentLst(14); 
CALL showParentLst(17); 
CALL showParentLst(18); 

四、遺留問題

1. 因為mysql對動態(tài)游標的支持不夠,所以要想做成通用的過程或函數(shù)比較困難,可以利用兩個臨時表來轉換(同時去掉了遞歸調用)是個相對通用的實現(xiàn)。

2. 目前來看無論哪種實現(xiàn),效率都不太好,希望mysql自己能實現(xiàn)Oracle 的connect by 功能,應該會比較優(yōu)化。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關文章

  • Mysql5.7定時備份的實現(xiàn)

    Mysql5.7定時備份的實現(xiàn)

    這篇文章主要介紹了Mysql5.7定時備份的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • php下巧用select語句實現(xiàn)mysql分頁查詢

    php下巧用select語句實現(xiàn)mysql分頁查詢

    mysql分頁查詢是我們經(jīng)常見到的問題,那么應該如何實現(xiàn)呢?下面就教您一個實現(xiàn)mysql分頁查詢的好方法,供您參考學習。
    2010-12-12
  • 深入了解mysql長事務

    深入了解mysql長事務

    這篇文章主要介紹了mysql長事務的相關資料,幫助大家更好的理解和學習mysql,感興趣的朋友可以了解下
    2020-08-08
  • mysql 臨時表 cann''t reopen解決方案

    mysql 臨時表 cann''t reopen解決方案

    MySql關于臨時表cann't reopen的問題,本文將提供詳細的解決方案,需要了解的朋友可以參考下
    2012-11-11
  • MYSQL定時清除備份數(shù)據(jù)的具體操作

    MYSQL定時清除備份數(shù)據(jù)的具體操作

    這篇文章主要給大家介紹了關于MYSQL定時清除備份數(shù)據(jù)的具體操作,文中通過示例代碼介紹的非常詳細,對大家學習或者使用MYSQL具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-06-06
  • MySQL?Community?Server?8.0.29安裝配置方法圖文教程

    MySQL?Community?Server?8.0.29安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了MySQL?Community?Server?8.0.29安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 詳解如何校驗MySQL及Oracle時間字段合規(guī)性

    詳解如何校驗MySQL及Oracle時間字段合規(guī)性

    這篇文章主要為大家介紹了如何校驗MySQL及Oracle時間字段合規(guī)性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • mysql中提高Order by語句查詢效率的兩個思路分析

    mysql中提高Order by語句查詢效率的兩個思路分析

    在MySQL數(shù)據(jù)庫中,Order by語句的使用頻率是比較高的。但是眾所周知,在使用這個語句時,往往會降低數(shù)據(jù)查詢的性能。
    2011-03-03
  • mysql數(shù)據(jù)庫id主鍵自增加刪除后不連續(xù)如何解決

    mysql數(shù)據(jù)庫id主鍵自增加刪除后不連續(xù)如何解決

    這篇文章主要介紹了mysql數(shù)據(jù)庫id主鍵自增加刪除后不連續(xù)的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Linux系統(tǒng)徹底卸載MySQL數(shù)據(jù)庫詳解

    Linux系統(tǒng)徹底卸載MySQL數(shù)據(jù)庫詳解

    這篇文章主要介紹了Linux系統(tǒng)徹底卸載MySQL數(shù)據(jù)庫,首先查詢系統(tǒng)是否安裝了mysql,如果安裝需要提前卸載,并刪除mysql安裝的組建服務,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2022-09-09

最新評論

休宁县| 青河县| 宁陕县| 临澧县| 镇雄县| 石家庄市| 濉溪县| 当涂县| 化德县| 涿州市| 八宿县| 三台县| 乐平市| 太仆寺旗| 科技| 乐亭县| 蓝田县| 信宜市| 霍林郭勒市| 新乡市| 曲麻莱县| 三原县| 东丰县| 民丰县| 龙门县| 新河县| 玉山县| 岐山县| 清徐县| 大邑县| 屯门区| 邵阳县| 元谋县| 汝州市| 普格县| 青冈县| 孝昌县| 囊谦县| 寻甸| 徐汇区| 长汀县|