1. 程式人生 > >MYSQL 遞迴獲取 子節點

MYSQL 遞迴獲取 子節點

表結構
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);