了解Sql Server2005CTE的用法
1.什么是CTE
指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在 SELECTINSERTUPDATE DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表表达式。
CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效。
与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次。
2.语法
[ WITH <common_table_expression> [ ,...n ] ]
<common_table_expression>::=
        expression_name [ ( column_name [ ,...n ] ) ]
    AS
        ( CTE_query_definition )
参数:
expression_name
公用表表达式的有效标识符。 expression_name 必须与在同一 WITH <common_table_expression> 子句中定义的任何其他公用表表达式的名称不同,但 expression_name 可以与基表或基视图的名称相同。在查询中对 expression_name 的任何引用都会使用公用表表达式,而不使用基对象。
column_name
在公用表表达式中指定列名。在一个 CTE 定义中不允许出现重复的名称。指定的列名数必须与 CTE_query_definition 结果集中列数匹配。只有在查询定义中为所有结果列都提供了不同的名称时,列名称列表才是可选的。
CTE_query_definition
指定一个其结果集填充公用表表达式的 SELECT 语句。除了 CTE 不能定义另一个 CTE 以外,CTE_query_definition SELECT 语句必须满足与创建视图时相同的要求。
3.创建和使用CTE
1)应用于非递归 CTE
·      CTE 之后必须跟随引用部分或全部 CTE 列的 SELECTINSERTUPDATE DELETE 语句。也可以在 CREATE VIEW 语句中将 CTE 指定为视图中 SELECT 定义语句的一部分。
·      可以在非递归 CTE 中定义多个 CTE 查询定义。定义必须与以下集合运算符之一结合使用:UNION ALLUNIONsql中delete用法INTERSECT EXCEPT
·      CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。
·
      不允许在一个 CTE 中指定多个 WITH 子句。例如,如果 CTE_query_definition 包含一个子查询,则该子查询不能包括定义另一个 CTE 的嵌套的 WITH 子句。
·      不能在 CTE_query_definition 中使用以下子句:
·  COMPUTE COMPUTE BY
·  ORDER BY(除非指定了 TOP 子句)
·  INTO
·  带有查询提示的 OPTION 子句
·  FOR XML
·  FOR BROWSE
·      如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾。
·
      可以使用引用 CTE 的查询来定义游标。
·      可以在 CTE 中引用远程服务器中的表。
·      在执行 CTE 时,任何引用 CTE 的提示都可能与该 CTE 访问其基础表时发现的其他提示相冲突,这种冲突与引用查询中的视图的提示所发生的冲突相同。发生这种情况时,查询将返回错误。
2)定义和使用递归 CTE
a. 定义递归 CTE
·  递归 CTE 定义至少必须包含两个 CTE 查询定义,一个定位点成员和一个递归成员。可以定义多个定位点成员和递归成员;但必须将所有定位点成员查询定义置于第一个递归成员定义之前。所有 CTE 查询定义都是定位点成员,但它们引用 CTE 本身时除外。
·  定位点成员必须与以下集合运算符之一结合使用:UNION ALLUNIONINTERSECT EXCEPT。在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用 UNION ALL 集合运算符。
·  定位点成员和递归成员中的列数必须一致。
·  递归成员中列的数据类型必须与定位点成员中相应列的数据类型一致。
·  递归成员的 FROM 子句只能引用一次 CTE expression_name
·  在递归成员的 CTE_query_definition 中不允许出现下列项:
·  SELECT DISTINCT
·  GROUP BY
·  HAVING
·  标量聚合
·  TOP
·  LEFTRIGHTOUTER JOIN(允许出现 INNER JOIN
·  子查询
·  应用于对 CTE_query_definition 中的 CTE 的递归引用的提示。
b. 使用递归 CTE
·  无论参与的 SELECT 语句返回的列的为空性如何,递归 CTE 返回的全部列都可以为空。
·  如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。可以使用 MAXRECURSION 提示以及在 INSERTUPDATEDELETE SELECT 语句的 OPTION 子句中的一个 0 32,767 之间的值,来限制特定语句所允许的递归级数,以防止出现无限循环。这样就能够在解决产生循环的代码问题之前控制语句的执行。服务器范围内的默认值是 100。如果指定 0,则没有限制。每一个语句只能指定一个 MAXRECURSION 值。
·  不能使用包含递归公用表表达式的视图来更新数据。
·  可以使用 CTE 在查询上定义游标。递归 CTE 只允许使用快速只进游标和静态(快照)游标。如果在递归 CTE 中指定了其他游标类型,则该类型将转换为静态游标类型。
·  可以在 CTE 中引用远程服务器中的表。如果在 CTE 的递归成员中引用了远程服务器,那么将为每个远程表创建一个假脱机,这样就可以在本地反复访问这些表。
如果定义了多个 CTE_query_definition,则这些查询定义必须用下列一个集合运算符联接起来:UNION ALLUNIONEXCEPT INTERSECT
4.优点
简化查询语句,提高SQL语句的可维护性。
5.注意事项
1)定义CTE后,必须紧跟CTESQL语句(如selectinsertupdate等),否则,显示出现语法错误或对象名无效等错误,CTE也会失效。
2CTE后可以再定义CTE,但是共用一个with
3CTE的名字可以与表或视图名字相同。
4)如果将 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)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。