以下的文章主要向大家讲述的是SQL Server CTEs 的递归功能是SQL Server数据库中的三种保存临时结果的实际操作方法之一。其另两种是临时表与View,当然你也可以说View并不保存数据,从这一点上来将, CTE更像View一些。
当你的查询需要从一个源表中统计出结果,基于这个结果再做进一步的统计,如此3次以上的话,你必然会用到View或者临时表,现在你也可以考虑用CTE了。
CTE的语法相当的简单, 如下:
With CTE的名字 AS
(
子查询
)
Select * from CTE的名字
SQL Server CTEs支持在定义时引用自身,从而可以达到递归的目的,看下面的例子(1):
---preparetestdata SETNOCOUNTON; CREATETABLEdbo.Parts ( partidINTNOTNULLPRIMARYKEY, partnameVARCHAR(25)NOTNULL ); INSERTINTOdbo.Parts(partid,partname) select1,'BlackTea' unionallselect2,'WhiteTea' unionallselect3,'Latte' unionallselect4,'Espresso' CREATETABLEdbo.BOM ( partidINTNOTNULLREFERENCESdbo.Parts, assemblyidINTNULLREFERENCESdbo.Parts, unitVARCHAR(3)NOTNULL, qtyDECIMAL(8,2)NOTNULL, UNIQUE(partid,assemblyid), CHECK(partid<>assemblyid) ); INSERTINTOdbo.BOM(partid,assemblyid,unit,qty) select1,NULL,'EA',1.00 unionall select2,1,'EA',1.00 unionall select3,2,'EA',1.00 unionall select4,3,'EA',1.00 --performthetest WITHBOMTCAS( SELECTassemblyid,partid FROMdbo.BOM WHEREassemblyidISNOTNULL UNIONALL SELECTP.assemblyid,C.partid FROMBOMTCASP JOINdbo.BOMASCONC.assemblyid=P.partid ) SELECTDISTINCTassemblyid,partidFROMBOMTC;
输出结果如下:
例子(2):
createtableEmployee ( MgrIdint, EmpIdint, Titlenvarchar(256) ) insertintoemployee selectNULL,1,'CEO' unionall select1,2,'VP' unionall select2,3,'DevManager' unionall select2,4,'QAManager' unionall select1,5,'SalesManager' unionall select3,30,'Developer' unionall select3,31,'Developer' unionall select4,40,'Tester' unionall select4,41,'Tester' WithDirectReportsas ( selectMgrId,EmpId,Title,0as[Level]fromEmployeewhereMgrIdisnull unionall selecta.MgrId,a.EmpId,a.Title,[Level]+1as[Level] fromEmployeeajoinDirectReportsbona.MgrId=b.EmpId ) select*fromDirectReports
结果:
讲解:重点是子查询中的两个select语句,以上述例子加以说明:
***个Select子句被称为锚点语句,它返回的结果跟普通的SQL没有区别,在这里返回MgrID为null的员工。
第二个子句就没那么普通了,它被称为递归语句,请注重到在from后面, Employee和DirectReport进行了链接操作。你一定会问,DirectReport的定义还没完成,这个名字代表什么结果呢?答案是它不只是代表了一个结果,实际上代表了一系列的结果。换句话说,在DirectReport这个名字下,包含着DirectReport0,DirectReport1,DirectReport2…这些较小的集合。
DirectReport0 是Employee和锚点结合的产物;
DirectReport1 是Employee和 DirectReport0 结合的产物;
依次类推, DirectReport n是Employee和DirectReport n-1结合的产物;
当DirectReport_n为空的时候,这个过程就结束了。
*** 锚点和DirectReport0,DirectReport1… 的并集就是DirectReport的内容。
作为一个程序员,每次看到递归的程序,必然会想到无限递归这个错误。为了避免了在开发阶段,无限递归导致数据库的崩溃,SQL Server提供了一个QueryHint, MaxRecursion,可以控制递归的***层数,假如超过这个数字而仍为结束,则视为代码错误,强制退出。如:Option(MaxRecursion 10)
可见SQL Server CTEs可以用来递归操作树形结构的数据表。
【编辑推荐】
- SQL Server浮点数据类型的详细解析卸载SQL Server 2005组件的正确顺序SQL Server 2000删除实战演习SQL Server存储过程的命名标准如何进行?Server数据库的临时表的正确操作步骤