1. 程式人生 > 其它 >mysql自定義函式遞迴查詢部門層級

mysql自定義函式遞迴查詢部門層級

最近有個專案需要在很多前端頁面顯示當前員工的部門,但是這個部門是顯示當前部門的所有父級部門,比如當前為研發部,在前臺頁面需要顯示為

“集團公司>子公司>研發部” 的格式,因為很多頁面都需要這種資料,在查詢時關聯查詢可能比較麻煩,所以選擇自定義一個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

可以看到即使現在這條資料不存在也不會死迴圈了。