SQL遞迴查詢(SqlServer/ORACLE遞迴查詢)[文法差異分析]

來源:互聯網
上載者:User

在 SQLSERVER2005以後,mssql開始有了遞迴查詢的方法了。比較起最開始寫預存程序或者寫function的方式。這樣的方式更加簡便靈活的。

而oracle也有內建的樹形結構遞迴查詢方法,connect by

下面我自己寫的一段SQL,簡單注釋下CTE共用運算式的一些用法。 實現對樹狀結構的根節點和子節點的查詢。

代碼------------------------------------------------------------------------
-- author:jc_liumangtu(【DBA】小七)
-- date:    2010-03-30 15:09:42
-- version:
-- Microsoft SQL Server 2005 - 9.00.1399.06 (Intel X86)
--     Oct 14 2005 00:33:37
--     Copyright (c) 1988-2005 Microsoft Corporation
--     Developer Edition on Windows NT 5.1 (Build 2600: Service Pack 3)
--
------------------------------------------------------------------------
use test
set nocount on
if object_id('Dept','U') is not null
drop table Dept
go
create table Dept(ID int,ParentID int,Name varchar(20))  
insert into Dept select 1,0,'AA'
insert into Dept select 2,1,'BB'
insert into Dept select 3,1,'CC' 
insert into Dept select 4,2,'DD' 
insert into Dept select 5,3,'EE' 
insert into Dept select 6,0,'FF'
insert into Dept select 7,6,'GG'
insert into Dept select 8,7,'HH'
insert into Dept select 9,7,'II'
insert into Dept select 10,7,'JJ'
insert into Dept select 11,9,'KK'

go  
SELECT * FROM Dept;

--查詢樹狀結構某節點的上級所有根節點。
with cte_root(ID,ParentID,NAME)
as
(
    --起始條件
    select ID,ParentID,NAME
    from Dept
    where Name = 'II'   --列出子節點查詢條件
    union all
    --遞迴條件
    select a.ID,a.ParentID,a.NAME
    from Dept a
    inner join
    cte_root b          --執行遞迴,這裡就要理解下了
    on a.ID=b.ParentID  --根據基礎資料表條件查詢子節點(a.ID),通過CTE遞迴找到其父節點(b.ParentID)。
)                       --可以和下面查詢子節點的cte_child對比。
select * from cte_root ;

--查詢樹狀結構某節點下的所有子節點。
with cte_child(ID,ParentID,NAME)
as
(
    --起始條件
    select ID,ParentID,NAME
    from Dept
    where Name = 'II' --列出父節點查詢條件
    union all
    --遞迴條件
    select a.ID,a.ParentID,a.NAME
    from Dept a
    inner join
    cte_child b
    on ( a.ParentID=b.ID)  --根據查詢到的父節點(a.Parent),通過CTE遞迴查詢出其子節點(b.ID)
)

select * from cte_child --可以改變之前的查詢條件'II'再測試結果

ID          ParentID    Name
----------- ----------- --------------------
1           0           AA
2           1           BB
3           1           CC
4           2           DD
5           3           EE
6           0           FF
7           6           GG
8           7           HH
9           7           II
10          7           JJ
11          9           KK

ID          ParentID    NAME
----------- ----------- --------------------
9           7           II
7           6           GG
6           0           FF

ID          ParentID    NAME
----------- ----------- --------------------
9           7           II
11          9           KK
複製代碼

在msdn中介紹了CTE的一些限制:

至少有一個錨點成員和一個遞迴成員,當然,你可以定義多個錨點成員和遞迴成員,但所有錨點成員必須在遞迴成員的前面
錨點成員之間必須使用UNION ALL、UNION、INTERSECT、EXCEPT集合運算子,最後一個錨點成員與遞迴成員之間必須使用UNION ALL,遞迴成員之間也必須使用UNION ALL串連
錨點成員和遞迴成員中的欄位數量和類型必須完全一致
遞迴成員的FROM子句只能引用一次CTE對象
遞迴成員中不允許出現下列項
    SELECT DISTINCT
    GROUP BY
    HAVING
    標量彙總
    TOP
    LEFT、RIGHT、OUTER JOIN(允許出現 INNER JOIN)
    子查詢

接下來介紹下Oracle裡面的遞迴查詢方法,connect by prior ,start with。相對於SqlServer來說,Oracle的方法更加簡潔明了,簡單易懂。很容易就讓人理解其用法。借來我會用和上面SqlServer同樣的資料和結構進行代碼示範,和對一些關鍵字的用法進行闡述。

SELECT …..

CONNECT BY {PRIOR 列名1=列名2|列名1=PRIOR 列名2}
[START WITH];

下面是代碼測試:

代碼--建立表
create table Dept(ID int,ParentID int,Name varchar(20));
--增加測試資料,和上面的SqlServer資料相同
insert into Dept  select 1,0,'AA' from dual;
insert into Dept  select 2,1,'BB' from dual;
insert into Dept  select 3,1,'CC'  from dual;
insert into Dept  select 4,2,'DD'  from dual;
insert into Dept  select 5,3,'EE'  from dual;
insert into Dept  select 6,0,'FF' from dual;
insert into Dept  select 7,6,'GG' from dual;
insert into Dept  select 8,7,'HH' from dual;
insert into Dept  select 9,7,'II' from dual;
insert into Dept  select 10,7,'JJ' from dual;
insert into Dept  select 11,9,'KK' from dual;
commit;

--查詢根節點(父節點)
select * from Dept            --查詢基礎資料表
connect by id=prior parentid  --connect by就是欄位的關聯關鍵字,prior有預先和前的意思,則是放在哪個欄位前,哪個就是遞迴的上一層
start with name='II';         --start with則是遞迴的起始位置,也可以用id或者是parentid。可以修改II的值測試其他資料。

--查詢結果
ID    PARENTID    NAME
9      7            II
7      6            GG
6      0            FF

--查詢子節點

select * from Dept
connect by prior id=parentid  --同樣的語句,僅僅改變prior位子,就發生了指向性的變化,就是這裡id為遞迴上一層。
start with name='II';

--查詢結果
ID    PARENTID    NAME
9       7            II
11    9            KK

--測試結果和SqlServer一致,語句卻更精練,簡潔易懂。複製代碼

經過分別對SqlServer和Oracle的測試,發現兩個資料庫都很好的支援遞迴查詢,相比之下Oracle的遞迴查詢語句更加簡練易懂,更容易讓人理解。

在做測試的時候,SqlServer更方便的產生測試資料,上面的代碼可以複製後重複執行,而Oracle複製執行一次可以,重複執行的話,在執行建立表的工作,就會報錯了,原因很簡單,Oracle要判斷表存在然後刪除後重建的工作用代碼實現很麻煩。而SqlServer只需要if後drop表再create就搞定。所以兩種資料庫各有千秋。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.