mysql 樹結構遞歸處理


日常開發中我們經常會遇到樹形結構數據處理,一般表結構通常會常用id,pid這種設計方案。

之前用oracle、sqlServer數據庫,用相應的語法即可獲取樹形結構數據(oracel:connect by prior ;sqlServer:with...as ...)。

最近一個項目數據庫用的是mysql,需求中含有獲取樹形結構數據的接口,由於之前沒怎么用過mysql,於是第一時間就是查看mysql語法,看看有沒有類似於oracle或sqlserver的遞歸語法,結果是沒有,后來決定自定義數據庫函數(暫時解決了需求)。

1.自定義遞歸函數

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Function structure for `getPartyChildOrg`
-- ----------------------------
DROP FUNCTION IF EXISTS `getPartyChildOrg`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `getPartyChildOrg`(orgid BIGINT) RETURNS varchar(4000) CHARSET utf8
BEGIN
DECLARE oTemp VARCHAR(4000);
DECLARE oTempChild VARCHAR(4000);
 
SET oTemp = '';
SET oTempChild = CAST(orgid AS CHAR);
 
WHILE oTempChild IS NOT NULL
DO
SET oTemp = CONCAT(oTemp,',',oTempChild);
SELECT GROUP_CONCAT(id) INTO oTempChild FROM sub_party_orginfo WHERE logic_delete = 0 and FIND_IN_SET(pid,oTempChild) > 0;
END WHILE;
RETURN oTemp;
END
;;
DELIMITER ;

  暫時滿足了需求,后期數據量大了,再加上主鍵生成策略生成的主鍵長度比較長,函數返回結果長度受VARCHAR最大長度限制,該方案會失效,導致查詢的數據不全。

2.自定義存儲過程,將查詢的結果存放到臨時表中。

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Procedure structure for `findPartyOrgChildList`
-- ----------------------------
DROP PROCEDURE IF EXISTS `findPartyOrgChildList`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `findPartyOrgChildList`(IN pid VARCHAR(20))
BEGIN
  DECLARE v_org BIGINT(20);
  DECLARE done INTEGER DEFAULT 0;
    -- 查詢結果放入游標中
  DECLARE C_org CURSOR FOR SELECT d.id
                           FROM sub_party_orginfo d
                           WHERE d.pid = pid;
  DECLARE CONTINUE HANDLER FOR NOT found SET done=1;
  SET @@max_sp_recursion_depth = 10;
    
    -- 傳入的組織id寫入臨時表
 INSERT INTO temp_party_org VALUES (pid);
  OPEN C_org;
  FETCH C_org INTO v_org;
  WHILE (done=0)
  DO
        -- 遞歸調用,查找下級
    CALL findPartyOrgChildList(v_org);
    FETCH C_org INTO v_org;
  END WHILE;
  CLOSE C_org;
END
;;
DELIMITER ;

-- ----------------------------
-- Procedure structure for `findPartyOrgList`
-- ----------------------------
DROP PROCEDURE IF EXISTS `findPartyOrgList`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `findPartyOrgList`(IN pid BIGINT(20))
BEGIN
  DROP TEMPORARY TABLE IF EXISTS temp_party_org;
    -- 創建臨時表
    CREATE TEMPORARY TABLE temp_party_org(id BIGINT(20));
    -- 清空臨時表數據
    DELETE FROM temp_party_org;
    -- 發起調用
    CALL findPartyOrgChildList(pid);
   
END
;;
DELIMITER ;

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM