1-前言:sql
在Mysql使用遞歸查詢是很不方便的,不像Sqlserver能夠直接使用聲明變量,使用虛擬表等等。如:DECLARE,BEGIN ... END ,WHILE ,IF 等等。函數
在Mysql能夠經過建立函數,來使用上面的流程控制語句,Mysql對函數的語法檢查也是很苛刻的,能夠說很煩人,不熟悉的人估計會哭。。。spa
2-遞歸查詢關鍵部分:code
a-個人表結構:server
b-個人遞歸腳本:blog
用於查詢:當前類目ID及全部的父級元素的ID使用逗號分割開的一個字符串:排序
下面腳本里使用了組合結果集的一個函數:GROUP_CONCAT,使用該函數能夠在查不到結果的時候繼續給pid賦值,從而跳出循環,詳細可參考文章下面的注意點。遞歸
SELECT ParentID INTO pid FROM product_leimu WHERE 1=2; -- 找不到數據的狀況下, INTO 沒法給pid賦值,pid結果不變,字符串
SELECT GROUP_CONCAT(ParentID) INTO pid FROM product_leimu WHERE 1=2; -- 找不到數據的狀況下,經過函數GROUP_CONCAT組合以後,能夠繼續使用INTO 給pid賦值,pid結果爲NULLget
DROP FUNCTION IF EXISTS `fn_getLeimuPath`; CREATE DEFINER = `sa`@`%` FUNCTION `fn_getLeimuPath`(`subId` int) RETURNS varchar(1000) BEGIN DECLARE pathID VARCHAR(4000) DEFAULT subId; DECLARE pid INT default subid; WHILE pid>0 DO SELECT GROUP_CONCAT(ParentID) INTO pid FROM product_leimu WHERE ID = pid; IF pid>0 THEN SET pathID = concat(pid, ',', pathID); END IF; END WHILE; RETURN pathID; END;
查詢結果展現:
3-一些須要注意的點,函數的一些特殊語法檢查:
a-腳本結束標記檢查: 分號檢查:
如:每一個獨立的腳本語句; 流程控制語句結尾:END IF; END; END WHILE;
b-流程控制語句組合:
如:
IF 條件 THEN
代碼
ELSEIF
代碼
END IF;
WHILE 條件 DO
代碼
END WHILE;
c-特殊函數的使用:
函數:GROUP_CONCAT:將結果集連接在一塊兒,使用逗號分隔,group_concat([DISTINCT] 要鏈接的字段 [Order BY ASC/DESC 排序字段] [Separator ‘分隔符’])
備註: 這個函數能夠在找不到數據的狀況下,繼續執行從而給INTO的變量賦值。 比較神奇:
SELECT ParentID INTO pid FROM product_leimu WHERE 1=2; -- 找不到數據的狀況下, INTO 沒法給pid的結果不變,
SELECT GROUP_CONCAT(ParentID) INTO pid FROM product_leimu WHERE 1=2; -- 找不到數據的狀況下,經過函數GROUP_CONCAT組合以後,能夠繼續使用INTO 給pid賦值,NULL
咱們這裏是想在查不到的結果的時候,經過WHILE的判斷結束循環,若是不經過GROUP_CONCAT函數將結果傳給pid,那麼將會進入無線循環當中,是很坑的!! 下面腳本的代碼結果是:2
DECLARE pid INT; SELECT ParentID INTO pid FROM product_leimu WHERE 1=2; IF pid IS NULL THEN SET pid=1; END IF; SELECT GROUP_CONCAT(ParentID) INTO pid FROM product_leimu WHERE 1=2; IF pid IS NULL THEN SET pid=2; END IF;