1. 程式人生 > >ORACLE 中 WITH AS 的用法

ORACLE 中 WITH AS 的用法

下面是摘抄並整合的部分。

一.WHAT:

    WITH AS短語,也叫做子查詢部分(subquery factoring,可以用來定義一個SQL片斷,該SQL片斷會被整個SQL語句所用,也可以提高sql語句的可讀性,
也有可能是在UNION ALL的不同部分,作為提供資料的部分。其中特別對於UNION ALL比較有用。因為UNION ALL的每個部分可能相同,但是如果每個部分都去執行一遍的話,則成本太高,所以可以使用WITH AS短語,則只要執行一遍即可。

    如果WITH AS短語所定義的表名被呼叫兩次以上,則優化器會自動將WITH AS短語所獲取的資料放入一個TEMP表裡,如果只是被呼叫一次,則不會。而提示materialize則是強制將WITH AS短語裡的資料放入一個全域性臨時表裡。很多查詢通過這種方法都可以提高速度。


二.HOW:

先看下面一個巢狀的查詢語句:
select * from StateProvince where CountryRegionCode in
         (select CountryRegionCode from CountryRegion where Name like 'C%')

    上面的查詢語句使用了一個子查詢。雖然這條SQL語句並不複雜,但如果巢狀的層次過多,會使SQL語句非常難以閱讀和維護。此時可以使用公用表表達式(CTE),使用CTE,可以提高SQL語句的可維護性,同時,CTE要比表變數的效率高得多。

    下面是CTE的語法:
[ WITH <common_table_expression> [ ,n ] ]
<common_table_expression>::=
        expression_name [ ( column_name [ ,n ] ) ]
    AS
        ( CTE_query_definition )

    現在使用CTE來解決上面的問題,SQL語句如下:
with
cr as
(
    select CountryRegionCode from person.CountryRegion where Name like 'C%'
)
select * from person.StateProvince where CountryRegionCode in (select * from cr)

    其中cr是一個公用表表達式,該表示式在使用上與表變數類似。

    在使用CTE時應注意如下幾點:
1. CTE後面必須直接跟使用CTE的SQL語句(如select、insert、update等),否則,CTE將失效。如下面的SQL語句將無法正常使用CTE:
with
cr as
(
    select CountryRegionCode from person.CountryRegion where Name like 'C%'
)
select * from person.CountryRegion  -- 應將這條SQL語句去掉
-- 使用CTE的SQL語句應緊跟在相關的CTE後面 --
select * from person.StateProvince where CountryRegionCode in (select * from cr)

2. CTE後面也可以跟其他的CTE,但只能使用一個with,多個CTE中間用逗號(,)分隔,如下面的SQL語句所示:
with
cte1 as
(
    select * from table1 where name like 'abc%'
),
cte2 as
(
    select * from table2 where id > 20
),
cte3 as
(
    select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

3. 如果CTE的表示式名稱與某個資料表或檢視重名,則緊跟在該CTE後面的SQL語句使用的仍然是CTE,當然,後面的SQL語句使用的就是資料表或檢視了,如下面的SQL語句所示:
--  table1是一個實際存在的表
with
table1 as
(
    select * from persons where age < 30
)
select * from table1  --  使用了名為table1的公共表表達式
select * from table1  --  使用了名為table1的資料表

    讀過以上內容之後在理解的基礎上已經能看懂並維護之前的sql語句了。按照公司安全協議經過脫密處理後的程式碼如下:

WITH 
  TABLEA 
AS  
(SELECT COLUMN1,COLUMN2 FROM TABLEB   
 WHERE COLUMN1 IN ('01','02') 
 AND COLUMN3='CD04') 
SELECT T1.COLUMN4, T3.COLUMN2   
FROM TABLEC T1  
INNER JOIN TABLEA T3 
  ON T1.COLUMN5 = T3.COLUMN1  
WHERE T1.COLUMN6 = '2112000000'  
ORDER BY T1.COLUMN7