﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Hafeyang's Tech Space-随笔分类-Oracle</title><link>http://www.blogjava.net/Hafeyang/category/43489.html</link><description>长于前端开发。乐意分享。</description><language>zh-cn</language><lastBuildDate>Tue, 26 Oct 2010 20:55:42 GMT</lastBuildDate><pubDate>Tue, 26 Oct 2010 20:55:42 GMT</pubDate><ttl>60</ttl><item><title>一种能跨数据库的树形数据表格设计</title><link>http://www.blogjava.net/Hafeyang/archive/2010/10/25/336069.html</link><dc:creator>阳衡锋</dc:creator><author>阳衡锋</author><pubDate>Mon, 25 Oct 2010 03:20:00 GMT</pubDate><guid>http://www.blogjava.net/Hafeyang/archive/2010/10/25/336069.html</guid><wfw:comment>http://www.blogjava.net/Hafeyang/comments/336069.html</wfw:comment><comments>http://www.blogjava.net/Hafeyang/archive/2010/10/25/336069.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/Hafeyang/comments/commentRss/336069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Hafeyang/services/trackbacks/336069.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span">在数据表的设计中，对于树形的表格数据，处理起来时比较棘手的，个人经历过sql server,oracle,mysql，发现对于树形的表格数据处理都不同。<br />
<br />
通常的属性表格设计时我们会这样设计:<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">create</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">table</span><span style="color: #000000">&nbsp;demo_tree&nbsp;(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;</span><span style="color: #000000; font-weight: bold">int</span><span style="color: #000000">&nbsp;,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nodename&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold">varchar</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">50</span><span style="color: #000000">),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parentid&nbsp;</span><span style="color: #000000; font-weight: bold">int</span><span style="color: #000000">&nbsp;<br />
)</span></div>
</span>这样对于不同的数据库处理起来方法就各异了。在sql server里面可能需要用函数递归，在oracle里面可以使用 connect by&nbsp; ..&nbsp;start with ..&nbsp;order sibling by ..去达到深度遍历树的目的。<br />
<br />
虽然主流的ORM框架能处理数据库厂商sql语法的差异，但是对于树形数据还是缺乏统一的支持。所以有人设计了一个这样的表结构:<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">create</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">table</span><span style="color: #000000">&nbsp;DEMO_TREE<br />
</span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">(&nbsp;&nbsp;<br />
</span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;NODELEVEL&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold">INTEGER</span><span style="color: #000000">&nbsp;</span><span style="color: #808080">not</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">,<br />
</span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;LEVELCODE&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold">VARCHAR2</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">500</span><span style="color: #000000">)&nbsp;</span><span style="color: #808080">not</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">,<br />
</span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;PARENTNODE&nbsp;</span><span style="color: #000000; font-weight: bold">VARCHAR2</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">500</span><span style="color: #000000">),<br />
</span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;NODENAME&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold">VARCHAR2</span><span style="color: #000000">(</span><span style="color: #800000; font-weight: bold">200</span><span style="color: #000000">)<br />
</span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #008080">/*</span><span style="color: #008080">其他字段略</span><span style="color: #008080">*/</span><span style="color: #000000"><br />
</span><span style="color: #008080">8</span>&nbsp;<span style="color: #000000">)</span></div>
<ul>
    <li>nodelevel是树的深度，1,2,3...</li>
    <li>levelcode这个字段格式是这样的，我们可以假定每级节点的数量是有上限的，可以根据需要约定比如我们限定每个节点的最多是99999个子节点。这样。levelcode 的第一个节点可以levelcode编号为"00001",其相邻节点为"00002"，他的第一个子节点为"0000100001"，以此类推，可以为每个节点一个唯一编号。</li>
    <li>parentnode就是父节点的levelcode</li>
    <li>nodename是节点名称</li>
</ul>
<p>这样的设计后。我们给出一个实例查询：<br />
</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;t.nodelevel,t.nodename,t.levelcode,t.parentnode&nbsp;</span><span style="color: #0000ff">From</span><span style="color: #000000">&nbsp;demo_tree&nbsp;t&nbsp;</span><span style="color: #0000ff">order</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">by</span><span style="color: #000000">&nbsp;t.levelcode</span></div>
<br />
这样查询的结果形如：<br />
<table style="width: 469pt; border-collapse: collapse" border="0" cellspacing="0" cellpadding="0" width="623">
    <colgroup>
    <col style="width: 59pt" width="78">
    <col style="width: 101pt" width="134">
    <col style="width: 169pt" width="225">
    <col style="width: 140pt" width="186">
    <tbody>
        <tr style="height: 15pt" height="20">
            <td style="width: 59pt; height: 15pt" height="20" width="78"><a name="RANGE!A1:D32">NODELEVEL</a></td>
            <td style="width: 101pt" width="134">NODENAME</td>
            <td style="width: 169pt" class="xl63" width="225">LEVELCODE</td>
            <td style="width: 140pt" class="xl63" width="186">PARENTNODE</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">1</td>
            <td>一级测试节点1</td>
            <td>&nbsp;00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试节点1</td>
            <td>&nbsp;0000100001</td>
            <td>00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>sdfasfasfad</td>
            <td>&nbsp;000010000100001</td>
            <td>0000100001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试节点2</td>
            <td>&nbsp;0000100002</td>
            <td>00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试节点3</td>
            <td>&nbsp;0000100003</td>
            <td>00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试节点5</td>
            <td>&nbsp;0000100005</td>
            <td>00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>asdfgh</td>
            <td>&nbsp;0000100007</td>
            <td>00001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">1</td>
            <td>一级测试节点2</td>
            <td>&nbsp;00002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试节点2</td>
            <td>&nbsp;0000200001</td>
            <td>00002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>fasdfasfsaf</td>
            <td>&nbsp;000020000100001</td>
            <td>0000200001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>二级测试gg4</td>
            <td>&nbsp;0000200002</td>
            <td>00002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>dfasfasfas</td>
            <td>&nbsp;000020000200001</td>
            <td>0000200002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>fgh</td>
            <td>&nbsp;000020000200001</td>
            <td>0000200002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">4</td>
            <td>fdsafdas</td>
            <td>&nbsp;00002000020000100001</td>
            <td>000020000200001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">4</td>
            <td>dfasfsafsda</td>
            <td>&nbsp;00002000020000100001</td>
            <td>000020000200001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">5</td>
            <td>fadsfasfsa</td>
            <td>&nbsp;0000200002000010000100001</td>
            <td>00002000020000100001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">5</td>
            <td>fdasfdasfasdf</td>
            <td>&nbsp;0000200002000010000100001</td>
            <td>00002000020000100001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>dsafasfasdf</td>
            <td>&nbsp;000020000300001</td>
            <td>0000200003</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">1</td>
            <td>测试深度节点1</td>
            <td>&nbsp;10001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>测试深度节点10</td>
            <td>&nbsp;1000100000</td>
            <td>10001</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>测试深度节点100</td>
            <td>&nbsp;100010000000000</td>
            <td>1000100000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">4</td>
            <td>测试深度节点1000</td>
            <td>&nbsp;10001000000000000000</td>
            <td>100010000000000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">5</td>
            <td>测试深度节点10000</td>
            <td>&nbsp;1000100000000000000000000</td>
            <td>10001000000000000000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">1</td>
            <td>测试深度节点2</td>
            <td>&nbsp;10002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>测试深度节点20</td>
            <td>&nbsp;1000200000</td>
            <td>10002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>测试深度节点200</td>
            <td>&nbsp;100020000000000</td>
            <td>1000200000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">4</td>
            <td>测试深度节点2000</td>
            <td>&nbsp;10002000000000000000</td>
            <td>100020000000000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">5</td>
            <td>测试深度节点20000</td>
            <td>&nbsp;1000200000000000000000000</td>
            <td>10002000000000000000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">6</td>
            <td>qwerfga</td>
            <td>&nbsp;100020000000000000000000000001</td>
            <td>1000200000000000000000000</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">2</td>
            <td>sdfg</td>
            <td>&nbsp;1000200001</td>
            <td>10002</td>
        </tr>
        <tr style="height: 15pt" height="20">
            <td style="height: 15pt" height="20" align="right">3</td>
            <td>safsdfsadfaaa</td>
            <td>&nbsp;100020000100001</td>
            <td>1000200001</td>
        </tr>
    </tbody>
</table>
<br />
他是树的深度遍历结果,这也就是这样设计的最大的好处。<br />
<br />
对于新增树节点时需要多做一步就是计算levelcode,比如增加同级节点时需要找到同级节点的最后一个节点。然后将levelcode最后一节+1。对于新增子节点需要找到最大levelcode的子节点然后+1。<br />
<br />
删除也比较方便，如需要删除一个节点以及其所有的子节点，可以<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #0000ff">delete</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">from</span><span style="color: #000000">&nbsp;demo_tree&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000">&nbsp;levelcode&nbsp;</span><span style="color: #808080">like</span><span style="color: #000000">&nbsp;</span><span style="color: #ff0000">'</span><span style="color: #ff0000">00001%</span><span style="color: #ff0000">'</span></div>
<br />
需要获取树的广度遍历结果可以直接用nodelevel排序。<br />
<br />
这样的设计带来的好处是在各种数据库上都可以用。不会因为数据库不同获取树的遍历结果需要写不同的sql。<br />
<br />
当然，问题在于levelcode的计算会导致同级节点的排序不好实现。要获取遍历结果，通常是按照levelcode排序，由于计算levelcode是根据新增的先后顺序，所以同级排序就留给大家思考了。<br />
<br />
<br />
<img src ="http://www.blogjava.net/Hafeyang/aggbug/336069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Hafeyang/" target="_blank">阳衡锋</a> 2010-10-25 11:20 <a href="http://www.blogjava.net/Hafeyang/archive/2010/10/25/336069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle索引，真的用上了么？</title><link>http://www.blogjava.net/Hafeyang/archive/2010/01/09/308809.html</link><dc:creator>阳衡锋</dc:creator><author>阳衡锋</author><pubDate>Sat, 09 Jan 2010 03:12:00 GMT</pubDate><guid>http://www.blogjava.net/Hafeyang/archive/2010/01/09/308809.html</guid><wfw:comment>http://www.blogjava.net/Hafeyang/comments/308809.html</wfw:comment><comments>http://www.blogjava.net/Hafeyang/archive/2010/01/09/308809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Hafeyang/comments/commentRss/308809.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Hafeyang/services/trackbacks/308809.html</trackback:ping><description><![CDATA[<p>最近发现了一个Oracle索引的小细节。</p> <p>如果索引是建立在多个列上， 只有在它的第一个列(leading column)被where子句引用时，优化器才会选择使用该索引。 <p>这也是一条简单而重要的规则。见以下实例。 <p>SQL&gt; create table multiindexusage ( inda number ， indb number ， descr varchar2(10));  <p>Table created。 <p>SQL&gt; create index multindex on multiindexusage(inda，indb);  <p>Index created。 <p>SQL&gt; set autotrace traceonly  <p>SQL&gt; select * from multiindexusage where inda = 1;  <p>Execution Plan  <p>----------------------------------------------------------  <p>0 SELECT STATEMENT Optimizer=CHOOSE  <p>1 0 TABLE ACCESS (BY INDEX ROWID) OF 'MULTIINDEXUSAGE'  <p>2 1 INDEX (RANGE SCAN) OF 'MULTINDEX' (NON-UNIQUE)  <p>(只使用索引的第一个字段查询，可以利用索引) <p>SQL&gt; select * from multiindexusage where indb = 1;  <p>Execution Plan  <p>----------------------------------------------------------  <p>0 SELECT STATEMENT Optimizer=CHOOSE  <p>1 0 TABLE ACCESS (FULL) OF 'MULTIINDEXUSAGE'  <p>(只使用索引的第二个字段查询，将不会利用索引) <p>很明显， 当仅引用索引的第二个列时，优化器使用了全表扫描而忽略了索引。</p> <img src ="http://www.blogjava.net/Hafeyang/aggbug/308809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Hafeyang/" target="_blank">阳衡锋</a> 2010-01-09 11:12 <a href="http://www.blogjava.net/Hafeyang/archive/2010/01/09/308809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>