27,579
社区成员
发帖
与我相关
我的任务
分享
--测试环境
--Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)
-- Jul 9 2008 14:43:34
-- Copyright (c) 1988-2008 Microsoft Corporation
-- Enterprise Evaluation Edition on Windows NT 5.1 <X86> (Build 2600: Service Pack 3, v.5938)
--测试TSQL
with leno (r)
as
(
select 1 r
union all
select r + 1 from leno where r <5
)
select * from leno
--测试结果
r
-----------
1
2
3
4
5
(5 行受影响)
SELECT SUBSTRING(@Lctext2,number,1) as value
from master..spt_values
where type='p' and number <=LEN(@Lctext2)and CHARINDEX(SUBSTRING(@Lctext2,number,1),@Lctext1)>0
/*****************************************************************
*CTE应用示例
*版权所有:Gaojier 引用请注明
******************************************************************/
--一、语法
--[ 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 语句必须满足与创建视图时相同的要求。
--如果定义了多个 CTE_query_definition,则这些查询定义必须用下列一个集合运算符联接起来:
--UNION ALL、UNION、EXCEPT 或 INTERSECT。
--三、递归
--伪代码和语义
--递归 CTE 结构必须至少包含一个定位点成员和一个递归成员。
--以下伪代码显示了包含一个定位点成员和一个递归成员的简单递归 CTE 的组件。
--WITH cte_name ( column_name [,...n] )
--AS
--(
--CTE_query_definition –- Anchor member is defined.
--UNION ALL
--CTE_query_definition –- Recursive member is defined referencing cte_name.
--)
---- Statement using the CTE
--SELECT *
--FROM cte_name
--递归执行的语义如下:
--将 CTE 表达式拆分为定位点成员和递归成员。
--运行定位点成员,创建第一个调用或基准结果集 (T0)。
--运行递归成员,将 Ti 作为输入,将 Ti+1 作为输出。
--重复步骤 3,直到返回空集。
--返回结果集。这是对 T0 到 Tn 执行 UNION ALL 的结果。
--四、示例
--A.简单的CTE
USE AdventureWorks;
GO
WITH DirReps(ManagerID, DirectReports) AS
(
SELECT ManagerID, COUNT(*)
FROM HumanResources.Employee AS e
WHERE ManagerID IS NOT NULL
GROUP BY ManagerID
)
SELECT ManagerID, DirectReports
FROM DirReps
ORDER BY ManagerID;
GO
--B.基表覆盖
CREATE TABLE T1(id INT)
INSERT T1
SELECT 1 UNION ALL
SELECT 2
CREATE TABLE T2(id INT)
GO
WITH T2 AS(
SELECT * FROM T1)
DROP tal
SELECT * FROM T2
SELECT * FROM T2 --此处的查询结果已经不再是CTE的内容引用
WITH T3 AS
(
SELECT * FROM T1
)
SELECT * FROM T3
SELECT * FROM T3 --此时会提示错误
DROP TABLE T1
DROP TABLE T2
--C.递归
CREATE TABLE Dept(
id INT PRIMARY KEY,
parent_id INT,
NAME NVARCHAR(20))
INSERT Dept
SELECT 0,0,N'青岛软控' UNION ALL
SELECT 1,0,N'财务管理部' UNION ALL
SELECT 2,0,N'总裁办' UNION ALL
SELECT 3,0,N'市场营销部' UNION ALL
SELECT 4,0,N'软控研究院' UNION ALL
SELECT 5,4,N'电子信息研究所' UNION ALL
SELECT 6,4,N'信息工程研究所' UNION ALL
SELECT 7,6,N'MES组' UNION ALL
SELECT 8,6,N'控制开发组' UNION ALL
SELECT 9,7,N'数据库开发'
GO
--查询指定部门下面的所有部门
DECLARE @DeptName NVARCHAR(20)
SET @DeptName=N'信息工程研究所'
;WITH
Detpts AS
(
--定位点成员
SELECT * FROM Dept
WHERE NAME=@DeptName
UNION ALL
SELECT A.*
FROM Dept A,Detpts B
WHERE A.parent_id=B.id
)
SELECT * FROM Detpts
DROP TABLE Dept
--D.综合应用
--示例要求:查询指定部门下面的所有部门,同时汇总各部门的下级部门的数来
DECLARE @DeptName NVARCHAR(20)
SET @DeptName=N'信息工程研究所'
;WITH
DEPTS AS
(
SELECT * FROM Dept
WHERE [NAME]=@DeptName
UNION ALL
SELECT A.*
FROM Dept A,DEPTS B
WHERE A.parent_id=B.id
),
DEPTCHILD AS
(
SELECT Dept_id=P.id,C.id,C.parent_id
FROM DEPTS P,Dept C
WHERE P.id=C.parent_id
UNION ALL
SELECT P.Dept_id,C.id,C.parent_id
FROM DEPTCHILD P,Dept C
WHERE p.id=C.parent_id
),
DEPTCHILDCNT AS
(
SELECT Dept_id,Cnt=COUNT(*)
FROM DEPTCHILD
GROUP BY Dept_id
)
SELECT D.*,ChildDeptCnt=ISNULL(DS.Cnt,0)
FROM DEPTS D LEFT JOIN
DEPTCHILDCNT DS ON D.id=DS.Dept_id
--总结:递归经常用于树形菜单、产品结构、组织结构类应用中。
解决方案:
with leno (r)
as
(
select 1 r
union all
select r + 1 from leno where r < 3000
)
select COUNT(*) from leno
OPTION ( MAXRECURSION 0 )
-----------
3000
(1 row(s) affected)
消息 530,级别 16,状态 1,第 1 行
语句被终止。完成执行语句前已用完最大递归 100。