为什么 ORDER BY 不属于视图?

ngm*_*eli 53 sql-server order-by

知道 不能有 ORDER BY一个视图。(至少在我使用的 SQL Server 2012 中)

我也明白对视图进行排序的“正确”方法是ORDER BYSELECT查询视图的语句周围放置一个。

但是对于实际的 SQL 和视图的用法相对较新,我想了解为什么这是设计使然。如果我正确地遵循了历史记录,这曾经是可能的,并且已从 SQL Server 2008 等中明确删除(不要引用我的确切版本)。

但是,我能想到的关于 Microsoft 删除此功能的最佳理由是因为“视图是未排序的数据集合”。

我假设有一个很好的、合乎逻辑的理由来解释为什么 View 应该未排序。为什么视图不能只是扁平化的数据集合?为什么特别排序?想出这样的情况似乎并不难(至少对我/恕我直言)拥有排序视图似乎非常直观。

Aar*_*and 39

(当然,除了索引视图。)

视图未具体化 - 数据未存储,那么如何对其进行排序?视图有点像一个存储过程,SELECT它只包含一个没有参数的...它不保存数据,它只保存查询的定义。由于对视图的不同引用可能需要以不同方式排序的数据,因此您执行此操作的方式 - 就像从表中选择一样,根据定义,该表也是未排序的行集合 - 是在外部查询中包含 order by .

也可以稍微了解一下历史。你可能从来没有ORDER BY在视图中,也没有包括TOP。在这种情况下,ORDER BY决定了包含哪些行TOP,而不是如何呈现它们。碰巧的是,在 SQL Server 2000 中,如果TOP100 PERCENT{some number >= number of rows in the table},优化器相当简单,它最终会生成一个与TOP/ORDER BY. 但这种行为从未得到保证或记录 -它只是基于观察,这是一个坏习惯。当 SQL Server 2005 出现时,这种行为开始“中断”,因为优化器的变化导致使用不同的计划和运算符 - 其中包括TOP / ORDER BY如果是,将被完全忽略TOP 100 PERCENT。一些客户对此的抱怨如此之大,以至于微软发布了一个跟踪标志来恢复旧的行为。我不会告诉你标志是什么,因为我不想让你使用它,我想确保意图是正确的 - 如果你想要一个可预测的排序顺序,请ORDER BY在外部查询中使用。

总结并尽可能澄清您提出的一点: Microsoft 没有删除任何内容。他们使产品变得更好,作为副作用,这种无证、无保证的行为变得不那么可靠。总的来说,我认为产品更适合它。

  • @TimSchmelter 那里 *order* 不是在谈论行的顺序,而是在谈论一行中的列的顺序。在 SQL Server 中,我们通常不说行是元组,因为行的物理实现对我们来说非常明显(表按照您定义的顺序列出列)。 (2认同)

Mar*_*ith 9

如果允许对视图进行排序,那么这里的结果顺序应该是什么?

CREATE VIEW dbo.V1
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number ASC

GO

CREATE VIEW dbo.V2
AS
  SELECT number
  FROM   SomeTable
  ORDER  BY number DESC

GO

SELECT *
FROM   dbo.V1
       JOIN dbo.V2
         ON V1.number = V2.number 
Run Code Online (Sandbox Code Playgroud)


小智 8

一种可能性是避免排序冲突 - 如果视图按一个顺序排序并且该视图上的选择按另一个顺序排序(不知道视图排序),则可能会影响性能。所以把排序要求留给用户比较安全。

另一个原因,排序会带来性能成本,所以为什么要惩罚视图的所有用户,当只有一些用户需要排序时..


Tom*_*m V 5

ANSI SQL 只允许ORDER BY最外层查询出于多种原因,其中一个原因是当子选择/视图/CTE 连接到另一个表并且外层查询有一个ORDER BY自身时会发生什么。

SQL Server 从未在视图中支持它(除非你使用 aTOP 100 PERCENT来欺骗它,在我看来这主要是触发了一个错误)。

即使您触发了错误,结果也从来都不可靠,而且排序并不总是如您所愿。

请参阅查询优化器团队的这篇博文以获得完整的技术解释TOP 100 Percent ORDER BY Considered Harmful。

此代码的默认计划实现恰好在执行 TOP 操作的过程中对行进行排序。通常,这意味着结果碰巧按排序顺序返回,这使客户相信行已排序是有保证的。实际上并非如此。如果您希望按排序顺序将行返回给用户,则需要在最外面的查询块(根据 ANSI)上使用 ORDER BY 以保证输出的显示顺序。