最近有個項目需要在很多前端頁面顯示當前員工的部門,但是這個部門是顯示當前部門的所有父級部門,比如當前為研發部,在前台頁面需要顯示為
“集團公司>子公司>研發部” 的格式,因為很多頁面都需要這種數據,在查詢時關聯查詢可能比較麻煩,所以選擇自定義一個mysql函數來查詢這種格式。
現在需要的是從子級查詢父級部門,是從下往上查,可能父級部門只有一個,也可能有多個父級部門,所以我們需要for循環來遞歸查詢。
為了舉個栗子,新建表結構及插入數據
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for sa_org -- ---------------------------- DROP TABLE IF EXISTS `sa_org`; CREATE TABLE `sa_org` ( `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `p_org_id` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `org_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of sa_org -- ---------------------------- INSERT INTO `sa_org` VALUES ('27193728124848239', '0', '集團公司'); INSERT INTO `sa_org` VALUES ('27193728124848240', '27193728124848239', '子公司1'); INSERT INTO `sa_org` VALUES ('27193728124848241', '27193728124848240', '合規部'); SET FOREIGN_KEY_CHECKS = 1;
這里插入三條數據,比如當前某個員工是合規部,需要顯示為如下格式:
這里我們設置最頂級的部門id為0,當當前部門的id為0時默認退出循環,所以我們可以這樣寫函數:
DROP FUNCTION IF EXISTS getOrgParent; CREATE FUNCTION `getOrgParent`(orgId varchar(100)) RETURNS varchar(1000) CHARSET utf8 BEGIN DECLARE orgNamePath VARCHAR(1000); DECLARE pOrgId VARCHAR(32); DECLARE orgName VARCHAR(128); SET orgNamePath = ''; SET pOrgId = orgId; set orgName = ''; WHILE pOrgId <> '0' DO SELECT p_org_id, org_name INTO pOrgId, orgName FROM sa_org WHERE id = pOrgId; IF orgNamePath = '' THEN SET orgNamePath = orgName; ELSE SET orgNamePath = CONCAT(orgName, '>', orgNamePath); END IF; END WHILE; RETURN orgNamePath; END
執行完成,查詢試一下:
select getOrgParent('27193728124848241')
select getOrgParent('27193728124848240')
可以看到實現了我們的需求,在查詢表格數據時,直接使用這個函數就可以將org_id變為部門層級展示了。
但是當我們輸入一個不存在於這個表的數據時,會發現這條查詢一直在執行,構成了死循環,所以我們改成如下:
drop FUNCTION if EXISTS `getOrgParent`; CREATE FUNCTION `getOrgParent`(orgId varchar(100)) RETURNS varchar(1000) CHARSET utf8 BEGIN DECLARE orgNamePath VARCHAR(1000); DECLARE pOrgId VARCHAR(32); DECLARE orgName VARCHAR(128); DECLARE count INT; SET orgNamePath = ''; SET pOrgId = orgId; set orgName = ''; set count = 1; WHILE pOrgId <> '0' and count <> 0 DO SELECT p_org_id, org_name, count(1) INTO pOrgId, orgName, count FROM sa_org WHERE id = pOrgId; IF orgNamePath = '' THEN SET orgNamePath = orgName; ELSE SET orgNamePath = CONCAT(orgName, '>', orgNamePath); END IF; END WHILE; RETURN orgNamePath; END
可以看到即使現在這條數據不存在也不會死循環了。