oracle 数据库中 connect by 和level 的用法
?這幾天看sql看到了有關(guān)connect by和level的關(guān)鍵字用法,以前都用mysql也沒用過這個(gè)關(guān)鍵字,感覺挺有用的,就學(xué)了下,整理一下學(xué)習(xí)過程。
??????首先,connect by和level都是為了快速的查詢層級(jí)關(guān)系的關(guān)鍵字,在代理關(guān)系中,或者權(quán)限關(guān)系中,經(jīng)常會(huì)有層層嵌套的場(chǎng)景,比如,同行數(shù)據(jù)的第一個(gè)字段是ID,第二個(gè)字段是parentID,parentID表示他的上級(jí)ID是誰。
???????如一條數(shù)據(jù),ID為1,parentID為0,表示沒有上級(jí),即頂層,grade 為老板
???????第二條數(shù)據(jù),ID為2,parentID為1,表示上級(jí)為1,grade 為總監(jiān)
????????第三條數(shù)據(jù),ID為3,parentID為2,表示上級(jí)為2,grade 為經(jīng)理
????????這就是一個(gè)三級(jí)的層級(jí)關(guān)系事例。
??????在這種情況下,如果想知道某個(gè):比如 一級(jí)代理的所有二級(jí)代理和三級(jí)代理的有關(guān)行是誰,就很麻煩了。如果使用mysql數(shù)據(jù)庫(kù),就有兩種方法
MYSQL
???????第一種是在java代碼或者別的service層,或工具層中編寫有關(guān)層級(jí)關(guān)系解析的方法代碼,然后把解析的數(shù)據(jù)放在redis或者map中(如果不放在redis 或者map中,數(shù)據(jù)量大的時(shí)候,每次調(diào)用關(guān)系都要重新算一遍是很大的消耗)。
???????第二種是在mysql數(shù)據(jù)庫(kù)中編寫相對(duì)的存儲(chǔ)過程,在select 查詢的時(shí)候調(diào)用自己封裝好的方法,獲取相應(yīng)的數(shù)據(jù)庫(kù)信息。
???但是oracle 中,則很貼心的提供了對(duì)應(yīng)的方法來解決上述的問題,這就是關(guān)鍵字:connect by?
????????其實(shí)簡(jiǎn)單來說,其基本語法是????
???select …,level from tablename???????start with 條件1connect by???prior 子字段id=父字段idwhere 條件3;???????例子:
??????SELECT a.FUNCID,a.PARENTID,LEVEL FROM AUTH_FUNC a START WITH a.FUNCID=3173
??????CONNECT BY PRIOR ?a.FUNCID = a.PARENTID;
?????????以上述模板為例,LEVEL是查詢的層級(jí),START WITH a.FUNCID=3173,表示從該條件開始尋找層級(jí)關(guān)系,CONNECT BY PRIOR a.FUNCID=a.PARENTID 代表,優(yōu)先按照a.FUNCID當(dāng)做基礎(chǔ),該例中(PARENTID的值,綁定的是FUNCID),所以查找FUNCID=3173的所有兒子孫子,及其層級(jí)(兒子LEVEL是2,孫子LEVEL是3)【即查詢所有的兒子孫子等等】
范例一:優(yōu)先查詢3174(父節(jié)點(diǎn))的所有孩子
?????????如果變成CONNECT BY a.FUNCID= PRIOR a.PARENTID,則代表起始為a.FUNCID=3173,優(yōu)先按照PARENTID查找,即尋找FUNCID=3173這條數(shù)據(jù)的所有父節(jié)點(diǎn)行。【查詢所有的父節(jié)點(diǎn)】
范例二:優(yōu)先查詢3174(子節(jié)點(diǎn))所有父節(jié)點(diǎn)
??????????這里有點(diǎn)難以理解,但是其實(shí)就是如果,PRIOR 放在父字段端,就是尋找STRAT WITH 標(biāo)注節(jié)點(diǎn)的所有的子節(jié)點(diǎn),如果PRIOR 放在子字段端,就是尋找STRAT WITH 標(biāo)注節(jié)點(diǎn)的所有的父節(jié)點(diǎn)
??????????????因?yàn)橐粋€(gè)兒子只有一個(gè)父親,而一個(gè)父親可能有多個(gè)兒子,所以當(dāng)PRIOR放在父字段端的時(shí)候,可能有多個(gè)層級(jí)族,因?yàn)樵谡覂鹤印.?dāng)放在子字段端的時(shí)候,最多只會(huì)有一個(gè)層級(jí)族,因?yàn)?#xff0c;他在找爸爸。
???????關(guān)于?connect by 和level 還有startwith 的詳細(xì)介紹和延伸,我在學(xué)習(xí)過程中,找到了兩個(gè)很好的博客,在此就不轉(zhuǎn)載了,直接轉(zhuǎn)網(wǎng)址了,以供以后自己學(xué)習(xí)和看此篇博客的人學(xué)習(xí)。
???????oracle connect by用法篇:https://blog.csdn.net/wang_yunj/article/details/51040029/
???????Oracle中start with...connect by子句的用法:http://www.blogjava.net/xzclog/archive/2010/03/05/314642.html
????????看完這兩篇博客,應(yīng)該是能懂很多東西的,我這里在嘗試和學(xué)習(xí)的過程中,也做了一些事例,如果在有oracle數(shù)據(jù)庫(kù),且想很快形象的學(xué)習(xí)有關(guān)這塊知識(shí),也可以直接在oracle中執(zhí)行我的事例代碼,配上注釋,應(yīng)該能簡(jiǎn)單不少。
?????????后續(xù)如果有更多的相關(guān)知識(shí),會(huì)在加在下面的
??????????事例代碼
?????????
--關(guān)于LEVEL,START WITH CONNECT BY 的例子
--創(chuàng)建數(shù)據(jù)庫(kù)實(shí)例 CREATE TABLE "CHANNEL"."AUTH_FUNC" ( "FUNCID" VARCHAR2(255) NOT NULL , "PARENTID" VARCHAR2(255) NOT NULL , PRIMARY KEY ("FUNCID") ) NOCOMPRESS ;?
INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3173', '0'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3174', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3175', '3174'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3176', '3174'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3177', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3178', '3177'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3179', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3180', '3179'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3181', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3182', '3181'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3183', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3184', '3183'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3185', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3186', '3173'); INSERT INTO "AUTH_FUNC" ("FUNCID", "PARENTID") VALUES ('3187', '3173'); select * from AUTH_FUNC order by parentid;
?
--輸出從1到100
?
--輸出所有數(shù)據(jù),這個(gè)時(shí)候,因?yàn)闆]有在條件中設(shè)置層級(jí)關(guān)系,所以LEVEL為多大都不影響結(jié)果
--輸出所有數(shù)據(jù),這個(gè)時(shí)候,因?yàn)闆]有在條件中設(shè)置層級(jí)關(guān)系,所以LEVEL為多大都不影響結(jié)果
--但是此條中將LEVEL加入了WHERE條件,所以查詢結(jié)果受影響
?
--以上語句只是為了方便理解LEVEL,他其實(shí)就是一個(gè)可以當(dāng)做條件的,
--限制或表現(xiàn)層數(shù)的方法字段
?
?
--接下來是CONNECT BY的用法
--想找到父節(jié)點(diǎn)是0開始的所有相關(guān)子節(jié)點(diǎn)及其層數(shù)
--也就是FUNCID 為3173的所有子節(jié)點(diǎn)(從父節(jié)點(diǎn)從父級(jí),從上往下查找,可能獲得多個(gè)子集分支)
?
--將PRIOR 放在等于號(hào)后面,將會(huì)獲得不同的結(jié)果(從子節(jié)點(diǎn)開始查詢,獲取上層節(jié)點(diǎn))
--因?yàn)樵撎嶧UNCID 就為頂級(jí),作為子節(jié)點(diǎn)查詢的話,肯定只有一條
--原因就是,PRIOR是優(yōu)先級(jí)的意思,放在前面或者后面,或者調(diào)換等于號(hào)兩遍的條件順序都會(huì)獲得相反的結(jié)果
?
?
--如這個(gè)例子,就表示了以FUNCID 3175開始,從子節(jié)點(diǎn)遍歷獲取上層節(jié)點(diǎn)的例子
--因?yàn)槭菑淖庸?jié)點(diǎn)開始所以,節(jié)點(diǎn)族肯定只有一條,即:一個(gè)孫子只有一個(gè)爺爺
?
--如這個(gè)例子,就表示了以FUNCID 3174開始,從父節(jié)點(diǎn)遍歷獲取下層子節(jié)點(diǎn)的例子
--因?yàn)槭菑母腹?jié)點(diǎn)開始所以,節(jié)點(diǎn)族可能有多條,即:一個(gè)爺爺可能有多個(gè)兒子和孫子
?
--省略了START WITH 則表示全部滿足查詢條件的行,作為根節(jié)點(diǎn)
?
總結(jié)
以上是生活随笔為你收集整理的oracle 数据库中 connect by 和level 的用法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: InnoDB ReplicaSet
- 下一篇: 【SQL】格式为yyyymmddhh:m