oracle 递归语句及临时表、执行计划、报表

xiaoxiao2026-05-22  2

[color=red]start with connect by[/color] oracle 提供了start with connect by 语法结构可以实现递归查询。 1. 一个简单举例: SQL> select * from test; BILL_MONTH DAY_NUMBER MSISDN -------------------- ---------- -------------------- 200803 1 13800 200803 3 13800 200803 2 13800 200803 2 13801 200803 4 13804 200803 5 13804 200803 7 13804 200803 8 13804 200803 6 13802 200803 6 13801 200803 7 13801 200803 8 13801 12 rows selected SQL> SQL> select * from test 2 start with day_number=1 3 connect by prior day_number=day_number+1 and prior msisdn= msisdn 4 ; BILL_MONTH DAY_NUMBER MSISDN -------------------- ---------- -------------------- 200803 1 13800 200803 2 13800 200803 3 13800 SQL> 上面的语句查找出了从1开始,并且day_number 逐渐+1 递增的,并且 msisdn 相同的哪些个数据. [color=red]2. start with connect by 语法结构[/color] 如上面说看到的 例子, 其语法结构为 start with condition connect by condition (含 prior 关键字) start with conditon 给出的seed 数据的范围, connect by 后面给出了递归查询的条件,prior 关键字表示父数据,prior 条件表示子数据需要满足父数据的什么条件。 在下面的这个start with connect by 结构中,就表示 查找出了从1开始,并且day_number 逐渐+1 递增的,并且 msisdn 相同的那些个数据. start with day_number=1 connect by prior day_number=day_number+1 and prior msisdn= msisdn [color=red]3. 执行计划[/color] 对于这个特殊的语法结构,我们来看看它的执行计划。 通过下面的执行计划,我们可以看出,对于简单的访问一个对象的递归查询,实际上oracle 要三次访问要查询的对象。因此,这一个告诉我们,在使用递归查询时,一定要谨慎,因为即使原表数据不多,但是三倍的访问喜爱来,代价也会很大。 SQL>set timing on --显示执行时间 SQL>set autotrace on �C显示执行计划 SQL>set autotrace traceonly �C只显示执行计划即不显示查询出来的数据 SQL> explain plan for 2 2 select * from test 3 --where bill_month='200803' 4 start with day_number=1 5 connect by prior day_number=day_number+1 and prior msisdn= msisdn 6 ; Explained SQL> select * from table( dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- ------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost | ------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | | |* 1 | CONNECT BY WITH FILTERING| | | | | |* 2 | FILTER | | | | | | 3 | TABLE ACCESS FULL | TEST | | | | | 4 | NESTED LOOPS | | | | | | 5 | BUFFER SORT | | | | | | 6 | CONNECT BY PUMP | | | | | |* 7 | TABLE ACCESS FULL | TEST | | | | | 8 | TABLE ACCESS FULL | TEST | | | | ------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("TEST"."DAY_NUMBER"=1) 2 - filter("TEST"."DAY_NUMBER"=1) PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 7 - filter("TEST"."MSISDN"=NULL AND "TEST"."DAY_NUMBER"+1=NULL) Note: rule based optimization 23 rows selected SQL> 另外,发现了在含有其他条件的递归中,是先处理所有的递归查询,最后才用加入的条件过滤. 请看下面的例子。 和上面的执行计划对比下我们可以知道,加入条件 where bill_month='200803' 后,实际上却是在递归完成后,最后才执行的 1 - filter("TEST"."BILL_MONTH"='200803') 。 所以,为了确保语句的性能,不要直接加入条件在start with connect by 结构中,而是要想办法将原表的数据控制住。这个可以采用子查询的办法,或者使用临时表等(最好采用临时表,将数据量从本源上控制住;因为从子查询的执行计划我们可以看到,它每次也都是访问全表,再用条件过滤,要重复三次,不是一次过滤就够了). 两种临时表的语法: create global temporary table 临时表名 on commit preserve|delete rows 用preserve时就是SESSION级的临时表,用delete就是TRANSACTION级的临时表 [color=red]报表命令[/color] ttitle、btitle、break、compute、spool
转载请注明原文地址: https://www.6miu.com/read-5049168.html

最新回复(0)