Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 是用临时工作台的替代品吗?_Sql Server_Sql Server 2008_Tsql_Common Table Expression - Fatal编程技术网

Sql server 是用临时工作台的替代品吗?

Sql server 是用临时工作台的替代品吗?,sql-server,sql-server-2008,tsql,common-table-expression,Sql Server,Sql Server 2008,Tsql,Common Table Expression,因此,根据我所看到的使用的方式,以及: 指定临时命名结果集,称为公共表表达式(CTE) 似乎带的是#TEMP表格的替代品。这是正确的吗?否。CTE(由和引入)不会替换临时表,尽管在某些情况下,它们可以用于过去可能使用临时表的地方 WITH实际上只是一个派生表,不同之处在于它是在查询之前引入的,而不是内联的,并且被赋予了一个别名,可以在整个查询中多次用作表 派生表是一个完整的查询,位于圆括号内,使用起来就像是一个实表一样。视图和表值函数也被认为是派生表,但我们关注的是内联定义的类型。以下是一个例子

因此,根据我所看到的使用的方式,以及:

指定临时命名结果集,称为公共表表达式(CTE)

似乎带的
#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)
    计算将涉及第二次执行
    SalesTotals
    聚合的完全独立操作。虽然引擎可以具体化CTE的结果,但到目前为止SQL Server还没有这样做。值得注意的是,其他DBMS(如Oracle)可能会实现CTE的结果。在任何情况下,您都应该意识到这种双重查询可能(当然!)带来严重的性能影响
  • 临时表自动生成列统计信息,这有助于查询优化器选择更好的执行计划。CTE的“final”行集没有统计信息——使用底层表的统计信息
  • 临时表可以通过多条语句或重复语句增量添加或删除。它可以被更新
  • 可以修改临时表以添加或删除列或更改数据类型
  • 临时表可以具有聚集索引和非聚集索引以及约束
  • 在用户定义的函数中,不能以任何方式使用临时表
  • CTE虽然看起来像是在逻辑上分隔查询的各个部分,但并没有这样做。CTE是谓词下推、消除的完美候选,如果确定它们不会影响最终行集(或它们的一些表或联接被消除),或者它们可能会受到意外表达式求值顺序的影响。例如,在CTE中,您可能只返回文本列中的数字字符串,而在外部查询中,尝试将这些字符串转换为数字数据类型,但令人惊讶的是,您在尝试将非数字字符串转换为数字数据类型时出错。这是因为优化器可以随意以任何方式重新组织查询,并且可以在筛选包含字符串的数字之前将其转换为数字。一个临时表虽然需要两个语句(一个用于插入数据,另一个用于连接该数据),但不会有这个问题,因为查询是不同的,并且数据在使用它之前确实如预期的那样“物化”
最后,CTE可以做临时表不能做的事情:它可以是递归的。在Oracle中,这是通过
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多个表时,尤其是在一些大型表和视图以及需要时