SQL Server2005雜談(1):使用公用表表達式(CTE)簡化嵌套SQL

select  *  from  person.StateProvince  where  CountryRegionCode  in  
         (
select  CountryRegionCode  from  person.CountryRegion  where  Name  like  ' C% ' )

    上面的查詢語句使用了一個子查詢。雖然這條 SQL 語句並不複雜,但若是嵌套的層次過多,會使 SQL 語句很是難以閱讀和維護。所以,也可使用表變量的方式來解決這個問題, SQL 語句以下:

declare  @t  table (CountryRegionCode  nvarchar ( 3 ))
insert  into  @t (CountryRegionCode)  ( select  CountryRegionCode  from  person.CountryRegion  where  Name  like  ' C% ' )

select  *  from  person.StateProvince  where  CountryRegionCode 
                     
in  ( select  *  from  @t )

    雖然上面的SQL 語句要比第一種方式更復雜,但卻將子查詢放在了表變量@t 中,這樣作將使SQL 語句更容易維護,但又會帶來另外一個問題,就是性能的損失。因爲表變量實際上使用了臨時表,從而增長了額外的I/O 開銷,所以,表變量的方式並不太適合數據量大且頻繁查詢的狀況。爲此,在SQL Server 2005 中提供了另一種解決方案,這就是公用表表達式(CTE ),使用CTE ,可使SQL 語句的可維護性,同時,CTE 要比表變量的效率高得多。
    下面是 CTE 的語法:

[  WITH <common_table_expression> [ , ]  ]
< common_table_expression > :: =
        expression_name 
[  ( column_name [ , ]  ) ]
    
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 是一個公用表表達式,該表達式在使用上與表變量相似,只是SQL Server 2005 在處理公用表表達式的方式上有所不一樣。
    在使用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的數據表
4. CTE 能夠引用自身,也能夠引用在同一 WITH 子句中預先定義的 CTE 。不容許前向引用。
5.  不能在 CTE_query_definition 中使用如下子句:
1 COMPUTE COMPUTE BY
2 ORDER BY (除非指定了 TOP 子句)
3 INTO
4 )帶有查詢提示的 OPTION 子句
5 FOR XML
6 FOR BROWSE
6.  若是將 CTE 用在屬於批處理的一部分的語句中,那麼在它以前的語句必須以分號結尾,以下面的SQL 所示:
declare  @s  nvarchar ( 3 )
set  @s  =  ' C% '
;  
--  必須加分號
with
t_tree 
as
(
    
select  CountryRegionCode  from  person.CountryRegion  where  Name  like  @s
)
select  *  from  person.StateProvince  where  CountryRegionCode  in  ( select  *  from  t_tree)
    CTE 除了能夠簡化嵌套SQL 語句外,還能夠進行遞歸調用,關於這一部分的內容將在下一篇文章中介紹。
相關文章
相關標籤/搜索