MYSQL 遞迴獲取 子節點
阿新 • • 發佈:2019-01-14
表結構 create table `tb_xa_department` ( `id` bigint (20), `department_name` varchar (150), `level` int (11), `parent_id` bigint (20), `vendor_id` bigint (20) ); DROP TEMPORARY TABLE IF EXISTS tempTableForChildNote;drop procedure if exists findAlldep; CREATE PROCEDURE findAlldep(IN deptid BIGINT) BEGIN -- 建立臨時表 不能在這裡刪除 臨時表,刪除臨時表會報錯,或者 清空裡面的資料也是可以的 CREATE TEMPORARY TABLE tempTableForChildNote( departmentId BIGINT ); -- 這個是因為的 業務需要,需要把業務自身加進入 insert into tempTableForChildNote(departmentId) values(deptid); CALL findChildrenNote(deptid); END -- 查詢 子節點 drop procedure if exists findChildrenNote; CREATE PROCEDURE findChildrenNote(IN parentId BIGINT) BEGIN DECLARE finished INT DEFAULT 0; DECLARE childNote BIGINT; DECLARE number INT DEFAULT 0; DECLARE cur CURSOR FOR SELECT id FROM tb_xa_department WHERE parent_id=parentId; DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1; -- 設定 遞迴的深度,不設定回報錯 SET @@max_sp_recursion_depth = 100; OPEN cur; FETCH cur INTO childNote; WHILE finished = 0 DO -- 不要使用 動態sql,不然會報錯 -- SET @mysql = CONCAT('insert into tempTableForChildNote(departmentId) values(',childNote,')'); -- PREPARE stmt FROM @mysql; -- EXECUTE stmt; insert into tempTableForChildNote(departmentId) values(childNote); set number = 0; SELECT COUNT(*) INTO number FROM tb_xa_department WHERE parent_id=childNote; IF number > 0 THEN CALL findChildrenNote(childNote); -- 這裡遞迴 END IF; FETCH cur INTO childNote; END WHILE; CLOSE cur; END -- 建立方法 返回 查詢的結果,系統設計 4000 長度夠用 DROP FUNCTION IF EXISTS findAllNoteStr; CREATE FUNCTION findAllNoteStr(parentId bigint) RETURNS VARCHAR(4000) CHARSET utf8 BEGIN DECLARE result VARCHAR(4000); call findAlldep(parentId); select GROUP_CONCAT(departmentId)into result from tempTableForChildNote; -- 如果是用 drop table 回報錯,但是如如果是刪除臨時表舊不會報錯(很奇怪) DROP TEMPORARY TABLE IF EXISTS tempTableForChildNote; RETURN result; END; -- 這裡測試呼叫,臨時表是 每個 連結 建立,連結斷開的時候會自動刪除掉,因為我們 連結一直是在一個 連結中,所以需要我們在這裡刪除下 drop table tempTableForChildNote; select findAllNoteStr(4);