答案 0 :(得分:11)
没有。 CTE - 由WITH
引入 - 不替换临时表,尽管在某些情况下它们可以用于过去可能使用临时表的地方。
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;
我们有一个完整的查询,它返回自己的行集(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;
现在,临时表是一种完全不同的动物。它与CTE或派生表有非常重要的区别:
Avg(SalesTotal)
计算将涉及第二次执行SalesTotals
聚合的完全独立的操作。虽然引擎有可能实现CTE的结果,但到目前为止SQL Server还没有这样做。值得注意的是,其他DBMS(如Oracle)可能会实现CTE的结果。无论如何,你应该知道这种双重查询可能会(当然!)严重影响性能。最后,CTE可以执行临时表不能执行的操作:它可以是递归的。在Oracle中,这通过CONNECT BY
表示,在SQL Server中,它在CTE内部使用UNION ALL SELECT
来完成,允许引用CTE自己的别名。
小心CTE - 它们是一个伟大的抽象,但只不过是,你可能会遇到严重的问题。生成一百万行可以使用递归CTE一次一行完成,但它可能是最差的一百次或更多。
SQL Server 2005中还有另一种特殊的临时表,称为“表变量”,它非常像临时表(并且在tempdb中保持完全相同),但有一些值得注意的例外:
答案 1 :(得分:1)
SQL优化器在选择优秀的执行计划方面做得更好,但是当加入10个以上的表时,特别是对于一些大型表和视图并且需要使用多个过滤器时,它通常不能以最佳方式执行。我仍然发现没有什么能像使用#TEMP表那样快,并且在将它们连接在一起之前将查询分解为更小的子集。注意:我很少发现向#TEMP表添加索引可以提高性能。
答案 2 :(得分:0)
不,这不正确。它们都是独立的功能部件,每个部件都有各自的用途。
例如,CTE适用于少量数据,而临时表通常更适合较大的数据集。可以对临时表进行索引并提高其性能,而CTE则不能。
我会花一点时间阅读MSDN文档并查看您将使用其中一个的特定实例