日韩性视频-久久久蜜桃-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递归的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产老头和老头xxxx× | 久久麻豆视频 | www.色妞| a一级黄色 | 中文字幕视频免费观看 | 六月激情网 | 黄色xxxxxx| 肉色丝袜脚交一区二区 | 爱如潮水3免费观看日本高清 | 精品在线小视频 | 亚洲色图40p| 国产欧美日韩激情 | 色小姐在线视频 | 91av不卡| 日韩一级伦理片 | 久久精品视频在线 | 91麻豆蜜桃一区二区三区 | 久久青青草原 | 我和我的太阳泰剧在线观看泰剧 | 国产在线视频在线观看 | 在线观看免费av网址 | 污在线观看 | 日韩视频区 | 国精品一区二区三区 | 交专区videossex农村 | 日本在线视频二区 | 91人人爽 | 欧美怡红院视频 | 美国黄色片网站 | 色网导航站 | 免费的av | 四虎影院黄色 | 久久久888| 日本欧美在线 | 亚洲人掀裙打屁股网站 | av第一页| 欧美影视一区 | 亚洲自拍偷拍一区 | 国产免费视屏 | 色老板精品凹凸在线视频观看 | 亚洲夜夜爱 | www国产黄色 | 天天搞天天搞 | 久久国产主播 | 日韩人妻一区二区三区蜜桃 | 亚洲国产精彩视频 | 久久cao| 国产精品无码久久久久一区二区 | 97视频免费在线观看 | 成人性生交大片免费卡看 | 久久久天堂国产精品女人 | 好姑娘在线观看高清完整版电影 | 欧美性黄色 | 日韩专区第一页 | 免费在线看视频 | √天堂在线 | 久久久国产精品黄毛片 | 亚洲色图在线观看 | 一本一道久久综合狠狠老精东影业 | 国产黑丝91 | 啊v视频在线 | 中文字幕巨乳 | 国产精品无码影院 | 免费看毛片网站 | 久久网免费视频 | 亚洲熟伦熟女新五十路熟妇 | 午夜神器在线观看 | 日韩有码中文字幕在线 | 日日噜噜噜夜夜爽爽狠狠 | 免费黄色国产视频 | 日韩成人av网址 | 久久精品国产77777蜜臀 | 久久中文字幕在线观看 | 国产资源一区 | 男人av网站 | av资源在线看 | 亚洲av无码国产精品色午夜 | 成年人看的黄色 | 日本大乳美女 | 国产免费一区视频观看免费 | 少妇人妻好深好紧精品无码 | 手机av在线免费观看 | 性猛交富婆╳xxx乱大交麻豆 | 日韩一卡二卡在线 | 日韩一级片在线 | 亚洲精品精品 | 91免费观看入口 | 99热这里只有精品2 91免费版黄 | 国产在线播 | a毛毛片 | 深夜激情影院 | www.伊人久久 | 日韩国产欧美 | 国产精品一二三四五 | 久久性精品| 羞羞漫画在线 | 亚洲自拍偷拍一区二区 | 国产精品永久免费视频 | 成人人伦一区二区三区 |