日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql6支持connect by_mysql 实现oracle start with connect by递归

發布時間:2024/10/8 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql6支持connect by_mysql 实现oracle start with connect by递归 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Oracle 中我們知道有一個 Hierarchical Queries 通過CONNECT BY 我們可以方便的查了所有當前節點下的所有子節點。但很遺憾,在MySQL的目前版本中還沒有對應的功能。

在MySQL中如果是有限的層次,比如我們事先如果可以確定這個樹的最大深度是4, 那么所有節點為根的樹的深度均不會超過4,則我們可以直接通過left join 來實現。

但很多時候我們無法控制樹的深度。這時就需要在MySQL中用存儲過程來實現或在你的程序中來實現這個遞歸。本文討論一下幾種實現的方法。

樣例數據:

mysql> create

table treeNodes

-> (

->? id int primary key,

->? nodename varchar(20),

->? pid int

-> );

Query OK, 0 rows affected (0.09 sec)

mysql> select * from treenodes;

+----+----------+------+

| id | nodename | pid? |

+----+----------+------+

|? 1 |

A

|??? 0 |

|? 2 |

B

|??? 1 |

|? 3 |

C

|??? 1 |

|? 4 |

D

|??? 2 |

|? 5 |

E

|??? 2 |

|? 6 |

F

|??? 3 |

|? 7 |

G

|??? 6 |

|? 8 |

H

|??? 0 |

|? 9 |

I

|??? 8 |

| 10 |

J

|??? 8 |

| 11 |

K

|??? 8 |

| 12 |

L

|??? 9 |

| 13 |

M

|??? 9 |

| 14 |

N

|?? 12 |

| 15 |

O

|?? 12 |

| 16 |

P

|?? 15 |

| 17 |

Q

|?? 15 |

+----+----------+------+

17 rows in set (0.00 sec)

樹形圖如下

1:A

+-- 2:B

|??? +--

4:D

|??? +--

5:E

+-- 3:C

+-- 6:F

+-- 7:G

8:H

+-- 9:I

|??? +--

12:L

|

|

+--14:N

|

|

+--15:O

|

|

+--16:P

|

|

+--17:Q

|??? +--

13:M

+-- 10:J

+--

11:K

方法一:利用函數來得到所有子節點號。

創建一個function?getChildLst,

得到一個由所有子節點號組成的字符串.

mysql> delimiter

//

mysql>

mysql> CREATE FUNCTION `getChildLst`(rootId

INT)

-> RETURNS

varchar(1000)

-> BEGIN

->? ?DECLARE sTemp

VARCHAR(1000);

->? ?DECLARE

sTempChd VARCHAR(1000);

->

->? ?SET sTemp =

'$';

->? ?SET sTempChd

=cast(rootId as CHAR);

->

->? ?WHILE

sTempChd is not null DO

->

SET sTemp =

concat(sTemp,',',sTempChd);

->

SELECT

group_concat(id) INTO sTempChd FROM treeNodes where

FIND_IN_SET(pid,sTempChd)>0;

->? ?END

WHILE;

->? ?RETURN

sTemp;

-> END

-> //

Query OK, 0 rows affected (0.00 sec)

mysql>

mysql> delimiter ;

使用我們直接利用find_in_set函數配合這個getChildlst來查找

mysql> select

getChildLst(1);

+-----------------+

| getChildLst(1)??|

+-----------------+

| $,1,2,3,4,5,6,7 |

+-----------------+

1 row in set (0.00 sec)

mysql> select * from treeNodes

-> where

FIND_IN_SET(id, getChildLst(1));

+----+----------+------+

| id | nodename | pid??|

+----+----------+------+

|??1 | A

|

0 |

|??2 | B

|

1 |

|??3 | C

|

1 |

|??4 | D

|

2 |

|??5 | E

|

2 |

|??6 | F

|

3 |

|??7 | G

|

6 |

+----+----------+------+

7 rows in set (0.01 sec)

mysql> select * from treeNodes

-> where

FIND_IN_SET(id, getChildLst(3));

+----+----------+------+

| id | nodename | pid??|

+----+----------+------+

|??3 | C

|

1 |

|??6 | F

|

3 |

|??7 | G

|

6 |

+----+----------+------+

3 rows in set (0.01 sec)

優點: 簡單,方便,沒有遞歸調用層次深度的限制

(max_sp_recursion_depth,最大255) ;

缺點:長度受限,雖然可以擴大 RETURNS

varchar(1000),但總是有最大限制的。

MySQL目前版本( 5.1.33-community)中還不支持function 的遞歸調用。

方法二:利用臨時表和過程遞歸

創建存儲過程如下。createChildLst 為遞歸過程,showChildLst為調用入口過程,準備臨時表及初始化。

mysql> delimiter

//

mysql>

mysql> # 入口過程

mysql> CREATE PROCEDURE showChildLst (IN rootId

INT)

-> BEGIN

->? CREATE TEMPORARY TABLE IF NOT

EXISTS tmpLst

->? ?(sno int

primary key auto_increment,id int,depth int);

->??DELETE FROM

tmpLst;

->

->??CALL

createChildLst(rootId,0);

->

->??select

tmpLst.*,treeNodes.* from tmpLst,treeNodes where

tmpLst.id=treeNodes.id order by tmpLst.sno;

-> END;

-> //

Query OK, 0 rows affected (0.00 sec)

mysql>

mysql> # 遞歸過程

mysql> CREATE

PROCEDURE createChildLst (IN rootId INT,IN nDepth INT)

-> BEGIN

->??DECLARE done

INT DEFAULT 0;

->??DECLARE b

INT;

->??DECLARE cur1

CURSOR FOR SELECT id FROM treeNodes where pid=rootId;

->??DECLARE

CONTINUE HANDLER FOR NOT FOUND SET done = 1;

->

->??insert into

tmpLst values (null,rootId,nDepth);

->

->??OPEN

cur1;

->

->??FETCH cur1

INTO b;

->??WHILE done=0

DO

->

CALL

createChildLst(b,nDepth+1);

->

FETCH cur1

INTO b;

->??END

WHILE;

->

->??CLOSE

cur1;

-> END;

-> //

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

調用時傳入結點

mysql> call

showChildLst(1);

+-----+------+-------+----+----------+------+

| sno | id?? | depth | id |

nodename | pid? |

+-----+------+-------+----+----------+------+

|?? 4

|??? 1

|

0 |? 1 |

A

|??? 0 |

|?? 5

|??? 2

|

1 |? 2 |

B

|??? 1 |

|?? 6

|??? 4

|

2 |? 4 |

D

|??? 2 |

|?? 7

|??? 5

|

2 |? 5 |

E

|??? 2 |

|?? 8

|??? 3

|

1 |? 3 |

C

|??? 1 |

|?? 9

|??? 6

|

2 |? 6 |

F

|??? 3 |

|? 10

|??? 7

|

3 |? 7 |

G

|??? 6 |

+-----+------+-------+----+----------+------+

7 rows in set

(0.13 sec)

Query OK, 0 rows affected, 1 warning (0.14 sec)

mysql>

mysql> call showChildLst(3);

+-----+------+-------+----+----------+------+

| sno | id?? | depth | id |

nodename | pid? |

+-----+------+-------+----+----------+------+

|?? 1

|??? 3

|

0 |? 3 |

C

|??? 1 |

|?? 2

|??? 6

|

1 |? 6 |

F

|??? 3 |

|?? 3

|??? 7

|

2 |? 7 |

G

|??? 6 |

+-----+------+-------+----+----------+------+

3 rows in set

(0.11 sec)

Query OK, 0 rows affected, 1 warning (0.11 sec)

depth

為深度,這樣可以在程序進行一些顯示上的格式化處理。類似于oracle中的?level 偽列。sno

僅供排序控制。這樣你還可以通過臨時表tmpLst與數據庫中其它表進行聯接查詢。

MySQL中你可以利用系統參數 max_sp_recursion_depth 來控制遞歸調用的層數上限。如下例設為12.

mysql> set

max_sp_recursion_depth=12;

Query OK, 0 rows affected (0.00 sec)

優點 : 可以更靈活處理,及層數的顯示。并且可以按照樹的遍歷順序得到結果。

缺點 : 遞歸有255的限制。

方法三:利用中間表和過程

(本方法由yongyupost2000提供樣子改編)

創建存儲過程如下。由于MySQL中不允許在同一語句中對臨時表多次引用,只以使用普通表tmpLst來實現了。當然你的程序中負責在用完后清除這個表。

delimiter

//

drop PROCEDURE IF

EXISTS? showTreeNodes_yongyupost2000//

CREATE PROCEDURE

showTreeNodes_yongyupost2000 (IN rootid INT)

BEGIN

DECLARE Level int ;

drop TABLE IF EXISTS tmpLst;

CREATE TABLE tmpLst (

id int,

nLevel int,

sCort varchar(8000)

);

Set Level=0 ;

INSERT into tmpLst SELECT id,Level,ID FROM

treeNodes WHERE PID=rootid;

WHILE ROW_COUNT()>0 DO

SET Level=Level+1 ;

INSERT into tmpLst

SELECT

A.ID,Level,concat(B.sCort,A.ID) FROM treeNodes A,tmpLst B

WHERE

A.PID=B.ID AND B.nLevel=Level-1 ?;

END WHILE;

END;

//

delimiter

;

CALL

showTreeNodes_yongyupost2000(0);

執行完后會產生一個tmpLst表,nLevel 為節點深度,sCort 為排序字段。

使用方法

SELECT concat(SPACE(B.nLevel*2),'+--',A.nodename)

FROM treeNodes A,tmpLst B

WHERE A.ID=B.ID

ORDER BY B.sCort;

+--------------------------------------------+

| concat(SPACE(B.nLevel*2),'+--',A.nodename) |

+--------------------------------------------+

|

+--A

|

|

+--B

|

|

+--D

|

|

+--E

|

|

+--C

|

|

+--F

|

|

+--G

|

|

+--H

|

|

+--J

|

|

+--K

|

|

+--I

|

|

+--L

|

|

+--N

|

|

+--O

|

|

+--P

|

|

+--Q

|

|

+--M

|

+--------------------------------------------+

17 rows in set (0.00 sec)

總結

以上是生活随笔為你收集整理的mysql6支持connect by_mysql 实现oracle start with connect by递归的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本jizzjizz | 特级西西人体444www高清 | 成人视品 | 青娱乐国产视频 | 久久国产精品久久久久 | 天堂网中文在线观看 | 伦理一级片 | 九九九国产视频 | 婷婷伊人综合 | 欧美成人久久久免费播放 | 色综合久久88色综合天天免费 | 久久久国产精品成人免费 | 清清草在线视频 | 国产在线欧美 | 亚洲国产精品无码久久久久高潮 | 亚洲论理 | 国产午夜片 | 久久成人一区二区 | a一级视频| 久久在线| 九草影院 | 成人深夜福利 | 快乐激情网 | 国产九色sp调教91 | 亚洲一区二区视频在线观看 | 午夜精品久久久久久久四虎美女版 | 中文字幕一区二区三区5566 | www.777奇米 | 国产精品视频a | 欧美日韩黄色片 | 91日本精品 | 国产男女啪啪 | 黄色成人免费视频 | 精品国产av色一区二区深夜久久 | 国产第三页 | 免费在线黄色网址 | 亚洲国产图片 | 午夜影视在线观看 | 波多野结衣黄色 | 国产99久久久 | 91极品国产 | 国偷自拍第113页 | 国产一区在线观看免费 | 日韩视频免费在线 | 伊人av综合 | 极品蜜桃臀肥臀-x88av | 欧美人与性动交g欧美精器 国产在线视频91 | 国产日韩欧美一区二区东京热 | 日本中文字幕一区二区 | 天天色图片 | 婷婷丁香九月 | 色噜噜综合网 | 欧美成人福利 | 日本不卡影院 | 亚洲成人av网址 | 国产女人18毛片水18精 | 欧美成性色 | 四虎国产精品永久在线国在线 | 成人超碰在线 | 黄色特级一级片 | 黄色一级片久久 | 台湾少妇xxxx做受 | 一区免费观看 | av小说免费在线观看 | 亚洲精品二 | 少妇又紧又色又爽又刺激 | 国产小毛片 | 老牛嫩草二区三区观影体验 | 五月天色视频 | 丰满人妻老熟妇伦人精品 | 国产精品18久久久久久vr下载 | 国产在线xxx | 国产日韩一区二区三区在线观看 | 欧美午夜精品久久久久久孕妇 | 国产精品毛片久久久久久 | 日本草草视频 | 亚洲黄色免费视频 | 中文字幕亚洲欧美日韩在线不卡 | 男生看的污网站 | 久久嫩 | 亚洲视频免费在线播放 | 国产亚洲精品久久久久丝瓜 | 福利视频一二区 | 成人h动漫精品一区二区 | 日本一级片在线播放 | 久久叉| 日韩一区二区三区四区 | 欧美三级在线 | www日韩在线| 91香蕉视频污污 | 日韩在线一区视频 | 激情五月在线观看 | 九色porny原创自拍 | 在线黄色观看 | 日韩一级在线观看视频 | 在线观看av一区 | 日韩av中文字幕在线播放 | 亚洲精品网站在线播放gif | 亚洲日本成人在线观看 |