oracle中能夠用CONNECT BY子句實現遞歸查詢,其基本語法是:
select ... from <TableName>
where <Conditional-1>
start with <Conditional-2>
connect by [nocycle]<Conditional-3>
order siblings by <conditional-4>;
<Conditional-1>:過濾條件,用於對返回的全部記錄進行過濾。(關聯條件和過濾條件有區別,關聯條件最早執行)
<Conditional-2>:根節點條件,只用於第一次過濾出根節點。
<Conditional-3>:鏈接條件,nocycle關鍵字,防止循環;prior操做符,用於層級條件,沒有prior操做符不會發生層級關聯,一個connect by語句中能夠有多個prior條件,也能夠有其餘普通條件,可是prior不能用於sequence序列。
<conditional-4>:同級節點排序條件。sql
執行順序:
一、語句中有多表關聯,先執行關聯,不管是join仍是where條件中的關聯條件。
二、執行start with的條件,選出第一個節點。
三、執行connect by 的條件,層級關聯,選出子節點。
四、執行where中的過濾條件,排除結果集中不知足條件的記錄,可是不會由於排除一條記錄而把它對應的子節點排除。
五、執行order siblings by的排序條件,對同級節點排序。oracle
僞劣:
level:標記層級級數,最上層節點爲1,以後爲二、3……。
CONNECT_BY_ISCYCLE:標記此節點是否爲某一個祖先節點的父節點,致使循環,1爲是,0爲否。
CONNECT_BY_ISLEAF :標記此節點是否爲葉子節點,即沒有子節點,1爲是,0爲否。
CONNECT_BY_ROOT:標記此節點的祖先節點,後面加列名或表達式,取祖先節點的記錄值。函數
SYS_CONNECT_BY_PATH(column,char) 函數:記錄根節點到此節點的路徑,column是每一個節點的路徑值,以char分割。column和char都必須是char,varchar2,nchar,或者nvarchar2。
例如:LPAD(' ', 2*level-1)||SYS_CONNECT_BY_PATH(last_name, '/') "Path"表示以last_name爲路徑,'/'分割,記錄根到節點的全路徑。lpad是優化顯示。測試
(如下來自網上)例子:優化
select a.child, a.parent, level "層次", sys_connect_by_path(child, '->') "合併層次", prior a.child "父節點", connect_by_root a.child "根節點", decode(connect_by_isleaf, 1, a.child, null) "子節點", decode(connect_by_isleaf, 1, '是', '否') "是否子節點" from test_connect_by a start with a.parent is null --從parent爲空開始掃描 connect by prior a.child = a.parent --以child爲父列鏈接parent order siblings by child desc --對層次排序 ;
一個特殊的使用,使用connect by rownum<=N可使表的第一行重複N次,若是無記錄則無效果:
生成1到10的序列:code
SQL> SELECT ROWNUM FROM DUAL CONNECT BY ROWNUM <= 10; ROWNUM ---------- 1 2 3 4 5 6 7 8 9 10 10 rows selected
藉助這個功能,拆分字符串的每個字符:對象
CREATE OR REPLACE FUNCTION f_hex_to_dec(p_str IN VARCHAR2) RETURN VARCHAR2 IS ---------------------------------------------------------------------------------------------------------------------- -- 對象名稱: f_hex_to_dec -- 對象描述: 十六進制轉換十進制 -- 輸入參數: p_str 十六進制字符串 -- 返回結果: 十進制字符串 -- 測試用例: SELECT f_hex_to_dec('78A') FROM dual; ---------------------------------------------------------------------------------------------------------------------- v_return VARCHAR2(4000); BEGIN SELECT SUM(DATA) INTO v_return FROM (SELECT (CASE upper(substr(p_str, rownum, 1)) WHEN 'A' THEN '10' WHEN 'B' THEN '11' WHEN 'C' THEN '12' WHEN 'D' THEN '13' WHEN 'E' THEN '14' WHEN 'F' THEN '15' ELSE substr(p_str, rownum, 1) END) * power(16, length(p_str) - rownum) DATA FROM dual CONNECT BY rownum <= length(p_str)); RETURN v_return; EXCEPTION WHEN OTHERS THEN RETURN NULL; END;