MySQL 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题)
前言:
关于多级别菜单栏或者权限系统中部门上下级的树形遍历,oracle中有connect by来实现,mysql没有这样的便捷途径,所以MySQL遍历数据表是我们经常会遇到的头痛问题,下面通过存储过程来实现。
1,建立测试表和数据:
DROP TABLE IF EXISTS csdn.channel; CREATE TABLE csdn.channel ( id INT(11) NOT NULL AUTO_INCREMENT, cname VARCHAR(200) DEFAULT NULL, parent_id INT(11) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO channel(id,cname,parent_id) VALUES (13,'首页',-1), (14,'TV580',-1), (15,'生活580',-1), (16,'左上幻灯片',13), (17,'帮忙',14), (18,'栏目简介',17); DROP TABLE IF EXISTS channel;
2,利用临时表和递归过程实现树的遍历(mysql的UDF不能递归调用):
2.1,从某节点向下遍历子节点,递归生成临时表数据
-- pro_cre_childlist DELIMITER $$ DROP PROCEDURE IF EXISTS csdn.pro_cre_childlist$$ CREATE PROCEDURE csdn.pro_cre_childlist(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 pro_cre_childlist(b,nDepth+1); FETCH cur1 INTO b; END WHILE; CLOSE cur1; END$$
2.2,从某节点向上追溯根节点,递归生成临时表数据
-- pro_cre_parentlist DELIMITER $$ DROP PROCEDURE IF EXISTS csdn.pro_cre_parentlist$$ CREATE PROCEDURE csdn.pro_cre_parentlist(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 pro_cre_parentlist(b,nDepth+1); FETCH cur1 INTO b; END WHILE; CLOSE cur1; END$$
2.3,实现类似Oracle SYS_CONNECT_BY_PATH的功能,递归过程输出某节点id路径
-- pro_cre_pathlist DELIMITER $$ USE csdn$$ DROP PROCEDURE IF EXISTS pro_cre_pathlist$$ CREATE PROCEDURE pro_cre_pathlist(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 pro_cre_pathlist(parentid,delimit,pathstr); FETCH cur1 INTO parentid,pathstr; END WHILE; CLOSE cur1; END$$ DELIMITER ;
2.4,递归过程输出某节点name路径
-- pro_cre_pnlist DELIMITER $$ USE csdn$$ DROP PROCEDURE IF EXISTS pro_cre_pnlist$$ CREATE PROCEDURE pro_cre_pnlist(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 pro_cre_pnlist(parentid,delimit,pathstr); FETCH cur1 INTO parentid,pathstr; END WHILE; CLOSE cur1; END$$ DELIMITER ;
2.5,调用函数输出id路径
-- fn_tree_path DELIMITER $$ DROP FUNCTION IF EXISTS csdn.fn_tree_path$$ CREATE FUNCTION csdn.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 pro_cre_pathlist(nid,delimit,@pathid); RETURN @pathid; END$$
2.6,调用函数输出name路径
-- fn_tree_pathname -- 调用函数输出name路径 DELIMITER $$ DROP FUNCTION IF EXISTS csdn.fn_tree_pathname$$ CREATE FUNCTION csdn.fn_tree_pathname(nid INT,delimit VARCHAR(10)) RETURNS VARCHAR(2000) CHARSET utf8 BEGIN DECLARE pathid VARCHAR(1000); SET @pathid=''; CALL pro_cre_pnlist(nid,delimit,@pathid); RETURN @pathid; END$$ DELIMITER ;
2.7,调用过程输出子节点
-- pro_show_childLst DELIMITER $$ -- 调用过程输出子节点 DROP PROCEDURE IF EXISTS pro_show_childLst$$ CREATE PROCEDURE pro_show_childLst(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 pro_cre_childlist(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$$
2.8,调用过程输出父节点
-- pro_show_parentLst DELIMITER $$ -- 调用过程输出父节点 DROP PROCEDURE IF EXISTS `pro_show_parentLst`$$ CREATE PROCEDURE `pro_show_parentLst`(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 pro_cre_parentlist(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$$
3,开始测试:
3.1,从根节点开始显示,显示子节点集合:
mysql> CALL pro_show_childLst(-1); +----+-----------------------+-----------+-------+-------------+----------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+-----------------------+-----------+-------+-------------+----------------------------+ | 13 | --首页 | -1 | 1 | -1/13 | 首页/ | | 16 | --左上幻灯片 | 13 | 2 | -1/13/16 | 首页/左上幻灯片/ | | 14 | --TV580 | -1 | 1 | -1/14 | TV580/ | | 17 | --帮忙 | 14 | 2 | -1/14/17 | TV580/帮忙/ | | 18 | --栏目简介 | 17 | 3 | -1/14/17/18 | TV580/帮忙/栏目简介/ | | 15 | --生活580 | -1 | 1 | -1/15 | 生活580/ | +----+-----------------------+-----------+-------+-------------+----------------------------+ 6 rows in set (0.05 sec) Query OK, 0 rows affected (0.05 sec)
3.2,显示首页下面的子节点
CALL pro_show_childLst(13); mysql> CALL pro_show_childLst(13); +----+---------------------+-----------+-------+----------+-------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+---------------------+-----------+-------+----------+-------------------------+ | 13 | --首页 | -1 | 0 | -1/13 | 首页/ | | 16 | --左上幻灯片 | 13 | 1 | -1/13/16 | 首页/左上幻灯片/ | +----+---------------------+-----------+-------+----------+-------------------------+ 2 rows in set (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql>
3.3,显示TV580下面的所有子节点
CALL pro_show_childLst(14); mysql> CALL pro_show_childLst(14); +----+--------------------+-----------+-------+-------------+----------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+--------------------+-----------+-------+-------------+----------------------------+ | 14 | --TV580 | -1 | 0 | -1/14 | TV580/ | | 17 | --帮忙 | 14 | 1 | -1/14/17 | TV580/帮忙/ | | 18 | --栏目简介 | 17 | 2 | -1/14/17/18 | TV580/帮忙/栏目简介/ | +----+--------------------+-----------+-------+-------------+----------------------------+ 3 rows in set (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql>
3.4,“帮忙”节点有一个子节点,显示出来:
CALL pro_show_childLst(17); mysql> CALL pro_show_childLst(17); +----+------------------+-----------+-------+-------------+----------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+------------------+-----------+-------+-------------+----------------------------+ | 17 | --帮忙 | 14 | 0 | -1/14/17 | TV580/帮忙/ | | 18 | --栏目简介 | 17 | 1 | -1/14/17/18 | TV580/帮忙/栏目简介/ | +----+------------------+-----------+-------+-------------+----------------------------+ 2 rows in set (0.03 sec) Query OK, 0 rows affected (0.03 sec) mysql>
3.5,“栏目简介”没有子节点,所以只显示最终节点:
mysql> CALL pro_show_childLst(18); +----+----------------+-----------+-------+-------------+----------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+----------------+-----------+-------+-------------+----------------------------+ | 18 | --栏目简介 | 17 | 0 | -1/14/17/18 | TV580/帮忙/栏目简介/ | +----+----------------+-----------+-------+-------------+----------------------------+ 1 row in set (0.36 sec) Query OK, 0 rows affected (0.36 sec) mysql>
3.6,显示根节点的父节点
CALL pro_show_parentLst(-1); mysql> CALL pro_show_parentLst(-1); Empty set (0.01 sec) Query OK, 0 rows affected (0.01 sec) mysql>
3.7,显示“首页”的父节点
CALL pro_show_parentLst(13); mysql> CALL pro_show_parentLst(13); +----+----------+-----------+-------+-------+----------+ | id | NAME | parent_id | depth | path | pathname | +----+----------+-----------+-------+-------+----------+ | 13 | --首页 | -1 | 0 | -1/13 | 首页/ | +----+----------+-----------+-------+-------+----------+ 1 row in set (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql>
3.8,显示“TV580”的父节点,parent_id为-1
CALL pro_show_parentLst(14); mysql> CALL pro_show_parentLst(14); +----+---------+-----------+-------+-------+----------+ | id | NAME | parent_id | depth | path | pathname | +----+---------+-----------+-------+-------+----------+ | 14 | --TV580 | -1 | 0 | -1/14 | TV580/ | +----+---------+-----------+-------+-------+----------+ 1 row in set (0.02 sec) Query OK, 0 rows affected (0.02 sec)
3.9,显示“帮忙”节点的父节点
mysql> CALL pro_show_parentLst(17); mysql> CALL pro_show_parentLst(17); +----+-----------+-----------+-------+----------+---------------+ | id | NAME | parent_id | depth | path | pathname | +----+-----------+-----------+-------+----------+---------------+ | 17 | --帮忙 | 14 | 0 | -1/14/17 | TV580/帮忙/ | | 14 | --TV580 | -1 | 1 | -1/14 | TV580/ | +----+-----------+-----------+-------+----------+---------------+ 2 rows in set (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql>
3.10,显示最低层节点“栏目简介”的父节点
CALL pro_show_parentLst(18); mysql> CALL pro_show_parentLst(18); +----+----------------+-----------+-------+-------------+----------------------------+ | id | NAME | parent_id | depth | path | pathname | +----+----------------+-----------+-------+-------------+----------------------------+ | 18 | --栏目简介 | 17 | 0 | -1/14/17/18 | TV580/帮忙/栏目简介/ | | 17 | --帮忙 | 14 | 1 | -1/14/17 | TV580/帮忙/ | | 14 | --TV580 | -1 | 2 | -1/14 | TV580/ | +----+----------------+-----------+-------+-------------+----------------------------+ 3 rows in set (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql>
以上就是MySQL 实现树形的遍历(关于多级菜单栏以及多级上下部门的查询问题) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



MySQL sesuai untuk pemula kerana mudah dipasang, kuat dan mudah untuk menguruskan data. 1. Pemasangan dan konfigurasi mudah, sesuai untuk pelbagai sistem operasi. 2. Menyokong operasi asas seperti membuat pangkalan data dan jadual, memasukkan, menanyakan, mengemas kini dan memadam data. 3. Menyediakan fungsi lanjutan seperti menyertai operasi dan subqueries. 4. Prestasi boleh ditingkatkan melalui pengindeksan, pengoptimuman pertanyaan dan pembahagian jadual. 5. Sokongan sokongan, pemulihan dan langkah keselamatan untuk memastikan keselamatan data dan konsistensi.

MySQL adalah sistem pengurusan pangkalan data sumber terbuka. 1) Buat Pangkalan Data dan Jadual: Gunakan perintah Createdatabase dan Createtable. 2) Operasi Asas: Masukkan, Kemas kini, Padam dan Pilih. 3) Operasi lanjutan: Sertai, subquery dan pemprosesan transaksi. 4) Kemahiran Debugging: Semak sintaks, jenis data dan keizinan. 5) Cadangan Pengoptimuman: Gunakan indeks, elakkan pilih* dan gunakan transaksi.

Anda boleh membuka phpmyadmin melalui langkah -langkah berikut: 1. Log masuk ke panel kawalan laman web; 2. Cari dan klik ikon phpmyadmin; 3. Masukkan kelayakan MySQL; 4. Klik "Login".

Buat pangkalan data menggunakan Navicat Premium: Sambungkan ke pelayan pangkalan data dan masukkan parameter sambungan. Klik kanan pada pelayan dan pilih Buat Pangkalan Data. Masukkan nama pangkalan data baru dan set aksara yang ditentukan dan pengumpulan. Sambung ke pangkalan data baru dan buat jadual dalam penyemak imbas objek. Klik kanan di atas meja dan pilih masukkan data untuk memasukkan data.

MySQL dan SQL adalah kemahiran penting untuk pemaju. 1.MYSQL adalah sistem pengurusan pangkalan data sumber terbuka, dan SQL adalah bahasa standard yang digunakan untuk mengurus dan mengendalikan pangkalan data. 2.MYSQL menyokong pelbagai enjin penyimpanan melalui penyimpanan data yang cekap dan fungsi pengambilan semula, dan SQL melengkapkan operasi data yang kompleks melalui pernyataan mudah. 3. Contoh penggunaan termasuk pertanyaan asas dan pertanyaan lanjutan, seperti penapisan dan penyortiran mengikut keadaan. 4. Kesilapan umum termasuk kesilapan sintaks dan isu -isu prestasi, yang boleh dioptimumkan dengan memeriksa penyataan SQL dan menggunakan perintah menjelaskan. 5. Teknik pengoptimuman prestasi termasuk menggunakan indeks, mengelakkan pengimbasan jadual penuh, mengoptimumkan operasi menyertai dan meningkatkan kebolehbacaan kod.

Anda boleh membuat sambungan MySQL baru di Navicat dengan mengikuti langkah -langkah: Buka aplikasi dan pilih Sambungan Baru (Ctrl N). Pilih "MySQL" sebagai jenis sambungan. Masukkan nama host/alamat IP, port, nama pengguna, dan kata laluan. (Pilihan) Konfigurasikan pilihan lanjutan. Simpan sambungan dan masukkan nama sambungan.

Memulihkan baris yang dipadam secara langsung dari pangkalan data biasanya mustahil melainkan ada mekanisme sandaran atau transaksi. Titik Utama: Rollback Transaksi: Jalankan balik balik sebelum urus niaga komited untuk memulihkan data. Sandaran: Sandaran biasa pangkalan data boleh digunakan untuk memulihkan data dengan cepat. Snapshot Pangkalan Data: Anda boleh membuat salinan bacaan pangkalan data dan memulihkan data selepas data dipadam secara tidak sengaja. Gunakan Pernyataan Padam dengan berhati -hati: Periksa syarat -syarat dengan teliti untuk mengelakkan data yang tidak sengaja memadamkan. Gunakan klausa WHERE: Secara jelas menentukan data yang akan dipadam. Gunakan Persekitaran Ujian: Ujian Sebelum Melaksanakan Operasi Padam.

Langkah -langkah untuk melaksanakan SQL di Navicat: Sambungkan ke pangkalan data. Buat tetingkap editor SQL. Tulis pertanyaan SQL atau skrip. Klik butang Run untuk melaksanakan pertanyaan atau skrip. Lihat hasilnya (jika pertanyaan dilaksanakan).
