Mik*_*oud 2 t-sql sql-server common-table-expression sql-server-2008
指定临时命名结果集,称为公用表表达式(CTE).
它似乎WITH是#TEMP表的替代品.那是对的吗?
Eri*_*ikE 11
CTE - 由WITH--don't 引入 - 替换临时表,尽管在某些情况下,它们可以用于过去可能使用临时表的地方.
WITH 实际上只是一个派生表,区别在于它是在查询之前引入而不是内联,并且给出了一个别名,然后可以在整个查询中多次使用该表.
派生表是括号内的完整查询,就像它是真实表一样.视图和表值函数也被视为派生表,但我们关注的是内联定义的类型.这是一个例子:
SELECT
C.Name,
S.SalesTotal
FROM
dbo.Customer C
INNER JOIN (
SELECT
O.CustomerID,
SalesTotal = Sum(OrderTotal)
FROM
dbo.CustomerOrder O
GROUP BY
O.CustomerID
) S
ON C.CustomerID = S.CustomerID;
Run Code Online (Sandbox Code Playgroud)
我们有一个完整的查询,返回自己的行集(GROUP BY查询).通过将其置于括号内并为其指定别名S,我们现在可以像表一样使用它.我们可以加入更多表格.但是,我们只加入过这个表一次.
要将此转换为CTE,我们进行了一个非常简单的更改:
WITH SalesTotals AS (
SELECT
O.CustomerID,
SalesTotal = Sum(OrderTotal)
FROM
dbo.CustomerOrder O
GROUP BY
O.CustomerID
)
SELECT
C.Name,
S.SalesTotal
FROM
dbo.Customer C
INNER JOIN SalesTotals S
ON C.CustomerID = S.CustomerID
-- and for an example of using the CTE twice:
INNER JOIN (
SELECT Avg(SalesTotal)
FROM SalesTotals
) A (AverageSalesTotal)
ON S.SalesTotal >= A.AverageSalesTotal;
Run Code Online (Sandbox Code Playgroud)
现在,临时表是一种完全不同的动物.它与CTE或派生表有非常重要的区别:
Avg(SalesTotal)SQL Server版本至少到2012年的计算将涉及SalesTotals第二次执行聚合的完全独立的操作.虽然引擎有可能实现CTE的结果,但到目前为止SQL Server还没有这样做.值得注意的是,其他DBMS(如Oracle)可能会实现CTE的结果.在任何情况下,您应该意识到这种双重查询可能(当然!)严重的性能影响.最后,CTE可以做临时表不能做的事情:它可以是递归的.在Oracle中,这表示通过CONNECT BY,并且在SQL Server中,它是UNION ALL SELECT在CTE内部完成的,允许引用CTE自己的别名.
小心CTE - 它们是一个很好的抽象,但只不过是这样,你可能会遇到严重问题.生成一百万行可以一次一行地使用递归CTE来完成,但它可能是最差的一百次或多次.
SQL Server 2005中还有另一种特殊的临时表,称为"表变量",它非常像临时表(并且在tempdb中保持完全相同),但有一些值得注意的例外: