SQL Server 使用CTE

1.什么是CTE

         CTE的全称是Common Table Expression,翻译过来就是公用表表达式。该表达式源自简单查询,可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集。CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效。与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次。

2.CTE优点

        使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。
 
        查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。
 

3.CTE可使用的范围

      可以在用户定义的例程(如函数、存储过程、触发器或视图)中定义 CTE。

 

4.CTE的语法

 
  1. [WITH <common_table_expression> [ ,...n ]]  
  2. <common_table_expression>::=  
  3.         expression_name [( column_name [ ,...n ] )]  
  4.     AS  
  5.         (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 语句必须满足与创建视图时相同的要求。 

5.定义和使用CTE 

(1)应用于非递归 CTE

CTE 之后必须跟随引用部分或全部 CTE 列的 SELECT、INSERT、UPDATE 或 DELETE 语句。也可以在 CREATE VIEW 语句中将 CTE 指定为视图中 SELECT 定义语句的一部分。可以在非递归 CTE 中定义多个 CTE 查询定义。定义必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。不允许在一个 CTE 中指定多个 WITH 子句。例如,如果 CTE_query_definition 包含一个子查询,则该子查询不能包括定义另一个 CTE 的嵌套的 WITH 子句。不能在 CTE_query_definition 中使用以下子句:

COMPUTE 或 COMPUTE BY

   ORDERBY(除非指定了 TOP 子句)

   INTO

  带有查询提示的 OPTION 子句

   FORXML

   FORBROWSE

   如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾。

   可以使用引用 CTE 的查询来定义游标。

   可以在 CTE 中引用远程服务器中的表。

   在执行 CTE 时,任何引用 CTE 的提示都可能与该 CTE 访问其基础表时发现的其他提示相冲突,这种冲突与引用查询中的视图的提示所发生的冲突相同。发生这种情况时,查询将返回错误。

 (2)定义和使用递归 CTE

a. 定义递归 CTE

定位点成员必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用 UNION ALL 集合运算符。递归 CTE 定义至少必须包含两个 CTE 查询定义,一个定位点成员和一个递归成员。可以定义多个定位点成员和递归成员;但必须将所有定位点成员查询定义置于第一个递归成员定义之前。所有 CTE 查询定义都是定位点成员,但它们引用 CTE 本身时除外。定位点成员和递归成员中的列数必须一致。递归成员中列的数据类型必须与定位点成员中相应列的数据类型一致。递归成员的 FROM 子句只能引用一次 CTEexpression_name。在递归成员的 CTE_query_definition 中不允许出现下列项:

   SELECT DISTINCT

   GROUPBY

   HAVING

   标量聚合

   TOP

   LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)

   子查询

   应用于对 CTE_query_definition 中的 CTE 的递归引用的提示。

b. 使用递归 CTE

   无论参与的 SELECT 语句返回的列的为空性如何,递归 CTE 返回的全部列都可以为空。

   如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。可以使用 MAXRECURSION 提示以及在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中的一个 0 到 32,767 之间的值,来限制特定语句所允许的递归级数,以防止出现无限循环。这样就能够在解决产生循环的代码问题之前控制语句的执行。服务器范围内的默认值是 100。如果指定 0,则没有限制。每一个语句只能指定一个 MAXRECURSION 值。

   不能使用包含递归公用表表达式的视图来更新数据。

   可以使用 CTE 在查询上定义游标。递归 CTE 只允许使用快速只进游标和静态(快照)游标。如果在递归 CTE 中指定了其他游标类型,则该类型将转换为静态游标类型。

   可以在 CTE 中引用远程服务器中的表。如果在 CTE 的递归成员中引用了远程服务器,那么将为每个远程表创建一个假脱机,这样就可以在本地反复访问这些表。

如果定义了多个 CTE_query_definition,则这些查询定义必须用下列一个集合运算符联接起来:UNION ALL、UNION、EXCEPT 或 INTERSECT。

原文地址:https://www.cnblogs.com/CatHeadTiger/p/3056997.html