oracle with语句

http://lzfhope.blog.163.com/blog/static/6363992200919101257971/?suggestedreading&wumii

重新发现with语句  

2009-02-09 10:12:57|  分类: sql解析与技巧 |  标签:with  oracle  性能   |字号 订阅

 
 
        程序越编越多,忽然发现,可以利用with语句提高部分性能和工作效率,这是上周对oracle的一个比较大发现。
        oracle会把这个oracle语句当成一个内建视图或者临时表使用。
        有的时候,例如写过程,需要先用临时表存储一些预先计算好的数据,比较传统的方式就是直接使用临时表或者一个视图。但是这样做在某些情况下是由局限性或者不足的地方的,例如:
        1)如果使用临时表,那么每次都需要truncate下,编写过程的语句增加,当然你可以忽略这种增加。但是当许多类似的情况存在的时候,大量的临时表存在也是个麻烦的事情,作为人和服务器在管理这些临时表的时候都显得有点麻烦。这样的情况虽然不多,但是存在。
        2) 如果使用常规的视图,虽然能够省掉临时表的麻烦,但是同样存在另外一个问题:在某些场合,类似或者同样的SQL可能不得不写一次以上,例如以下结构的语句(为了方便,不写出v的具体内容):
        select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
        也许有人说,为什么x,y不合并在一起,这样视图v只要出现一次就可以了。不研究这个,总之有这个存在的理由和必要性。
        如果这样来写,那么不但写起来比较麻烦,其次对于性能没有任何好处,对于这样的视图,oracle并不会自动地只执行一次扫描,所以就这个方面也需要多浪费一些时间。
        但至少在在以上的情形下,with语句的子查询,可以体现出优势来。例如使用with子句上文的sql可以这么写:
        with v as (select * from xxx where xx )
          select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
        前面说过了,oracle会把这种子查询当作内建视图或者临时表,不过是内建视图还是临时表,都可以在一个地方定义,一次产生,并处处引用(自生除外,这个应该很好理解)。如果是以内建视图存在,效率明显又会更快一些,因为是内存上;如果是临时表,则省却了管理临时表的麻烦。最关键的是省掉了常规视图的多次查询导致效率下降的问题。
        目前唯一不确定的是:当数据量比较大的时候,这个方式会不会比较低效。我的想法是不会。

       几种情况下的with语句位置.
       1)  insert into 语句
         insert into
           with v as (  )
            ...  select * from v
        2) select into 语句
        with v as ()
            select ..  into .. from v..
        3)open cursor 语句
        open c
        with v as () 
             select .... from v
       4) update 语句
        update  a set ()=(
           with v as ()
           select ..  from v
         );
         但这个看起来,好像只能针对更新一个列的情况,如果列的个数>=2,那么会提示语法错误.

posted @ 2013-04-01 15:09  rattersnake  阅读(3133)  评论(0编辑  收藏  举报