我是FE,也是Fe

          前端來源于不斷的點(diǎn)滴積累。我一直在努力。

          統(tǒng)計(jì)

          留言簿(15)

          閱讀排行榜

          評(píng)論排行榜

          一種能跨數(shù)據(jù)庫的樹形數(shù)據(jù)表格設(shè)計(jì)

          在數(shù)據(jù)表的設(shè)計(jì)中,對(duì)于樹形的表格數(shù)據(jù),處理起來時(shí)比較棘手的,個(gè)人經(jīng)歷過sql server,oracle,mysql,發(fā)現(xiàn)對(duì)于樹形的表格數(shù)據(jù)處理都不同。

          通常的屬性表格設(shè)計(jì)時(shí)我們會(huì)這樣設(shè)計(jì):
          create table demo_tree (
                 id 
          int ,
                 nodename  
          varchar(50),
                 parentid 
          int 
          )
          這樣對(duì)于不同的數(shù)據(jù)庫處理起來方法就各異了。在sql server里面可能需要用函數(shù)遞歸,在oracle里面可以使用 connect by  .. start with .. order sibling by ..去達(dá)到深度遍歷樹的目的。

          雖然主流的ORM框架能處理數(shù)據(jù)庫廠商sql語法的差異,但是對(duì)于樹形數(shù)據(jù)還是缺乏統(tǒng)一的支持。所以有人設(shè)計(jì)了一個(gè)這樣的表結(jié)構(gòu):
          1 create table DEMO_TREE
          2 (  
          3   NODELEVEL  INTEGER not null,
          4   LEVELCODE  VARCHAR2(500not null,
          5   PARENTNODE VARCHAR2(500),
          6   NODENAME   VARCHAR2(200)
          7   /*其他字段略*/
          8 )
          • nodelevel是樹的深度,1,2,3...
          • levelcode這個(gè)字段格式是這樣的,我們可以假定每級(jí)節(jié)點(diǎn)的數(shù)量是有上限的,可以根據(jù)需要約定比如我們限定每個(gè)節(jié)點(diǎn)的最多是99999個(gè)子節(jié)點(diǎn)。這樣。levelcode 的第一個(gè)節(jié)點(diǎn)可以levelcode編號(hào)為"00001",其相鄰節(jié)點(diǎn)為"00002",他的第一個(gè)子節(jié)點(diǎn)為"0000100001",以此類推,可以為每個(gè)節(jié)點(diǎn)一個(gè)唯一編號(hào)。
          • parentnode就是父節(jié)點(diǎn)的levelcode
          • nodename是節(jié)點(diǎn)名稱

          這樣的設(shè)計(jì)后。我們給出一個(gè)實(shí)例查詢:

          select t.nodelevel,t.nodename,t.levelcode,t.parentnode From demo_tree t order by t.levelcode

          這樣查詢的結(jié)果形如:
          NODELEVEL NODENAME LEVELCODE PARENTNODE
          1 一級(jí)測(cè)試節(jié)點(diǎn)1  00001
          2 二級(jí)測(cè)試節(jié)點(diǎn)1  0000100001 00001
          3 sdfasfasfad  000010000100001 0000100001
          2 二級(jí)測(cè)試節(jié)點(diǎn)2  0000100002 00001
          2 二級(jí)測(cè)試節(jié)點(diǎn)3  0000100003 00001
          2 二級(jí)測(cè)試節(jié)點(diǎn)5  0000100005 00001
          2 asdfgh  0000100007 00001
          1 一級(jí)測(cè)試節(jié)點(diǎn)2  00002
          2 二級(jí)測(cè)試節(jié)點(diǎn)2  0000200001 00002
          3 fasdfasfsaf  000020000100001 0000200001
          2 二級(jí)測(cè)試gg4  0000200002 00002
          3 dfasfasfas  000020000200001 0000200002
          3 fgh  000020000200001 0000200002
          4 fdsafdas  00002000020000100001 000020000200001
          4 dfasfsafsda  00002000020000100001 000020000200001
          5 fadsfasfsa  0000200002000010000100001 00002000020000100001
          5 fdasfdasfasdf  0000200002000010000100001 00002000020000100001
          3 dsafasfasdf  000020000300001 0000200003
          1 測(cè)試深度節(jié)點(diǎn)1  10001
          2 測(cè)試深度節(jié)點(diǎn)10  1000100000 10001
          3 測(cè)試深度節(jié)點(diǎn)100  100010000000000 1000100000
          4 測(cè)試深度節(jié)點(diǎn)1000  10001000000000000000 100010000000000
          5 測(cè)試深度節(jié)點(diǎn)10000  1000100000000000000000000 10001000000000000000
          1 測(cè)試深度節(jié)點(diǎn)2  10002
          2 測(cè)試深度節(jié)點(diǎn)20  1000200000 10002
          3 測(cè)試深度節(jié)點(diǎn)200  100020000000000 1000200000
          4 測(cè)試深度節(jié)點(diǎn)2000  10002000000000000000 100020000000000
          5 測(cè)試深度節(jié)點(diǎn)20000  1000200000000000000000000 10002000000000000000
          6 qwerfga  100020000000000000000000000001 1000200000000000000000000
          2 sdfg  1000200001 10002
          3 safsdfsadfaaa  100020000100001 1000200001

          他是樹的深度遍歷結(jié)果,這也就是這樣設(shè)計(jì)的最大的好處。

          對(duì)于新增樹節(jié)點(diǎn)時(shí)需要多做一步就是計(jì)算levelcode,比如增加同級(jí)節(jié)點(diǎn)時(shí)需要找到同級(jí)節(jié)點(diǎn)的最后一個(gè)節(jié)點(diǎn)。然后將levelcode最后一節(jié)+1。對(duì)于新增子節(jié)點(diǎn)需要找到最大levelcode的子節(jié)點(diǎn)然后+1。

          刪除也比較方便,如需要?jiǎng)h除一個(gè)節(jié)點(diǎn)以及其所有的子節(jié)點(diǎn),可以
          delete from demo_tree where levelcode like '00001%'

          需要獲取樹的廣度遍歷結(jié)果可以直接用nodelevel排序。

          這樣的設(shè)計(jì)帶來的好處是在各種數(shù)據(jù)庫上都可以用。不會(huì)因?yàn)閿?shù)據(jù)庫不同獲取樹的遍歷結(jié)果需要寫不同的sql。

          當(dāng)然,問題在于levelcode的計(jì)算會(huì)導(dǎo)致同級(jí)節(jié)點(diǎn)的排序不好實(shí)現(xiàn)。要獲取遍歷結(jié)果,通常是按照levelcode排序,由于計(jì)算levelcode是根據(jù)新增的先后順序,所以同級(jí)排序就留給大家思考了。


          posted on 2010-10-25 11:20 衡鋒 閱讀(2576) 評(píng)論(4)  編輯  收藏 所屬分類: Oracle

          評(píng)論

          # re: 一種能跨數(shù)據(jù)庫的樹形數(shù)據(jù)表格設(shè)計(jì) 2010-10-25 12:35 vagrant

          with查詢應(yīng)該都可以搞定了吧  回復(fù)  更多評(píng)論   

          # re: 一種能跨數(shù)據(jù)庫的樹形數(shù)據(jù)表格設(shè)計(jì)[未登錄] 2010-10-25 15:03 小小

          這個(gè)確實(shí)可以實(shí)現(xiàn),我們?cè)囘^,但大數(shù)據(jù)量下效率實(shí)在遠(yuǎn)不如oracle connect by,小數(shù)據(jù)量無所謂;另外這種實(shí)現(xiàn)對(duì)于樹結(jié)點(diǎn)的移動(dòng)操作實(shí)在是噩夢(mèng)啊。
          五位一個(gè)編碼小數(shù)據(jù)量下浪費(fèi),大數(shù)據(jù)量下還有10萬的約束,雖不大可能超出,但這個(gè)約束還是不爽,類似于“潛規(guī)則”啊。
          所以我們最終更改了曾經(jīng)的這種實(shí)現(xiàn),還是充分使用不同的數(shù)據(jù)庫提供的解決方法更優(yōu)化,現(xiàn)在的java/c#實(shí)現(xiàn)多數(shù)據(jù)庫對(duì)應(yīng)不同實(shí)現(xiàn)代碼還是很簡單的。
            回復(fù)  更多評(píng)論   

          # re: 一種能跨數(shù)據(jù)庫的樹形數(shù)據(jù)表格設(shè)計(jì) 2010-10-25 17:28 陽衡鋒

          @vagrant
          with語法不是每個(gè)數(shù)據(jù)庫都支持的。

          @未登錄
          這樣的設(shè)計(jì)主要還是考慮在不同的數(shù)據(jù)庫都能夠簡單的實(shí)現(xiàn)遍歷和級(jí)聯(lián)刪除。當(dāng)然任何設(shè)計(jì)都是有利有弊的。如果產(chǎn)品要求數(shù)據(jù)庫兼容,必然會(huì)有些取舍。  回復(fù)  更多評(píng)論   

          # re: 一種能跨數(shù)據(jù)庫的樹形數(shù)據(jù)表格設(shè)計(jì) 2010-10-27 15:46 單飛

          一般來說tree model 不會(huì)全部構(gòu)造出來,除非數(shù)據(jù)量很少。針對(duì)海量的深度,要使用動(dòng)態(tài)加載,比如樹的節(jié)點(diǎn)被點(diǎn)擊開的時(shí)候才取子目錄的數(shù)據(jù)。Lazy-Load.  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 新河县| 四川省| 洛隆县| 昆山市| 海南省| 通河县| 通道| 广南县| 禄劝| 黄石市| 那坡县| 宁南县| 察雅县| 嘉禾县| 万州区| 丰都县| 辉县市| 沅陵县| 陈巴尔虎旗| 鄂州市| 曲沃县| 台东市| 蓬安县| 孙吴县| 昌吉市| 梧州市| 股票| 重庆市| 大兴区| 浮梁县| 西畴县| 顺平县| 定南县| 年辖:市辖区| 商水县| 会东县| 固原市| 新绛县| 侯马市| 务川| 健康|