3

以下代码:

SELECT JaguarStartupTime, CPU, AmountOfRam, UpdatedOn, *
FROM dbo.MachineConfiguration
WHERE ServerName = 'WashingtonDC01'
AND UpdatedOn > '11/21/2012'
ORDER BY JaguarStartupTime DESC

导致错误:Ambiguous column name 'JaguarStartupTime'

但是,删除ORDER BY使其工作。此外,在ORDER BY子句前面加上表格,如下所示,它也可以工作:

SELECT JaguarStartupTime, CPU, AmountOfRam, UpdatedOn, *
FROM dbo.MachineConfiguration
WHERE ServerName = 'WashingtonDC01'
AND UpdatedOn > '11/21/2012'
ORDER BY dbo.MachineConfiguration.JaguarStartupTime DESC

这对我来说从来没有意义。有人可以解释吗?

4

2 回答 2

8

因为查询*在 SELECT 子句中包括(所有列),该子句还包括 JaguarStartupTime 列。

用 Layman 的话来说:所以在检索结果时,该列显示了两次,然后当服务器尝试应用排序顺序时,不确定您指的是哪一列。

就个人而言,我会更改查询以消除查询中的使用*,即使这意味着列出一长串列名。这是最佳实践,它将避免此问题。


至于为什么加前缀可以工作,我在MSDN 文档中找到了这个:

在 SQL Server 中,限定列名和别名被解析为 FROM 子句中列出的列。如果 order_by_expression 不合格,则该值在 SELECT 语句中列出的所有列中必须是唯一的。

这只是数据库引擎将 SQL 语句转换为执行计划的底层机制的一部分。

于 2012-11-26T19:29:31.773 回答
1

我同意,在您的问题ORDER BY JaguarStartupTime中,这并不是真正的模棱两可,因为两个投影列实际上都指的是同一个基础列。

但是,在一般情况下,不能保证这是真的。如对此连接项的响应中所述。例如,在下面的查询中,使用哪一个显然是模棱两可的。

SELECT JaguarStartupTime,
       CPU AS JaguarStartupTime
FROM   dbo.MachineConfiguration
ORDER  BY JaguarStartupTime DESC 

出于语法验证的目的,SQL Server 不会对列名进行任何分析以确定它们是否真的模棱两可。当按some_name投影列名列表中存在的排序时,它some_name必须是唯一的。这是按照ANSI 规范

如果 a<sort specification>包含 a <column name>T 则应仅包含一个带有该列的列,<column name>并且<sort specification>标识该列。

使用表名限定列名可确保 SQL Server 按源列名而不是计划列名进行排序,因此它允许这样做。

SELECT name, name 
FROM master..spt_values v1
ORDER BY v1.name

此外,允许以下查询。

select name, name 
FROM master..spt_values v1
ORDER BY name + ''

之所以没有歧义,是因为ORDER BY子句中的列别名只能由它们自己使用,而不能在表达式中使用,所以在上面的查询name中不能解释为别名,必须解释为 ordering by v1.name

于 2012-11-26T22:12:52.210 回答