淺談oracle樹狀結構層級查詢html
oracle樹狀結構查詢即層次遞歸查詢,是sql語句常常用到的,在實際開發中組織結構實現及其層次化實現功能也是常常遇到的,雖然我是一個java程序開發者,我一直以爲只要精通數據庫那麼對於java開發你就成功了三分之一,本篇中主要介紹start with...connect by prior 、order by 、sys_connect_by_path。java
概要:樹狀結構一般由根節點、父節點、子節點和葉節點組成,簡單來講,一張表中存在兩個字段,dept_id,par_dept_id,那麼經過找到每一條記錄的父級id便可造成一個樹狀結構,也就是par_dept_id(子)=dept_id(父),通俗的說就是這條記錄的par_dept_id是另一條記錄也就是父級的dept_id,其樹狀結構層級查詢的基本語法是:面試
SELECT [LEVEL],*sql
FEOM table_name 數據庫
START WITH 條件1oracle
CONNECT BY PRIOR 條件2函數
WHERE 條件3學習
ORDER BY 排序字段測試
說明:LEVEL---僞列,用於表示樹的層次優化
條件1---根節點的限定條件,固然也能夠放寬權限,以得到多個根節點,也就是獲取多個樹
條件2---鏈接條件,目的就是給出父子之間的關係是什麼,根據這個關係進行遞歸查詢
條件3---過濾條件,對全部返回的記錄進行過濾。
排序字段---對全部返回記錄進行排序
對prior說明:要的時候有兩種寫法:connect by prior dept_id=par_dept_id 或 connect by dept_id=prior par_dept_id,前一種寫法表示採用自上而下的搜索方式(先找父節點而後找子節點),後一種寫法表示採用自下而上的搜索方式(先找葉子節點而後找父節點)。
樹狀結構層次化查詢須要對樹結構的每個節點進行訪問而且不能重複,其訪問步驟爲:
大體意思就是掃描整個樹結構的過程即遍歷樹的過程,其用語言描述就是:
步驟一:從根節點開始;
步驟二:訪問該節點;
步驟三:判斷該節點有無未被訪問的子節點,如有,則轉向它最左側的未被訪問的子節,並執行第二步,不然執行第四步;
步驟四:若該節點爲根節點,則訪問完畢,不然執行第五步;
步驟五:返回到該節點的父節點,並執行第三步驟。
除此以外,sys_connect_by_path函數是和connect by 一塊兒使用的,在實戰中具體帶目的具體介紹!
實戰:最近作項目的組織結構,對於部門的各級層次顯示,因爲這部分掌握不牢固,用最笨的like模糊查詢解決了,雖然功能實現了,可是問題不少,如擴展性很差,稍微改下需求就要進行大改,不滿意最後對其進行了優化。在開發中能用數據庫解決的就不要用java去解決,這也是我一直保持的想法並堅持着。
對於建表語句及其測試數據我放在另一篇博客中,須要進行測試的能夠過去拷貝運行測試驗證下!
博客地址:淺談oracle樹狀結構層級查詢測試數據
在這張表中有三個字段:dept_id 部門主鍵id;dept_name 部門名稱;dept_code 部門編碼;par_dept_id 父級部門id(首級部門爲 -1);
select t.dept_id, t.dept_name, t.dept_code, t.par_dept_id, level
from SYS_DEPT t
start with t.dept_id = '40288ac45a3c1e8b015a3c28b4ae01d6'
connect by prior t.dept_id = t.par_dept_id
order by level, t.dept_code
結果:
dept_id=40288ac45a3c1e8b015a3c28b4ae01d6 是客運部主鍵,對其下的全部子部門進行遍歷,同時用 order by level,dept_code 進行排序 以便達到實際生活中想要的數據;共31條數據,部分數據如圖所示:
可是:
有問題啊,若是你想在上面的數據中獲取層級在2也就是level=2的全部部門,發現剛開始的時候介紹的語言不起做用?而且會報ORA-00933:sql命令未正確結束,why?
這個我暫時也沒有獲得研究出理論知識,可是改變下where level='2'的位置發現纔會能夠的。錯誤的和正確的sql咱們對比一下,之後會用就行,要是路過的大神知道爲何,還請告知下,萬分感謝!
錯誤sql:
select t.dept_id, t.dept_name, t.dept_code, t.par_dept_id, level
from SYS_DEPT t
start with t.dept_id = '40288ac45a3c1e8b015a3c28b4ae01d6'
connect by prior t.dept_id = t.par_dept_id
where level = '2'
order by level, t.dept_code
select t.dept_id, t.dept_name, t.dept_code, t.par_dept_id, level
from SYS_DEPT t
where level = '2'
start with t.dept_id = '40288ac45a3c1e8b015a3c28b4ae01d6'
connect by prior t.dept_id = t.par_dept_id
order by level, t.dept_code
固然了,這個對其餘形式的where過濾全部返回記錄沒有影響的,這個只是一個例外!
sys_connect_by_path函數求父節點到子節點路徑
簡單介紹下,在oracle中sys_connect_by_path與connect by 一塊兒使用,也就是先要有或創建一棵樹,不然無用還會報錯。它的主要做用體如今path上即路徑,是能夠吧一個父節點下的全部節點經過某個字符區分,而後連接在一個列中顯示。
sys_connect_by_path(column,clear),其中column是字符型或能自動轉換成字符型的列名,它的主要目的就是將父節點到當前節點的「path」按照指定的模式出現,char能夠是單字符也能夠是多字符,但不能使用列值中包含的字符,並且這個參數必須是常量,且不容許使用綁定變量,clear不要用逗號。
文字容易讓人疲勞,放圖和代碼吧!
select sys_connect_by_path(t.dept_name,'-->'),t.dept_id, t.dept_name, t.dept_code, t.par_dept_id, level from SYS_DEPT t start with t.dept_id = '40288ac45a3c1e8b015a3c28b4ae01d6' connect by prior t.dept_id = t.par_dept_id order by level, t.dept_code
結果:
結束語
一個坑兩週時間填平,最近終於休息閒了下來,整理整理加深記憶,好記性不如爛筆頭,不要高估本身的記性,許久不用很快就會忘記的,在學習的道路上,但願本身也但願各位路過的同行不要放棄學習,任重而道遠!如今的我很菜,之後我會成爲大神!哈哈,意淫一下!
愛人是路,朋友是樹,人生有一條路,一條路上有許多樹,有錢的時候別迷路,缺錢的時候靠靠樹,幸福的時候莫忘路,休息的時候澆澆樹。
開心一樂
驚弓之鳥——說的是去面試的剛畢業大學生,一聽到用人單位提到行業經驗就落荒而逃的事情;
上聯:作 I T 風風雨雨 又一年下聯:賣電腦 辛辛苦苦 每一天橫批:從小不學好,長大賣電腦!