DELIMITER //
CREATE FUNCTION getChildRegions(parent_id INT) RETURNS VARCHAR(1000)
BEGIN
DECLARE child_list VARCHAR(1000);
SET child_list = '';
SELECT GROUP_CONCAT(id) INTO child_list FROM sys_region WHERE parent_code = parent_id;
RETURN child_list;
END//
DELIMITER ;
該函數通過遞歸調用自身獲取所有子節點的ID列表。
使用純SQL實現遞歸查詢
使用純SQL實現遞歸查詢不需要創建函數,但需要通過多次JOIN操作來反復獲取數據。
優缺點分析
優點:
無需創建復雜的函數,易于實現。
適合簡單的遞歸查詢。
缺點:
當層次結構較深時,SQL語句會變得冗長且難以維護。
示例代碼
SELECT T1.id, T1.name, T2.name AS parent_name
FROM sys_region T1
LEFT JOIN sys_region T2 ON T1.parent_code = T2.id;
該查詢通過JOIN操作獲取每個區域及其父區域的名稱。
使用WITH RECURSIVE實現遞歸查詢
MySQL 8.0以上版本支持WITH RECURSIVE語法,簡化了遞歸查詢的實現。
優缺點分析
優點:
語法簡潔,易于理解和維護。
性能優于傳統遞歸函數。
缺點:
僅適用于MySQL 8.0及以上版本。
示例代碼
WITH RECURSIVE region_cte AS (
SELECT id, name, parent_code FROM sys_region WHERE id = 1
UNION ALL
SELECT r.id, r.name, r.parent_code
FROM sys_region r
JOIN region_cte c ON r.parent_code = c.id
)
SELECT * FROM region_cte;
該代碼使用WITH RECURSIVE實現了從山東省開始的區域遞歸查詢。
實現步驟詳解
建表腳本
在實現遞歸查詢之前,我們需要創建示例數據表sys_region。
創建表
DROP TABLE IF EXISTS sys_region;
CREATE TABLE sys_region (
id int(50) NOT NULL AUTO_INCREMENT COMMENT '地區主鍵編號',
name varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地區名稱',
short_name varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '簡稱',
code varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '行政地區編號',
parent_code varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父id',
level int(2) NULL DEFAULT NULL COMMENT '1級:省、直轄市、自治區rn2級:地級市rn3級:市轄區、縣(旗)、縣級市、自治縣(自治旗)、特區、林區rn4級:鎮、鄉、民族鄉、縣轄區、街道rn5級:村、居委會',
flag int(1) NULL DEFAULT NULL COMMENT '0:正常 1廢棄',
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 182 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '地區表' ROW_FORMAT = Dynamic;