微软从SQl2005起引入了CTE(Common Table Expression)以强化T-SQL。这是一个类似于非持久视图的好东东。
按照MSDN介绍
1、公用表表达式 (CTE) 可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集 。CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效 。与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次 。
CTE 可用于:
创建递归查询。有关详细信息,请参阅使用公用表表达式的递归查询 。
在不需要常规使用视图时替换视图,也就是说,不必将定义存储在元数据中。
启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。
在同一语句中多次引用生成的表。
使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。可以在用户定义的例程(如函数、存储过程、触发器或视图)中定义 CTE。
2、公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE 。递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式。当某个查询引用递归 CTE 时,它即被称为递归查询 。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。
递归 CTE 可以极大地简化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句中运行递归查询所需的代码。在 SQL Server 的早期版本中,递归查询通常需要使用临时表、游标和逻辑来控制递归步骤流。有关公用表表达式的详细信息,请参阅使用公用表表达式 。
这里举例说明如下:
IF OBJECT_ID('Cate') IS NOT NULL
DROP TABLE CATE
GO
CREATE TABLE Cate
(
ID INT IDENTITY(1,1) PRIMARY KEY,
[C_Name] NVARCHAR(50),
[C_Level] [int] NOT NULL,
[C_Code] NVARCHAR(255) NULL,
[C_Parent] [int] NOT NULL
)
GO
INSERT INTO [Cate] VALUES('分类1',1,'0',0 )
INSERT INTO [Cate] VALUES('分类2',1,'0',0 )
INSERT INTO [Cate] VALUES('分类3',1,'0',0 )
INSERT INTO [Cate] VALUES('分类4',1,'0',0 )
INSERT INTO [Cate] VALUES('分类5',2,'1/',1 )
INSERT INTO [Cate] VALUES('分类6',2,'1/',1 )
INSERT INTO [Cate] VALUES('分类7',2,'2/',2 )
INSERT INTO [Cate] VALUES('分类8',2,'2/',2 )
INSERT INTO [Cate] VALUES('分类9',3,'1/5',5 )
INSERT INTO [Cate] VALUES('分类10',3,'1/6',6 )
INSERT INTO [Cate] VALUES('分类11',4,'1/5/9',9 )
INSERT INTO [Cate] VALUES('分类12',4,'1/5/9/11',10 )
GO
--WCT第一种方法
;WITH CTETBL AS
(
SELECT ID,[C_Name],C_Parent,[C_Code] FROM [Cate] WHERE ID=1 UNION ALL
SELECT A.ID,A.[C_Name],A.C_Parent,A.[C_Code] FROM
CTETBL B INNER JOIN
[Cate] A
ON B.ID=A.[C_Parent]
)
SELECT * FROM CTETBL order by id
--WCT第二种方法,(在查询的时候加上级别,Sublevel字段表现的淋漓尽致)
;WITH CTETBL2(C_Name, ID, C_Code,C_Parent,Sublevel) AS
(SELECT C_Name, ID, C_Code,C_Parent,0 FROM [Cate] WHERE ID =1
UNION ALL
SELECT p.C_Name, p.ID, p.C_Code,p.C_parent,Sublevel+1
FROM [Cate] P INNER JOIN
CTETBL2 A ON A.ID = P.C_Parent
)
SELECT * FROM CTETBL2
GO
--如果数据库表结构设计的好.
SELECT ID,[C_Name],C_Parent,[C_Code],
ISNULL((SELECT TOP 1 C_Name FROM [Cate] A WHERE A.ID=S.C_Parent ),'') PName
FROM [Cate] S
WHERE C_Code like '1/%'
GO
GO
这个应用示例重在简化业务逻辑 ,即便是性能不佳,但对临时表\表变量\游标等传统处理方式是一种业务层次上的简化或者说是优化。
部分内容转自:http://www.jzxue.com/shujuku/mssqlserver/200910/24-3001.html