(轉載)令人迷糊的Oracle遞歸查詢(start with)

来源:https://www.cnblogs.com/ShawnSiao/archive/2018/08/31/9567025.html
-Advertisement-
Play Games

轉載地址:https://blog.csdn.net/weiwenhp/article/details/8218091 備註:如有侵權,請聯繫立即刪除。 寫代碼時碰到要弄清楚Oracle的role之間的傳遞關係,就是有role A的話,可以通過grant A to B,把A賦予給B,又通過grant ...


轉載地址:https://blog.csdn.net/weiwenhp/article/details/8218091

備註:如有侵權,請聯繫立即刪除。

寫代碼時碰到要弄清楚Oracle的role之間的傳遞關係,就是有role A的話,可以通過grant A to B,把A賦予給B,又通過grant B to C .那我想知道所有role中,有哪些role具有A的許可權.

上網一查發現有個遞歸查詢,不過都講的不是太詳細,而那Oracle整的那用法實在太怪異了,跟我們平時用的SQL差的太遠,所以琢磨了好一陣子腦子才轉過彎呢.

樹形結構

可能一看到遞歸查詢這樣太專業的名詞大家就迷糊了.實際上可以看成有一個樹形結構,然後我們要怎麼把所有樹的所有結點查找出來.學數據結構的時候我們知道要遍歷一個樹結構有啥前序遍歷,中序遍歷,後序遍歷.反正挺麻煩的.不像遍歷個數組那麼容易的.那實際上在Oracle的一個表中也可以保存樹形結構信息.你要查詢所有的樹節點,自己整個函數或存儲過程去整肯定是超級麻煩的.Oracle提供了一個簡單的機制幫助你.要用到start with ...connect by等關鍵字.先來假定有下麵這樣一個簡單的樹形結構存儲在表中.

create table Tree(son char(10), father char(10)); 然後插入些信息變成這樣的表

 

SON            FATHTER

孫子SB         兒子

孫子NB         兒子

兒子             爸爸

爸爸             爺爺

 

很顯然這是一個簡單的樹形結構

                           孫子SB

                             ^

                             |

爺爺 --> 爸爸 --> 兒子 -->孫子NB

                          

 

遞歸查詢

假如要查詢出以爺爺為根的樹的所有節點值咋整呢 ?如果數據少多來幾個where嵌套就行.但要是樹層次有幾百那會搞死人了啊.於是我們就用Oracle提供的遞歸查詢.先看下SQL的寫法然後再講解

SELECT  son FROM tree

START WITH father = '爺爺'

CONNECT BY PRIOR son = father;

返回的結果為 爸爸 兒子 孫子NB 孫子SB

代碼看起來很短,但是極為怪異,腦子半天都不容易轉過彎呢.實際上我們不把這個SQL語句跟一般的SQL類比,而把它當作給一些函數指定一些參數的賦值語句才更容易理解.

那怎麼來理解上面的SQL呢?

首先把SELECT son FROM tree還是看成一般sql一樣,就是要查找son這一列的信息.而把以START WITH開頭的後面所有東東看成一個where限制條件.其中START WITH 是指定

樹的根,這裡指定的根是 '爺爺',實際上你還可以指定多個根的,比如 father in ('爺爺', '爸爸') .

而CONNECT BY PRIOR son = father相當於表明在遞歸的過程中,查找到的樹中其它節點接著又作為根結點.然後繼續遞歸. 反正看這sql語句前先想下樹形結構,然後想下一般編程語言中的遞歸函數.再來看時就容易理解點.實際上我覺得Oracle這樣設計不太好.如果用戶只是簡單的指定的一個根節點然後知道樹中其他節點信息.那麼就直接用START WITH指定根就行了.CONNECT BY PRIOR顯得有點多餘,可以不用用戶去指定.當作一個預設值,只有需要其他一些更複雜的操作時才讓用戶明確指定.這樣就不容易誤導人了.

為了便於理解可以可以CONNECT BY那一行當作多餘的,只記住要查詢的列名放前面,根列名放等號後面就行.這樣只要指定樹的根結點就比較好理解了.

 

start with ,connect by prior其他變形

上面講的用START WITH 指定樹的根,然後用CONNECT BY指定遞歸條件.是最簡單的也是最常用的形式.但實際上還有些變形.

1.START WITH 可以省略

比如

SELECT son FROM tree

CONNECT BY PRIOR son = father;

此時不指定樹的根的話,就預設把Tree整個表中的數據從頭到尾遍歷一次,每一個數據做一次根,然後遍歷樹中其他節點信息.

在這個例子中,上面的SQL等價於

SELECT son FROM tree

START WITH father IN (爺爺,爸爸,兒子,孫子NB,孫子SB)

CONNECT BY PRIOR son = father;

那查詢到的結果如下,有很多重覆信息的

爸爸,兒子,孫子NB,孫子SB    兒子,孫子NB,孫子SB    孫子NB,孫子SB

 

2.START WITH 與CONNECT BY PRIOR位置可互換

 

SELECT son FROM tree

CONNECT BY PRIOR son = father

START WITH father = '爺爺';

這語句與最開頭那個是等價的

 

3.nocycle關鍵字

我們知道標準的樹結構中是不會有環的,但表中的樹形結構不是標準的,有可能導致環的出現

比如

             ---------孫子SB

             |              ^

             |              |

爺爺 --> 爸爸 --> 兒子 -->孫子NB

哎在這裡想用線條整個箭頭出來真他媽麻煩啊.我又有點懶不想用其他畫圖工具啥的啊.反正假設兒子的兒子是孫子SB ,而孫子SB的兒子是爸爸.這樣就形成一個環了.

當然在Oracle中的role是禁止出現迴圈的.比如你grant A to B ,grant B to C .再來個grant C to A會出錯的.

假如有個上面的環,在再使用開始的遞歸查詢語言會出錯.得用nocycle關鍵字指定忽略環.

SELECT son FROM tree

START WITH father = '爺爺'

CONNECT BY NOCYCLE PRIOR son = father;

此時結果是

爸爸 兒子 孫子NB

你會註意到由於忽略了環,所以孫子SB的信息也被忽略掉了.

 

4. connect by prior 後麵條件順序的改變 (???)

SELECT son FROM tree

START WITH father = '爺爺'

CONNECT BY PRIOR son = father;

這是開頭的寫法,但實際上也可以寫成father = son倒過來寫.有人說沒倒過來是從上到下,從根往下.如果倒過來則是從下到上.哎不過我測試了下發現不是那麼回事.結果也有點亂七八糟的.沒想明白是啥規律.反正還有待研究啊

 

5.還可以加where條件

我上面說了可以把start with ,connect 假裝看成where 條件一樣.所以在這個sql語句其他地方還可以加其他where 語句,可以看成與遞歸查詢無關.只是對整個結果起過濾作用

比如

SELECT son FROM tree  WHERE son = '孫子SB'

START WITH father = '爺爺'

CONNECT BY PRIOR son = father;

 

當然你不能在最後部分加where,不能在connect by最後面再加.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 LINUX COMMAND 1.1 cat 1.2 ls 1.3 echo 1.4 sort 1.5 awk 1.6 df 1.7 du 1.8 fsck 1.9 dumpe2fs 1.10 rpm 1.10.1 RPM校驗 1.10.2 RPM包中文件提取 1.10.3 源碼包與RPM包的區別 ...
  • 1.下載mysql的綠色版壓縮包。(自行百度) 2.自行規劃目錄解壓 3.安裝 註意:我遇到的兩種版本的安裝方法(暫時按照解壓後的目錄中是否含有data目錄來區分) 3.1 無data目錄(我用到的的是5.7的版本) 3.1.1 配置環境變數 path環境變數 追加 D:\depemt\mysql- ...
  • 這個警告在常規場景中沒什麼影響,但如果是用excel跑SQL,它會因為該警告阻止你的後續操作~事實上excel執行sql限制多多,需要更多的奇技淫巧,之前我就寫過一篇。言歸正傳,要解決這個警告,一種當然是在語句中用到聚合函數的地方統統加上isnull,但如果語句很長,地方很多就蛋疼了,於是我推薦另一 ...
  • 前言 近幾個月一直在忙些瑣事,幾乎年後都沒怎麼閑過。忙忙碌碌中就進入了2018年的秋天了,不得不感嘆時間總是如白駒過隙,也不知道收穫了什麼和失去了什麼。最近稍微休息,買了兩本與技術無關的書,其一是Yann Martel 寫的《The High Mountains of Portugal》(葡萄牙的... ...
  • 說明:這篇文章是幾年前我發佈在網易博客當中的原創文章,但由於網易博客現在要停止運營了,所以我就把這篇文章搬了過來,雖然現如今SQL Server 2000軟體早已經過時了,但仍然有一部分人在使用它,尤其是某些高校的學生在做畢業設計或者課程設計的時候可能會使用到,所以就把該軟體的資料庫還原過程保留在這 ...
  • 說明:這篇文章是幾年前我發佈在網易博客當中的原創文章,但由於網易博客現在要停止運營了,所以我就把這篇文章搬了過來,雖然現如今SQL Server 2000軟體早已經過時了,但仍然有一部分人在使用它,尤其是某些高校的學生在做畢業設計或者課程設計的時候可能會使用到,所以就把該軟體的安裝過程保留在這裡吧。 ...
  • 一.概述 mysqlcheck客戶端工具可以檢查和修複MyISAM表,還可以優化和分析表。實際上,它集成了mysql工具中check,repair,analyze,optimize功能,對於check 則不支持MEMORY表, repair 則不支持 InnoDB表。mysqlcheck只有在資料庫 ...
  • 轉載地址:https://www.cnblogs.com/linjiqin/p/3152674.html 備註:如有侵權,請立即聯繫刪除。 oracle樹查詢的最重要的就是select…start with…connect by…prior語法了。依托於該語法,我們可以將一個表形結構的以樹的順序列出 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...