/* 创建部门表 */ CREATE TABLE department( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(200) NOT NULL, parent_id INT DEFAULT NULL ); /* 插入数据 */ INSERT INTO department(name, parent_id) VALUES('CEO', NULL); INSERT INTO department(name, parent_id) VALUES('技术部', 1); INSERT INTO department(name, parent_id) VALUES('市场部', 1); INSERT INTO department(name, parent_id) VALUES('研发部', 2); INSERT INTO department(name, parent_id) VALUES('测试部', 2); INSERT INTO department(name, parent_id) VALUES('销售部', 3); INSERT INTO department(name, parent_id) VALUES('宣传部', 3); INSERT INTO department(name, parent_id) VALUES('推广部', 4); INSERT INTO department(name, parent_id) VALUES('前端组', 4); INSERT INTO department(name, parent_id) VALUES('后端组', 4); INSERT INTO department(name, parent_id) VALUES('移动组', 4);
如上所示,大家创建了部门表,并插入了一些数据。这里parent_id表示上级部门id,NULL表示最高级部门或没有上级部门。
/* 定义循环体 */ DELIMITER $$ CREATE PROCEDURE get_sub_department(IN p_department_id INT) BEGIN SELECT id, name, parent_id FROM department WHERE parent_id = p_department_id; /* 定义变量 */ DECLARE done INT DEFAULT FALSE; DECLARE next_department_id INT; /* 定义游标 */ DECLARE cur CURSOR FOR SELECT id FROM department WHERE parent_id = p_department_id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; /* 开始循环 */ OPEN cur; read_loop: LOOP /* 读取游标 */ FETCH cur INTO next_department_id; /* 判断游标是否结束 */ IF done THEN LEAVE read_loop; END IF; /* 递归执行 */ CALL get_sub_department(next_department_id); END LOOP; /* 关闭游标 */ CLOSE cur; END$$ DELIMITER ;
此处大家定义了一个存储过程get_sub_department,它接收一个p_department_id参数,返回该部门的所有下级部门。将游标读取到的next_department_id作为参数递归调用get_sub_department存储过程实现循环查询。
/* 调用存储过程 */ CALL get_sub_department(NULL);
通过以上代码,大家可以调用get_sub_department存储过程,并将NULL作为参数来获取所有部门的层级关系。可以看到,MySQL提供了很强大的功能来完成层级查询,开发者可以根据实际需要进行调整和扩展。