1. 程式人生 > >存儲過程的遞歸調用(樹形結構路徑的快速生成)

存儲過程的遞歸調用(樹形結構路徑的快速生成)

fault recursion 結束 快速 substr 手動 默認值 這不 字符

最近在做表數據整理的時候碰到這樣的一個問題,我有一張permission表,其數據結構為樹形結構,裏面有個permission_path字段用於記錄根節點到父節點的路徑(以permission_id為路徑)。

  例子:假設100的父節點為10,10的父節點為1,這100的路徑為:1/10。

  但現在有個問題,permission_path字段在當時並沒有處理(為空字符串),如今這個表有四五百條數據,寫代碼來改太麻煩,更別說一條條數據手動修改,不可行!

  能否通過一個語句塊來自動生成路徑?顯然是可以的,因為現在的oracle、SQL SERVER2005以上版本和mysql5.0以上版本的數據庫都支持存儲過程,而存儲過程還有個比較有趣的玩法,那就是遞歸調用!用這個方法就可以快速、方便地解決上述問題。

  存儲過程的概念這裏就不介紹了,語句非常簡單,直接上語句(我使用的數據庫是mysql5.6),一步步解析:

CREATE PROCEDURE test(IN parent int)
BEGIN 
DECLARE ids VARCHAR(255) DEFAULT 0;   
DECLARE IND INT;
DECLARE i INT DEFAULT 1;
DECLARE path VARCHAR(255);
SELECT GROUP_CONCAT(t.permission_id) INTO ids from system_permissions t where t.permission_parent =
parent; SELECT COUNT(t.*) INTO IND from system_permissions t where t.permission_parent = parent; SELECT t.permission_path INTO path from system_permissions t where t.permission_id = parent; if ids <> 0 THEN UPDATE system_permissions set permission_path = CONCAT(path,/,parent) where permission_parent =
parent; SET @@max_sp_recursion_depth = 100; while i <= IND DO call test(substring_index(substring_index(ids,,, i), ,, -1)); set i = i + 1; end while; end if; end

  先介紹基本語法:

create procedure test(IN p1 int,IN p2 varchar2(10))      //create procedure 函數名(IN 參數1 類型,IN 參數2 類型),英文部分為固定寫法,
                                    中文部分為自定義,其中類型只能使用數據庫存在的類型
  begin   //標識著存儲過程邏輯的開始     語句內容  //邏輯、語句都寫在此處   end  //標識著存儲過程邏輯的結束
DECLARE 聲明變量
DECLARE ids VARCHAR(255) DEFAULT 0;    //DECLARE 表示聲明一個變量,該變量類型為varchar(255),默認值為0

把變量都定義好後,就可以使用sql語句對數據進行操作

在幾個select語句之後,會看到if的判斷語句,在if中使用update更新表的permissiom_path的值

if ids <> 0 THEN    //if語句的開頭,if 判斷條件 then
  邏輯內容
end if;    //if語句的結尾

while循環語句,用於循環遍歷同級數據,在這個存儲過程中也充當條件,避免無限遞歸循環

while i <= IND  DO  //while語句的開頭,while 判斷條件 do
  邏輯內容
end while;    //while語句的結尾

存儲過程的遞歸調用有兩個核心:

1、設置樹的極限深度,使用場景一般為存儲過程中調用存儲過程

SET @@max_sp_recursion_depth = 100;   //絕大部分情況設置100就夠用了,除非遞歸調用的深度超過100

2、調用自己

call test(substring_index(substring_index(ids,,, i), ,, -1));  //call 存儲過程名(參數)

最後,由於我的permission表的樹形結構的根節點id是0,所以我在生成存儲過程後執行的語句為

call test(0)

這樣就可以為permision表中的permission_path字段自動賦上路徑值

其實存儲過程的用法並不復雜,只要記住格式就行了,固定的格式開頭和結尾,中間的邏輯都可以是非常簡單的語句。而存儲過程的遞歸調用需要註意的地方無非是樹的深度的設置,以及防止死循環的邏輯。對於用代碼寫過遞歸調用的朋友們來說這不是什麽有難度的事,如果沒有寫過遞歸調用這樣的邏輯,建議先通過代碼熟悉遞歸調用的特點以及註意事項,再來寫sql!

ps:第一次寫博客,如有不足的地方歡迎指出!

存儲過程的遞歸調用(樹形結構路徑的快速生成)