Sql server 是用临时工作台的替代品吗?
因此,根据我所看到的使用的方式,以及: 指定临时命名结果集,称为公共表表达式(CTE) 似乎带的Sql server 是用临时工作台的替代品吗?,sql-server,sql-server-2008,tsql,common-table-expression,Sql Server,Sql Server 2008,Tsql,Common Table Expression,因此,根据我所看到的使用的方式,以及: 指定临时命名结果集,称为公共表表达式(CTE) 似乎带的是#TEMP表格的替代品。这是正确的吗?否。CTE(由和引入)不会替换临时表,尽管在某些情况下,它们可以用于过去可能使用临时表的地方 WITH实际上只是一个派生表,不同之处在于它是在查询之前引入的,而不是内联的,并且被赋予了一个别名,可以在整个查询中多次用作表 派生表是一个完整的查询,位于圆括号内,使用起来就像是一个实表一样。视图和表值函数也被认为是派生表,但我们关注的是内联定义的类型。以下是一个例子
是#TEMP
表格的替代品。这是正确的吗?否。CTE(由和
引入)不会替换临时表,尽管在某些情况下,它们可以用于过去可能使用临时表的地方
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;
我们有一个完全完整的查询,它返回自己的行集(groupby
查询)。通过将其放在括号内并为其指定别名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或派生表有非常重要的区别:
- temp表在多个查询中持续存在(在客户端连接的生命周期内,或直到显式删除),但CTE仅“存在”一个查询
- CTE虽然在逻辑上是一个“单个”表,但如果在查询中多次使用,则可能会多次生成其数据。临时表的数据可以简单地作为任何其他“真实”表读取。在上面的示例中,至少在2012年之前的SQL Server版本中,
计算将涉及第二次执行Avg(SalesTotal)
聚合的完全独立操作。虽然引擎可以具体化CTE的结果,但到目前为止SQL Server还没有这样做。值得注意的是,其他DBMS(如Oracle)可能会实现CTE的结果。在任何情况下,您都应该意识到这种双重查询可能(当然!)带来严重的性能影响SalesTotals
- 临时表自动生成列统计信息,这有助于查询优化器选择更好的执行计划。CTE的“final”行集没有统计信息——使用底层表的统计信息
- 临时表可以通过多条语句或重复语句增量添加或删除。它可以被更新
- 可以修改临时表以添加或删除列或更改数据类型
- 临时表可以具有聚集索引和非聚集索引以及约束
- 在用户定义的函数中,不能以任何方式使用临时表
- CTE虽然看起来像是在逻辑上分隔查询的各个部分,但并没有这样做。CTE是谓词下推、消除的完美候选,如果确定它们不会影响最终行集(或它们的一些表或联接被消除),或者它们可能会受到意外表达式求值顺序的影响。例如,在CTE中,您可能只返回文本列中的数字字符串,而在外部查询中,尝试将这些字符串转换为数字数据类型,但令人惊讶的是,您在尝试将非数字字符串转换为数字数据类型时出错。这是因为优化器可以随意以任何方式重新组织查询,并且可以在筛选包含字符串的数字之前将其转换为数字。一个临时表虽然需要两个语句(一个用于插入数据,另一个用于连接该数据),但不会有这个问题,因为查询是不同的,并且数据在使用它之前确实如预期的那样“物化”
connectby
表示的,在SQL Server中,这是通过CTE内部的UNION ALL SELECT
完成的,该CTE允许引用CTE自己的别名
小心使用CTE——它们是一个很好的抽象概念,但仅此而已,您可能会遇到严重的麻烦。使用递归CTE一次可以生成一百万行,但这是最糟糕的方式,可能会超过一百倍或更多
SQL Server 2005及更高版本中还有另一种特殊的临时表,称为“表变量”,与临时表非常相似(在tempdb中保持完全相同),但有几个显著的例外:
- 它只持续批处理的持续时间,而不是连接的持续时间
- 可以在用户定义的函数中使用表变量。某些类型的UDF需要一个
- 它只能声明内联约束(如主键或唯一性),虽然可以更新/插入/删除行,但声明后不能以任何方式修改其架构,因此不能添加/删除列、更改数据类型或添加索引
- 它不收集统计数据
- 它可以在SQL Server 2008及更高版本中作为参数(表值参数)传递
不,那是不对的。它们都是独立的功能,每个都有各自的用途 例如,CTE适用于少量数据,而临时表通常更适合于较大的数据集。临时表可以被索引,它们的性能可以得到提高,而CTE不能
我将花一点时间阅读MSDN文档,并查看您将使用其中一个的特定实例。SQL optimizer今天在选择优秀的执行计划方面做得更好,但在连接10多个表时,尤其是在一些大型表和视图以及需要时