溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用mysql 游標(biāo),快速刪除子節(jié)點(diǎn)及其附屬節(jié)點(diǎn)

發(fā)布時(shí)間:2020-07-06 06:25:18 來源:網(wǎng)絡(luò) 閱讀:1304 作者:AdaAda 欄目:MySQL數(shù)據(jù)庫

上篇,我寫了如何使用html展示數(shù)據(jù)庫中存儲(chǔ)的樹形結(jié)構(gòu), 本篇我將說一下如何通過存儲(chǔ)過程,快速刪除一個(gè)樹節(jié)點(diǎn)及其附屬節(jié)點(diǎn)。網(wǎng)上已經(jīng)有非常多的關(guān)于mysql 游標(biāo)使用的文章了, 為什么我還要寫這篇文章呢,我主要是想表達(dá)一些在軟件設(shè)計(jì)領(lǐng)域的一些想法。

一直不太贊同在數(shù)據(jù)庫中大量的使用存儲(chǔ)過程, 因?yàn)殡S著軟件系統(tǒng)的復(fù)雜度逐漸提高,維護(hù)的難度會(huì)逐漸的增大。而且大批量的使用存儲(chǔ)過程,不利于后期通過分布式部署應(yīng)用程序來解決日益增多的業(yè)務(wù)需求。

我推薦把存儲(chǔ)過程僅用在處理一些不包含太多業(yè)務(wù),批量操作數(shù)據(jù)的場景中,因?yàn)檫@樣可以避免應(yīng)用程序頻繁的訪問數(shù)據(jù)庫。刪除一個(gè)樹的子節(jié)點(diǎn)正好符合這一場景。

我們知道刪除一個(gè)樹節(jié)點(diǎn)的同時(shí),需要?jiǎng)h除其子節(jié)點(diǎn)或葉子節(jié)點(diǎn)。通過使用mysql的游標(biāo),我們可以遍歷某一節(jié)點(diǎn)的所有子節(jié)點(diǎn),通過使用遞歸,我們可以跨越多層直至葉子節(jié)點(diǎn)。

要實(shí)現(xiàn)刪除一個(gè)樹節(jié)點(diǎn), 一個(gè)存儲(chǔ)過程肯定可以搞定,但是為了讓程序邏輯更簡單些, 我寫了兩個(gè)存儲(chǔ)過程,一個(gè)用來獲取存儲(chǔ)過程所有符合條件的節(jié)點(diǎn),另一個(gè)用來執(zhí)行刪除操作。

遍歷節(jié)點(diǎn),找出符合節(jié)點(diǎn)及其所有的子節(jié)點(diǎn)的實(shí)現(xiàn)是這樣的。

/* 創(chuàng)建一個(gè)獲取樹節(jié)點(diǎn)及其子節(jié)點(diǎn)的函數(shù),并以 節(jié)點(diǎn)id1, 節(jié)點(diǎn)id2 的形式返回 */
DROP PROCEDURE IF EXISTS get_tree_node;
CREATE  PROCEDURE get_tree_node(IN node_id INT, OUT result VARCHAR(2000))
BEGIN      
    DECLARE nodeid INT(50);  
  DECLARE done INT DEFAULT 0;  
     DECLARE cur CURSOR FOR SELECT id FROM treenodes WHERE pid = node_id;
    DECLARE CONTINUE HANDLER FOR NOT found SET done = TRUE;

  # 這一句非常重要, 他可以保證存儲(chǔ)過程至少會(huì)返回一個(gè)根節(jié)點(diǎn)id,調(diào)用 CONCAT_WS 函數(shù)時(shí)就不會(huì)出錯(cuò)了
  SELECT id INTO result FROM treenodes WHERE id= node_id;

  OPEN cur;
  REPEAT
            FETCH cur INTO nodeid;                     
      # 避免多一條記錄
      IF done <> 1 THEN                
        # 調(diào)用遞歸函數(shù)獲取節(jié)點(diǎn)下的子節(jié)點(diǎn)
        CALL get_tree_node(nodeid, @temp);            
        # 合并父節(jié)點(diǎn)和子節(jié)點(diǎn)的id
                SELECT CONCAT_WS(",", result, @temp) INTO result;
            END IF;
    UNTIL done END REPEAT;  
  # 關(guān)閉光標(biāo)
    CLOSE cur;

END;

刪除樹節(jié)點(diǎn)的存儲(chǔ)過程是這個(gè)樣子的

/* 刪除一個(gè)節(jié)點(diǎn)及其附屬節(jié)點(diǎn) */
DROP PROCEDURE IF EXISTS delete_tree_node;
CREATE PROCEDURE delete_tree_node(IN node_id int)
BEGIN
    SET  max_sp_recursion_depth = 10;
    CALL get_tree_node(node_id, @result);
    DELETE FROM treenodes WHERE FIND_IN_SET(id, @result);
    DELETE FROM books WHERE FIND_IN_SET(id, @result);
END

這里注意 max_sp_recursion_depth 這個(gè)msyql 參數(shù) 和 FIND_IN_SET 函數(shù)。

max_sp_recursion_depth 控制可以執(zhí)行遞歸的層數(shù),

FIND_IN_SET 函數(shù)的作用,會(huì)將@result 先變?yōu)橐粋€(gè)字符串列表,再查找復(fù)合條件的值。這里若用 IN 關(guān)鍵字的話,將得不到任何結(jié)果

附件:http://down.51cto.com/data/2366729
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI