??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲日韩国产AV无码无码精品,亚洲国产精品无码av,91亚洲国产成人久久精品http://m.tkk7.com/conans/category/32376.html你越挣扎我就兴?/description>zh-cnMon, 22 Nov 2010 01:03:02 GMTMon, 22 Nov 2010 01:03:02 GMT60Oracle 常用SQL技巧收?/title><link>http://m.tkk7.com/conans/articles/338235.html</link><dc:creator>CONAN</dc:creator><author>CONAN</author><pubDate>Wed, 17 Nov 2010 03:12:00 GMT</pubDate><guid>http://m.tkk7.com/conans/articles/338235.html</guid><description><![CDATA[<strong>转自Q?/strong>http://www.javaeye.com/topic/805815<br /> <strong><br /> 1. SELECT子句中避免?“*”</strong> <br />     当你惛_SELECT子句中列出所有的COLUMN?使用动态SQL列引?‘*’ 是一个方便的Ҏ.不幸的是,q是一个非怽效的Ҏ. 实际?ORACLE在解析的q程? 会将“*” 依次转换成所有的列名, q个工作是通过查询数据字典完成? q意味着耗费更多的时? <br /> <br /> <strong>2.使用DECODE函数来减处理时?/strong> <br />     使用DECODE函数可以避免重复扫描相同记录或重复连接相同的? 例如: <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0020 AND  ENAME LIKE ‘SMITH%’;  </li> <li>SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0030 AND ENAME LIKE ‘SMITH%’;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0020 AND ENAME LIKE ‘SMITH%’; SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0030 AND ENAME LIKE ‘SMITH%’; </pre>     你可以用DECODE函数高效地得到相同结? <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT,  </li> <li>        COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT,  </li> <li>        SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,  </li> <li>        SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL  </li> <li>FROM EMP WHERE ENAME LIKE ‘SMITH%’;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT, COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT, SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL, SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL FROM EMP WHERE ENAME LIKE ‘SMITH%’; </pre>     cM?DECODE函数也可以运用于GROUP BY 和ORDER BY子句? <br /> <br /> <strong>3.删除重复记录</strong> <br />    最高效的删除重复记录方?( 因ؓ使用了ROWID) <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); </pre> <br /> <br /> <strong>4. 用TRUNCATE替代DELETE</strong> <br />     当删除表中的记录Ӟ在通常情况下,回滚D?rollback segments ) 用来存放可以被恢复的信息Q如果你没有COMMIT事务QORACLE会将数据恢复到删除之前的状?准确地说是恢复到执行删除命o之前的状?Q而当q? 用TRUNCATE? 回滚D不再存放Q何可被恢复的信息.当命令运行后,数据不能被恢?因此很少的资源被调用,执行旉也会很短. <br /> <br /> <strong>5.计算记录条数</strong> <br />     和一般的观点相反, count(*) 比count(1)E快 Q当然如果可以通过索引索,对烦引列的计C旧是最快的. 例如 COUNT(EMPNO) <br /> <br /> <strong>6.用Where子句替换HAVING子句</strong> <br />     避免使用HAVING子句QHAVING 只会在检索出所有记录之后才对结果集q行qoQ这个处理需要排序、总计{操作,如果能通过WHERE子句限制记录的数目,那就能减这斚w的开销, 例如: <br /> <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效  </li> <li>SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION GROUP BY REGION HAVING REGION REGION != ‘SYDNEY’ AND REGION != ‘PERTH’  </li> <li>--高效  </li> <li>SELECT REGIONQAVG(LOG_SIZE)  FROM  LOCATION WHERE REGION REGION != ‘SYDNEY’ ND REGION != ‘PERTH’ GROUP BY REGION  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效 SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION GROUP BY REGION HAVING REGION REGION != ‘SYDNEY’ AND REGION != ‘PERTH’ --高效 SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION WHERE REGION REGION != ‘SYDNEY’ ND REGION != ‘PERTH’ GROUP BY REGION </pre> <br /> <br /> <strong>7. 用EXISTS替代IN</strong> <br />    在许多基于基表的查询?Z满一个条?往往需要对另一个表q行联接.在这U情况下, 使用EXISTS(或NOT EXISTS)通常提高查询的效率. <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效  </li> <li>SELECT * FROM EMP WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’)  </li> <li>--高效:  </li> <li>SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’  FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效 SELECT * FROM EMP WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’) --高效: SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’) </pre> <br /> <br /> <strong>8.用NOT EXISTS替代NOT IN</strong> <br />    在子查询中,NOT IN子句执行一个内部的排序和合q? 无论在哪U情况下QNOT IN都是最低效? (因ؓ它对子查询中的表执行了一个全表遍?.  Z避免使用NOT INQ我们可以把它改写成外连?Outer Joins)或NOT EXISTS. 例如: <br /> SELECT …FROM EMP  WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT=’A’); <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--Z提高效率改写? (Ҏ一: 高效)  </li> <li>SELECT ….FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’  </li> <li>-- (Ҏ? 最高效)  </li> <li>SELECT ….FROM EMP E WHERE NOT EXISTS (SELECT ‘X’  FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’);  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--Z提高效率改写? (Ҏ一: 高效) SELECT ….FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’ -- (Ҏ? 最高效) SELECT ….FROM EMP E WHERE NOT EXISTS (SELECT ‘X’ FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’); </pre> <br /> <br /> <strong>9.用EXISTS替换DISTINCT</strong> <br />     当提交一个包含一对多表信?比如部门表和雇员?的查询时,避免在SELECT子句中用DISTINCT. 一般可以考虑用EXIST替换 <br /> 例如: <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效:   </li> <li>SELECT DISTINCT DEPT_NO,DEPT_NAME  FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO  </li> <li>--高效:  </li> <li>SELECT DEPT_NO,DEPT_NAME  FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);  </li> <li>--EXISTS 使查询更?因ؓRDBMS核心模块在子查询的条g一旦满_,立刻q回l果.  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效: SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO --高效: SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); --EXISTS 使查询更?因ؓRDBMS核心模块在子查询的条g一旦满_,立刻q回l果. </pre> <br /> <br /> <strong>10. 用烦引提高效?/strong> <br />    索引是表的一个概念部分,用来提高索数据的效率Q实际上ORACLE使用了一个复杂的自^衡B-treel构Q通常通过索引查询数据比全表扫描要快,? ORACLE扑և执行查询和Update语句的最佌\径时Q?ORACLE优化器将使用索引Q? 同样在联l多个表时用烦引也可以提高效率Q另一个用烦引的好处是,它提供了主键(primary key)的唯一性验证,除了那些LONG或LONG RAW数据cd, 你可以烦引几乎所有的? 通常, 在大型表中用烦引特别有? 当然,你也会发? 在扫描小表时,使用索引同样能提高效率,虽然使用索引能得到查询效率的提高,但是我们也必L意到它的代h. 索引需要空间来存储Q也需要定期维护,每当有记录在表中增减或烦引列被修ҎQ烦引本w也会被修改Q这意味着每条记录的INSERT , DELETE , UPDATEؓ此多付出4 , 5 ơ的盘I/OQ?因ؓ索引需要额外的存储I间和处理,那些不必要的索引反而会使查询反应时间变? <br /> <em>注:定期的重构烦引是有必要的. </em> <br /> <br /> <strong>11. 避免在烦引列上用计?/strong> <br />       WHERE子句中,如果索引列是函数的一部分Q优化器不使用索引而用全表扫? 举例Q? <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效Q?nbsp; </li> <li>SELECT …FROM DEPT WHERE SAL * 12 > 25000;  </li> <li>--高效:  </li> <li>SELECT … FROM DEPT WHERE SAL  > 25000/12;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效Q? SELECT …FROM DEPT WHERE SAL * 12 > 25000; --高效: SELECT … FROM DEPT WHERE SAL > 25000/12; </pre> <br /> <br /> <strong>12. ?gt;=替代></strong> <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--如果DEPTNO上有一个烦?nbsp; </li> <li>--高效Q?nbsp; </li> <li>   SELECT *  FROM EMP  WHERE DEPTNO >=4     </li> <li>--低效Q?nbsp; </li> <li>   SELECT *  FROM EMP   WHERE DEPTNO >3  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--如果DEPTNO上有一个烦? --高效Q? SELECT * FROM EMP WHERE DEPTNO >=4 --低效Q? SELECT * FROM EMP WHERE DEPTNO >3 </pre>    两者的区别在于, 前者DBMS直接蟩到第一个DEPT{于4的记录而后者将首先定位到DEPTNO=3的记录ƈ且向前扫描到W一个DEPT大于3的记? <strong>1. SELECT子句中避免?“*”</strong> <br />     当你惛_SELECT子句中列出所有的COLUMN?使用动态SQL列引?‘*’ 是一个方便的Ҏ.不幸的是,q是一个非怽效的Ҏ. 实际?ORACLE在解析的q程? 会将“*” 依次转换成所有的列名, q个工作是通过查询数据字典完成? q意味着耗费更多的时? <br /> <br /> <strong>2.使用DECODE函数来减处理时?/strong> <br />     使用DECODE函数可以避免重复扫描相同记录或重复连接相同的? 例如: <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0020 AND  ENAME LIKE ‘SMITH%’;  </li> <li>SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0030 AND ENAME LIKE ‘SMITH%’;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0020 AND ENAME LIKE ‘SMITH%’; SELECT COUNT(*)QSUM(SAL) FROM EMP WHERE DEPT_NO = 0030 AND ENAME LIKE ‘SMITH%’; </pre>     你可以用DECODE函数高效地得到相同结? <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT,  </li> <li>        COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT,  </li> <li>        SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,  </li> <li>        SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL  </li> <li>FROM EMP WHERE ENAME LIKE ‘SMITH%’;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT, COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT, SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL, SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL FROM EMP WHERE ENAME LIKE ‘SMITH%’; </pre>     cM?DECODE函数也可以运用于GROUP BY 和ORDER BY子句? <br /> <br /> <strong>3.删除重复记录</strong> <br />    最高效的删除重复记录方?( 因ؓ使用了ROWID) <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); </pre> <br /> <br /> <strong>4. 用TRUNCATE替代DELETE</strong> <br />     当删除表中的记录Ӟ在通常情况下,回滚D?rollback segments ) 用来存放可以被恢复的信息Q如果你没有COMMIT事务QORACLE会将数据恢复到删除之前的状?准确地说是恢复到执行删除命o之前的状?Q而当q? 用TRUNCATE? 回滚D不再存放Q何可被恢复的信息.当命令运行后,数据不能被恢?因此很少的资源被调用,执行旉也会很短. <br /> <br /> <strong>5.计算记录条数</strong> <br />     和一般的观点相反, count(*) 比count(1)E快 Q当然如果可以通过索引索,对烦引列的计C旧是最快的. 例如 COUNT(EMPNO) <br /> <br /> <strong>6.用Where子句替换HAVING子句</strong> <br />     避免使用HAVING子句QHAVING 只会在检索出所有记录之后才对结果集q行qoQ这个处理需要排序、总计{操作,如果能通过WHERE子句限制记录的数目,那就能减这斚w的开销, 例如: <br /> <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效  </li> <li>SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION GROUP BY REGION HAVING REGION REGION != ‘SYDNEY’ AND REGION != ‘PERTH’  </li> <li>--高效  </li> <li>SELECT REGIONQAVG(LOG_SIZE)  FROM  LOCATION WHERE REGION REGION != ‘SYDNEY’ ND REGION != ‘PERTH’ GROUP BY REGION  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效 SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION GROUP BY REGION HAVING REGION REGION != ‘SYDNEY’ AND REGION != ‘PERTH’ --高效 SELECT REGIONQAVG(LOG_SIZE) FROM LOCATION WHERE REGION REGION != ‘SYDNEY’ ND REGION != ‘PERTH’ GROUP BY REGION </pre> <br /> <br /> <strong>7. 用EXISTS替代IN</strong> <br />    在许多基于基表的查询?Z满一个条?往往需要对另一个表q行联接.在这U情况下, 使用EXISTS(或NOT EXISTS)通常提高查询的效率. <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效  </li> <li>SELECT * FROM EMP WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’)  </li> <li>--高效:  </li> <li>SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’  FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效 SELECT * FROM EMP WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’) --高效: SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’) </pre> <br /> <br /> <strong>8.用NOT EXISTS替代NOT IN</strong> <br />    在子查询中,NOT IN子句执行一个内部的排序和合q? 无论在哪U情况下QNOT IN都是最低效? (因ؓ它对子查询中的表执行了一个全表遍?.  Z避免使用NOT INQ我们可以把它改写成外连?Outer Joins)或NOT EXISTS. 例如: <br /> SELECT …FROM EMP  WHERE DEPT_NO NOT IN (SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT=’A’); <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--Z提高效率改写? (Ҏ一: 高效)  </li> <li>SELECT ….FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’  </li> <li>-- (Ҏ? 最高效)  </li> <li>SELECT ….FROM EMP E WHERE NOT EXISTS (SELECT ‘X’  FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’);  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--Z提高效率改写? (Ҏ一: 高效) SELECT ….FROM EMP A,DEPT B WHERE A.DEPT_NO = B.DEPT(+) AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+) = ‘A’ -- (Ҏ? 最高效) SELECT ….FROM EMP E WHERE NOT EXISTS (SELECT ‘X’ FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = ‘A’); </pre> <br /> <br /> <strong>9.用EXISTS替换DISTINCT</strong> <br />     当提交一个包含一对多表信?比如部门表和雇员?的查询时,避免在SELECT子句中用DISTINCT. 一般可以考虑用EXIST替换 <br /> 例如: <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效:   </li> <li>SELECT DISTINCT DEPT_NO,DEPT_NAME  FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO  </li> <li>--高效:  </li> <li>SELECT DEPT_NO,DEPT_NAME  FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);  </li> <li>--EXISTS 使查询更?因ؓRDBMS核心模块在子查询的条g一旦满_,立刻q回l果.  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效: SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO --高效: SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO); --EXISTS 使查询更?因ؓRDBMS核心模块在子查询的条g一旦满_,立刻q回l果. </pre> <br /> <br /> <strong>10. 用烦引提高效?/strong> <br />    索引是表的一个概念部分,用来提高索数据的效率Q实际上ORACLE使用了一个复杂的自^衡B-treel构Q通常通过索引查询数据比全表扫描要快,? ORACLE扑և执行查询和Update语句的最佌\径时Q?ORACLE优化器将使用索引Q? 同样在联l多个表时用烦引也可以提高效率Q另一个用烦引的好处是,它提供了主键(primary key)的唯一性验证,除了那些LONG或LONG RAW数据cd, 你可以烦引几乎所有的? 通常, 在大型表中用烦引特别有? 当然,你也会发? 在扫描小表时,使用索引同样能提高效率,虽然使用索引能得到查询效率的提高,但是我们也必L意到它的代h. 索引需要空间来存储Q也需要定期维护,每当有记录在表中增减或烦引列被修ҎQ烦引本w也会被修改Q这意味着每条记录的INSERT , DELETE , UPDATEؓ此多付出4 , 5 ơ的盘I/OQ?因ؓ索引需要额外的存储I间和处理,那些不必要的索引反而会使查询反应时间变? <br /> <em>注:定期的重构烦引是有必要的. </em> <br /> <br /> <strong>11. 避免在烦引列上用计?/strong> <br />       WHERE子句中,如果索引列是函数的一部分Q优化器不使用索引而用全表扫? 举例Q? <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--低效Q?nbsp; </li> <li>SELECT …FROM DEPT WHERE SAL * 12 > 25000;  </li> <li>--高效:  </li> <li>SELECT … FROM DEPT WHERE SAL  > 25000/12;  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--低效Q? SELECT …FROM DEPT WHERE SAL * 12 > 25000; --高效: SELECT … FROM DEPT WHERE SAL > 25000/12; </pre> <br /> <br /> <strong>12. ?gt;=替代></strong> <br /> <div> <div> <div>Sql代码 </div> </div> <ol start="1"> <li>--如果DEPTNO上有一个烦?nbsp; </li> <li>--高效Q?nbsp; </li> <li>   SELECT *  FROM EMP  WHERE DEPTNO >=4     </li> <li>--低效Q?nbsp; </li> <li>   SELECT *  FROM EMP   WHERE DEPTNO >3  </li> </ol> </div> <pre style="display: none;" name="code" class="sql">--如果DEPTNO上有一个烦? --高效Q? SELECT * FROM EMP WHERE DEPTNO >=4 --低效Q? SELECT * FROM EMP WHERE DEPTNO >3 </pre>    两者的区别在于, 前者DBMS直接蟩到第一个DEPT{于4的记录而后者将首先定位到DEPTNO=3的记录ƈ且向前扫描到W一个DEPT大于3的记? <img src ="http://m.tkk7.com/conans/aggbug/338235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/conans/" target="_blank">CONAN</a> 2010-11-17 11:12 <a href="http://m.tkk7.com/conans/articles/338235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle的decode、sign?trunc函数http://m.tkk7.com/conans/articles/319966.htmlCONANCONANMon, 03 May 2010 12:16:00 GMThttp://m.tkk7.com/conans/articles/319966.html

一?span class="hilite2">decode

 

 

?span class="hilite1">Oracle/PLSQL ?  decode h? IF-THEN-ELSE 一L功能?/span>

decode 函数语法如下Q?/span>

decode( expression , search , result [, search , result]... [, default] )

expression 要比较的表达?

 

search 要与expression 比较的字Dc?/em>.

 

result 如果expression ?em>search 一L话,q回该结果?

default 此参数可选,如果没有?em>expression 匚w上的search . p回此l果Q如果此参数没有讄Q当没有与expression匚w上的searchӞq回null?/span>

search ? result可成对出现多ơ,代表各种要匹配的情况?nbsp;
 

应用?/span>

  • Oracle 9i, Oracle 10g, Oracle 11g

例如Q?/span>

You could use the decode function in an SQL statement as follows:

 

select supplier_name,decode(supplier_id,1000,'IBM',10001,'Microsoft','1002','Hewlett Packard','Gateway') result from suppliers;

 

上面的sql语句相当于下面的IF-THEN-ELSE :

IF supplier_id = 10000 THEN
     result := 'IBM';

ELSIF supplier_id = 10001 THEN
    result := 'Microsoft';

ELSIF supplier_id = 10002 THEN
    result := 'Hewlett Packard';

ELSE
    result := 'Gateway';

END IF;


 decode 函数会挨个匹配supplier_id 的?


 

常见问题Q?/span>


 

 

问题1:  现在一个阅读者想问,怎么使用decode函数来比较两个日期呢Q(例如Qdate1 ? date2Q? 如果date1 > date2, decode 函数q回date2. 否则decode函数q回 date1.

回答:  要实Cq要求,可?span class="hilite2">decode函数如下Q?/span>

decode((date1 - date2) - abs(date1 - date2), 0, date2, date1)

如果date1大于date2Q下面表达是会等?Q?/span>

(date1 - date2) - abs(date1 - date2)

帮助性提C?/strong>: 可用decode函数l定SIGN 函数 像下面这?

上面比较日期的语句可修改如下:

DECODE(SIGN(date1-date2), 1, date2, date1)

SIGN/DECODE 联合对于有关销售红利等数字斚w的比较是非常有用的?/span>

DECODE(SIGN(actual-target), -1, 'NO Bonus for you', 0,'Just made it', 1, 'Congrats, you are a winner')


 

 

问题2:  我想知道是否可以?span class="hilite2">decode函数来确定数字范_例如 1-10 = 'category 1', 11-20 = 'category 2', 比一个一个比较应该会好一点吧.

回答: 不幸的告诉你Q不可以?span class="hilite2">decode函数来确定数字的范围. 可是你可以试着创徏一个表辑ּQ这个表辑ּ可以得一个数字指定的范围, 下一个数字对应下一个指定的范围, 以此cL.

例如Q?/strong>

select supplier_id,decode(trunc((supplier_id-1)/10),0,'category 1',1,'category 2',2,'category 3','unknown') result from suppliers;

 

q个例子Zq个公式Q?/span>trunc ((supplier_id - 1) / 10

 

如果supplier_id??0之间Q表辑ּ计算?0.

如果supplier_id?1?0之间Q表辑ּ计算?1.

如果supplier_id?1?0之间Q表辑ּ计算?3.

 

 

 

 

{等Q?


 

 

问题3:  我想写一?span class="hilite2">decode函数Q要求如?

如果 yrs_of_service < 1 q回 0.04
? ?nbsp;yrs_of_service >= 1 and < 5 q回0.04
如果 yrs_of_service > 5 q回 0.06

q种情况我该怎么做呢?

回答:  You will need to create a formula that will evaluate to a single number for each one of your ranges.

For example:

select emp_name,decode(trunc((yrs_of_service+3)/4),0,0.04,1,0.04,0.06) as perc_value from employees;


 

 

问题4decode函数的参C数有限制吗?我得C个错?"ORA-00939: too many arguments for function".

回答:  是的Q?span class="hilite2">decode函数的最大参CCؓ255?包括expression, search, and result arguments.<!-- InstanceEndEditable -->

 

 

-------------------------------------------------------------------------------------------------------------

 

 

二、sign

?span class="hilite1">Oracle/PLSQL ? sign 函数q回一个数字的正负标志.

 

语法如下Q?/span>sign( number )

 

        number 要测试标志的数字.

If number < 0, then sign returns -1.
If number = 0, then sign returns 0.
If number > 0, then sign returns 1.

应用?

  • Oracle 8i, Oracle 9i, Oracle 10g, Oracle 11g

例如:

      

sign(-23) would return -1
sign(0.001) would return -1
sign(0) would return 0
sign(0.001) would return 1
sign(23) would return 1
sig(23.601)

would return 1

 

 

 

----------------------------------------------------------------------------------------------------

三、trunc(number)

?span class="hilite1">Oracle/PLSQL? trunc function returns a number truncated to a certain number of decimal places.

trunc function 语法如下:

trunc( number, [ decimal_places ] )

number 要截取的数字.

decimal_places 要保留的数? q个参数必须是个整数. 如果此参数缺省,默认保留0位小?/span>
 

应用?

  • Oracle 8i, Oracle 9i, Oracle 10g, Oracle 11g


 

例如For example:

trunc(125.815) would return 125
trunc(125.815, 0) would return 125
trunc(125.815, 1) would return 125.8
trunc(125.815, 2) would return 125.81
trunc(125.81, 3) would return 125.81
trunc(-125.815, 2) would return -125.81
trunc(125.815, -1) would return 120
trunc(125.815, -2) would return 100
trunc(125.81, -3) would return 0

 

 如果decimal_places 大于number 本n的小C敎ͼq回原数字不会加0.

如:trunc(125.81,3) would return 125.81;

如果decimal_places 敎ͼ那么指定的位数

 



CONAN 2010-05-03 20:16 发表评论
]]>
oracle rownum 专题http://m.tkk7.com/conans/articles/319963.htmlCONANCONANMon, 03 May 2010 11:46:00 GMThttp://m.tkk7.com/conans/articles/319963.htmlRownum专题

 

对于rownum来说它是oraclepȝ序分配Z查询q回的行的编Pq回的第一行分配的?/span>1Q第二行?/span>2Q依此类推,q个伪字D可以用于限制查询返回的总行敎ͼ而且rownum不能以Q何表的名UC为前~?/span>
举例说明Q?/span>
例如表:student(学生)表,表结构ؓQ?/span>
ID
    char(6)           --学号
name
  VARCHAR2(10)   --姓名

/* Formatted on 2008/09/24 09:15 (Formatter Plus v4.8.7) */
CREATE TABLE student (ID CHAR(6), NAME VARCHAR2(100));

INSERT INTO student
     VALUES ('200001', '
张一
');
INSERT INTO student
     VALUES ('200002', '
王二
');
INSERT INTO student
     VALUES ('200003', '
李三
');
INSERT INTO student
     VALUES ('200004', '
赵四
');
COMMIT ;


(1) rownum
对于{于某值的查询条g

如果希望扑ֈ学生表中W一条学生的信息Q可以?/span>rownum=1作ؓ条g。但是想扑ֈ学生表中W二条学生的信息Q?/span>rownum=2l果查不到数据。因?/span>rownum都是?/span>1开始,但是1以上的自然数?/span>rownum做等于判断是时认为都?/span>false条gQ所以无法查?/span>rownum = nQ?/span>n>1的自然数Q?/span>
SQL> select rownum,id,name from student where rownum=1;
Q可以用在限制返回记录条数的? 方,保证不出错,如:隐式游标Q?/span>
SQL> select rownum,id,name from student where rownum=1;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200001
张一
SQL> select rownum,id,name from student where rownum =2;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------

Q?/span>2Q?/span>rownum对于大于某值的查询条g
  
如果xCW二行记录以后的 记录Q当使用rownum>2是查不出记录的, 原因是由?/span>rownum是一个L?/span>1开始的伪列Q?/span>Oracle 认ؓrownum> n(n>1的自然数)q种条g依旧不成立,所以查不到记录
SQL> select rownum,id,name from student where rownum >2;
ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
那如何才能找到第二行以后的记 录呀。可以用以下的子查询方法来解决。注意子查询中的rownum必须要有别名Q否则还是不会查录来Q这是因?/span>rownum不是某个表的列,如果不v别名的话Q无法知?/span>rownum是子查询的列q是L询的列?/span>
SQL>select * from(select rownum no ,id,name from student) where no>2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         3 200003
李三
         4 200004
赵四
SQL> select * from(select rownum,id,name from student)where rownum>2;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------

Q?/span>3Q?/span>rownum对于于某值的查询条g
如果x到第三条记录以前的记 录,当?/span>rownum<3是能得到两条记录 的。显?/span>rownum对于rownum<nQ?/span>(n>1的自然数Q的条g认ؓ是成立的Q所以可以找到记录?/span>
SQL> select rownum,id,name from student where rownum <3;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
        1 200001
张一
        2 200002
王二

lg几种情况Q可能有时候需? 查询rownum在某区间的数据,那怎么办呀从上可以看出rownum对小于某值的查询条g是h?/span>true的,rownum对于大于某值的查询条g直接认ؓ?/span>false的,但是可以间接的让它{为是true的。那必M用子查询。例如要查询rownum在第二行到第三行之间的数据,包括W二行和W三行数据,那么我们只能写以下语句,先让它返回小于等? 三的记录行,然后在主查询中判断新?/span>rownum的别? 列大于等于二的记录行。但是这L操作会在大数据集中媄响速度?/span>
SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2;
        NO ID     NAME
---------- ------ ---------------------------------------------------
         2 200002
王二
         3 200003
李三

Q?/span>4Q?/span>rownum和排?/span>
Oracle
中的rownum的是在取数据的时候生的序号Q所以想Ҏ定排序的数据L定的rowmun行数据就必须注意了?/span>
SQL> select rownum ,id,name from student order by name;
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         3 200003
李三
         2 200002
王二
         1 200001
张一
         4 200004
赵四
可以看出Q?/span>rownumq不是按?/span>name列来生成的序受系l是按照记录插入时的序l记录排的号Q?/span>rowid也是序分配的。ؓ了解册个问题,必须使用子查?/span>
SQL> select rownum ,id,name from (select * from student order by name);
    ROWNUM ID     NAME
---------- ------ ---------------------------------------------------
         1 200003
李三
         2 200002
王二
         3 200001
张一
         4 200004
赵四
q样成了按name排序Qƈ且用rownum标出正确序号Q有到大)?/span>

W者在工作中有一上百万条记录的表Q在jsp面中需对该表进行分|C, 便考虑?/span>rownum来作Q下面是具体Ҏ(每页
20?/span>)Q?/span>
“select * from tabname where rownum<20 order by name"
但却发现oracle却不能按自己的意愿来执行Q而是先随?/span>
?/span>20条记录,然后?/span> order byQ后l咨?/span>oracle,?/span>rownum实pP想用的话Q只能用子查?/span> 来实现先排序Q后
rownum
Q方法如下:
"select * from (select * from tabname order by name) where rownum<20",
但这样一来,效率会较低很多?/span>
后经W者试验,只需?/span>order by 的字D上加主键或索引卛_?/span>oracle先按 该字D|序,然后?/span>rownumQ方法不变:
   “select * from tabname where rownum<20 order by name"


补充Q我们正常分|如下Q?/span>order by 主键Q在最里面的那一层。非主键字段同样?/span> 加烦引)Q?/span>
/* Formatted on 2008/09/24 12:14 (Formatter Plus v4.8.7) */
SELECT *
FROM (SELECT tmp.*, ROWNUM rn
          FROM (SELECT   *
                    FROM student
                   WHERE 1 = 1
                ORDER BY NAME DESC) tmp
         WHERE 1 = 1 AND ROWNUM <= 3)
WHERE 1 = 1 AND rn >= 2



(5)
取得某列中第N大的?/span>

select column_name from
(select table_name.*,dense_rank() over (order by column desc) rank from table_name)
where rank = &N
Q?/span>

/* Formatted on 2008/09/24 12:30 (Formatter Plus v4.8.7) */
SELECT *
FROM (SELECT student.*, DENSE_RANK () OVER (ORDER BY ID DESC) RANK
          FROM student)
WHERE RANK = 2


(6)
假如要返回前5条记录:

select * from tablename where rownum<6;(
或是rownum <= 5 或是
rownum != 6)
假如要返回第5-9条记录:

/* Formatted on 2008/09/24 12:34 (Formatter Plus v4.8.7) */
SELECT   *
    FROM student
   WHERE ROWNUM < 4
MINUS
SELECT   *
    FROM student
   WHERE ROWNUM < 2


order by name
选出l果后用name排序昄l果?/span>(先选再排序)

注意Q只能用以上W号(<?/span><=?/span>!=)?/span>

(7)select * from tablename where rownum != 10;
q回的是前9条记录?/span>
不能用:>,>=,=,Between...and。由?/span>rownum是一个L?/span>1开始的伪列Q?/span>Oracle 认ؓq种条g 不成立,查不到记?/span>.

? 外,q个Ҏ更快Q?/span>

select * from (
select rownum r,a from yourtable
where rownum <= 20
order by name )
where r > 10
q样取出W?/span>11-20条记?/span>!(先选再排序再?/span>)

要先排序再选则ȝselect嵌套Q内层排序外层选?/span>
rownum
是随着l果集生成的Q一旦生成,׃会变化了Q同?/span>,生成的结? 是依ơ递加的,没有1永q不会有2!
rownum
是在 查询集合产生的过E中产生的伪列,q且如果where条g中存?/span> rownum 条g的话Q则:

1
Q?/span> 假如 判定条g是常量,则:
只能 rownum = 1, <= 大于1 的自然数Q?/span> = 大于1 的数是没有结果的Q?/span> 大于一个数也是没有l果?/span>
?/span> 当出C?/span> rownum 不满x件的时候则 查询l束   this is stop key!

2:
当判 定g是常量的时?/span>
若条件是 = var , 则只有当 var ?/span>1 的时候才满条gQ这个时候不存在 stop key ,必须q行 full scan ,Ҏ个满_?/span>where条g的数据进行判?/span>
选出一行后才能去?/span>rownum=2的行……



CONAN 2010-05-03 19:46 发表评论
]]>
Oracle递归查询http://m.tkk7.com/conans/articles/318052.htmlCONANCONANMon, 12 Apr 2010 05:35:00 GMThttp://m.tkk7.com/conans/articles/318052.html
有的情况下,我们需要用递归的方法整理数据,q才E序中很Ҏ做到Q但是在数据库中Q用SQL语句怎么实现Q下面我以最典型的树形结构来说明下如何在Oracle使用递归查询?
    Z说明方便Q创Z张数据库表,用于存储一个简单的树Şl构
Sql代码
  1. create table TEST_TREE  
  2. (  
  3.   ID   NUMBER,  
  4.   PID  NUMBER,  
  5.   IND  NUMBER,  
  6.   NAME VARCHAR2(32)  
  7. )  


    ID是主键,PID是父节点IDQIND是排序字D,NAME是节点名U。初始化几条试数据?/p>
ID PID IND NAME
1 0 1 根节?/td>
2 1 1 一U菜?
3 1 2 一U菜?
4 1 2 一U菜?
5 2 1 一U??
6 2 2 一U??
7 4 1 一U??
8 4 2 一U??
9 4 3 一U??
10 4 0 一U??

一、基本用:

    在Oracle中,递归查询要用到start   with 。。。。connect   by   prior。。?/p>

    具体格式是:

Sql代码
  1. SELECT column  
  2. FROM table_name  
  3. START WITH column=value  
  4. CONNECT BY PRIOR 父主?子外?nbsp;