一種能跨數據庫的樹形數據表格設計
在數據表的設計中,對于樹形的表格數據,處理起來時比較棘手的,個人經歷過sql server,oracle,mysql,發現對于樹形的表格數據處理都不同。通常的屬性表格設計時我們會這樣設計:
create table demo_tree (
id int ,
nodename varchar(50),
parentid int
)
這樣對于不同的數據庫處理起來方法就各異了。在sql server里面可能需要用函數遞歸,在oracle里面可以使用 connect by .. start with .. order sibling by ..去達到深度遍歷樹的目的。id int ,
nodename varchar(50),
parentid int
)
雖然主流的ORM框架能處理數據庫廠商sql語法的差異,但是對于樹形數據還是缺乏統一的支持。所以有人設計了一個這樣的表結構:
1 create table DEMO_TREE
2 (
3 NODELEVEL INTEGER not null,
4 LEVELCODE VARCHAR2(500) not null,
5 PARENTNODE VARCHAR2(500),
6 NODENAME VARCHAR2(200)
7 /*其他字段略*/
8 )
2 (
3 NODELEVEL INTEGER not null,
4 LEVELCODE VARCHAR2(500) not null,
5 PARENTNODE VARCHAR2(500),
6 NODENAME VARCHAR2(200)
7 /*其他字段略*/
8 )
- nodelevel是樹的深度,1,2,3...
- levelcode這個字段格式是這樣的,我們可以假定每級節點的數量是有上限的,可以根據需要約定比如我們限定每個節點的最多是99999個子節點。這樣。levelcode 的第一個節點可以levelcode編號為"00001",其相鄰節點為"00002",他的第一個子節點為"0000100001",以此類推,可以為每個節點一個唯一編號。
- parentnode就是父節點的levelcode
- nodename是節點名稱
這樣的設計后。我們給出一個實例查詢:
select t.nodelevel,t.nodename,t.levelcode,t.parentnode From demo_tree t order by t.levelcode
這樣查詢的結果形如:
NODELEVEL | NODENAME | LEVELCODE | PARENTNODE |
1 | 一級測試節點1 | 00001 | |
2 | 二級測試節點1 | 0000100001 | 00001 |
3 | sdfasfasfad | 000010000100001 | 0000100001 |
2 | 二級測試節點2 | 0000100002 | 00001 |
2 | 二級測試節點3 | 0000100003 | 00001 |
2 | 二級測試節點5 | 0000100005 | 00001 |
2 | asdfgh | 0000100007 | 00001 |
1 | 一級測試節點2 | 00002 | |
2 | 二級測試節點2 | 0000200001 | 00002 |
3 | fasdfasfsaf | 000020000100001 | 0000200001 |
2 | 二級測試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 | 測試深度節點1 | 10001 | |
2 | 測試深度節點10 | 1000100000 | 10001 |
3 | 測試深度節點100 | 100010000000000 | 1000100000 |
4 | 測試深度節點1000 | 10001000000000000000 | 100010000000000 |
5 | 測試深度節點10000 | 1000100000000000000000000 | 10001000000000000000 |
1 | 測試深度節點2 | 10002 | |
2 | 測試深度節點20 | 1000200000 | 10002 |
3 | 測試深度節點200 | 100020000000000 | 1000200000 |
4 | 測試深度節點2000 | 10002000000000000000 | 100020000000000 |
5 | 測試深度節點20000 | 1000200000000000000000000 | 10002000000000000000 |
6 | qwerfga | 100020000000000000000000000001 | 1000200000000000000000000 |
2 | sdfg | 1000200001 | 10002 |
3 | safsdfsadfaaa | 100020000100001 | 1000200001 |
他是樹的深度遍歷結果,這也就是這樣設計的最大的好處。
對于新增樹節點時需要多做一步就是計算levelcode,比如增加同級節點時需要找到同級節點的最后一個節點。然后將levelcode最后一節+1。對于新增子節點需要找到最大levelcode的子節點然后+1。
刪除也比較方便,如需要刪除一個節點以及其所有的子節點,可以
delete from demo_tree where levelcode like '00001%'
需要獲取樹的廣度遍歷結果可以直接用nodelevel排序。
這樣的設計帶來的好處是在各種數據庫上都可以用。不會因為數據庫不同獲取樹的遍歷結果需要寫不同的sql。
當然,問題在于levelcode的計算會導致同級節點的排序不好實現。要獲取遍歷結果,通常是按照levelcode排序,由于計算levelcode是根據新增的先后順序,所以同級排序就留給大家思考了。
posted on 2010-10-25 11:20 衡鋒 閱讀(2567) 評論(4) 編輯 收藏 所屬分類: Oracle