天天看點

Oracle的遞歸查詢

在有時候設計資料庫的時候,資料之間的關系是樹型結構的,什麼是樹型結構呢?比方說:

中國有很多省份,而每個省份又包含了很多市,市裡又包括縣,縣又包括鄉或者鎮,鎮又包括很多村。那麼要把這些資料放到一張表裡怎麼做呢?看看這些資料,是不是很像一顆樹呢?有父節點也有子節點。是以我們就可以用id,parentid來表示,比如說中國的id是1,因為在往上的話就沒有其父節點了,是以parentid可以是0,那麼河北省的id就可以是2,parentid就是1。即河北省的父節點是中國。

在網上找了一段樹型結構的資料,建好表後可以直接插入資料庫

INSERT INTO SC_DISTRICT(ID,NAME) VALUES(1,'四川省');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(2,1,'巴中市');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(3,1,'達州市'); 

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(4,2,'巴州區');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(5,2,'通江縣');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(6,2,'平昌縣');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(7,3,'通川區');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(8,3,'宣漢縣');

INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(9,8,'塔河鄉');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(10,8,'三河鄉');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(11,8,'胡家鎮');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(12,8,'南壩鎮');
 
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(13,6,'大寨鄉');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(14,6,'響灘鎮');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(15,6,'龍崗鎮');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(16,6,'白衣鎮');
           

在Oracle中,可以在select 指令中使用connect by 子句查詢表中的樹型結構關系。指令格式如下:

CONNECT BY {PRIOR 列名1=列名2|列名1=PRIOR 裂名2}

[START WITH];

Connect By子句說明每行資料将是按層次順序檢索,并規定将表中的資料連如樹型結構的關系中。Prior運算符必須放置在連結關系的兩列中某一個的前面,對于節點間父子關系,Prior運算符的一側表示父節點,在另一側表示子節點,進而确定查找樹結構是順序是自頂向下還是自底向上;Start With子句用來辨別哪個節點作為查找樹型結構的根節點。

下面來個簡單的應用:查詢四川省下面的所有地區

select t.id,t.parent_id,t.name from sc_district t connect by prior t.id=t.prent_id start with id='1'
           

start with既可以放在connect by 子句的前面,也可以放在connect by子句的後面,是以上面的語句等同于下面的語句

select t.id,t.parent_id,t.name from sc_district t  start with id='1' connect by prior t.id=t.perent_id</span>
           

查詢結果如下:

Oracle的遞歸查詢

運算符prior被放置于等号前後的位置,決定着查詢時的順序。

如果prior放在connect by子句中等号的前面時,則從根節點和葉節點的檢索,即自頂向下的查詢方式。如果prior放在connect by 子句中等号的後面時,則是自底向下的檢索。比如,上面的sql語句改為這樣就變成了查詢塔河鄉的所有父節點了。

select t.id,t.parent_id,t.name from sc_district  t  start with id='9' connect by t.id= prior t.perent_id
           

查詢結果如下:

Oracle的遞歸查詢

這樣看樹的層次結構,如果樹的層次很多的話看起來就很容易搞混,是以Oracle提供了一個sys_connect_by_path()函數來幫助我們解決這個問題。

         Sys_connect_by_path()函數必須與connect by子句一起使用,參數格式是

sys_connect_by_path(columnName,seperator),其中columnName為要顯示的字段,而seperator則為連接配接各個層次的分隔符。

下面我們來展示一下效果:

select t.id,t.parent_id,t.name,sys_connect_by_path(t.name,'>') from sc_district  t start with t.id='1' connect by prior p.id=p.parent_id
           
Oracle的遞歸查詢

一開始感覺這個遞歸查詢不是很好了解,但是動手去敲,敲了幾遍以後就感覺慢慢的懂了。是以,還是要動手去做。