【问题标题】:How can you force SQL Server 2008 R2 to accept an ORDER BY on a column that is not part of a table?如何强制 SQL Server 2008 R2 在不属于表的列上接受 ORDER BY?
【发布时间】:2024-05-21 04:10:02
【问题描述】:

在将我们从 SQL Server 2000 继承的大量应用程序迁移到 SQL Server 2008 R2 时,我遇到了现在失败的 ORDER BY 样式。

查询是由一种 SQL 生成层生成的(如果它更好,会尽快修复该层,但它很糟糕)。如果可能的话,我想推迟修复 SQL 生成层,直到我为它构建了一个像样的测试工具。

小例子(无论您使用哪种表:常规或本地/全局临时表):

select
  #IDTABLE.*,
  #NAMETABLE.NAME as NAME -- column alias is mandatory for SQL Server 2000 to succeed
from #IDTABLE
left join #NAMETABLE on #IDTABLE.ID = #NAMETABLE.ID
order by #IDTABLE.NAME

罪魁祸首是#IDTABLE 没有NAME 列。 SQL Server 2000 执行此操作,并采用引用#NAMETABLE.NAMENAME。 SQL Server 2008 R2 失败并显示“列名 'NAME' 无效。”

几个问题:

  • 是否可以强制 SQL Server 2008 R2 接受这种查询并执行 SQL Server 2000 的行为(这样我们就可以修复 SQL 生成层,并对其执行回归)?
  • 由于什么版本的 SQL Server 导致此类查询失败?
  • 为什么 SQL Server 2000 会欣然接受这种查询?

如果您想查看行为,这里有一个完整的示例:

create table #IDTABLE (
    ID Integer
)

create table #NAMETABLE (
    ID Integer,
    NAME VarChar(50)
)

insert into #IDTABLE values (0)
insert into #IDTABLE values (1)
insert into #IDTABLE values (2)

insert into #NAMETABLE values (0, 'FOO')
insert into #NAMETABLE values (1, 'BAR')
insert into #NAMETABLE values (2, 'SNAFU')

select *
from #IDTABLE

select *
from #NAMETABLE

select
  #IDTABLE.*,
  #NAMETABLE.NAME as NAME -- NAME alias is mandatory for SQL Server 2000 to succeed
from #IDTABLE
left join #NAMETABLE on #IDTABLE.ID = #NAMETABLE.ID
order by #IDTABLE.NAME

drop table #IDTABLE
drop table #NAMETABLE

以及OSQL的输出:

(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
 ID
 -----------
           0
           1
           2

(3 rows affected)
 ID          NAME
 ----------- --------------------------------------------------
           0 FOO
           1 BAR
           2 SNAFU

(3 rows affected)
 ID          NAME
 ----------- --------------------------------------------------
           1 BAR
           0 FOO
           2 SNAFU

【问题讨论】:

  • 只是为了让你知道这个选项:mydigitallife.info/…
  • 为什么这么多人突然使用##global 临时表?您是否测试过多个用户同时运行此代码?是龙!
  • 废话,这是一个搜索替换错字。对不起。修好了。
  • 您的##IDTABLE 没有“NAME”列。
  • @granadaCoder 他知道这一点。 SQL Server 2000 在检查列的来源方面有点懒惰,基本上忽略了别名。

标签: sql-server-2008-r2 sql-server-2000 sql-order-by


【解决方案1】:

你可以暂时破解它来“工作”:

ALTER DATABASE [your database] SET COMPATIBILITY_LEVEL = 80;

但是,您最好在升级到 SQL Server 2012 之前修复您的生成层以生成有效的 SQL,因为该兼容级别不再有效,并且在 90 及以上代码中断。没关系,将数据库设置为 80 可能会产生其他不良副作用 - 我在这里讨论它们:

SQL Server 2000 to 2008 Migration - ORDER BY Issue when using DISTINCT

(顺便说一句,如果##IDTABLE 没有NAME 列,为什么它首先会生成##IDTABLE.NAME?)

【讨论】:

  • why on earth 也是我首先想到的。然后我看到了代码... +1,接受了。感谢您的快速回答。
  • 它生成它是因为生成器的构造函数有一个table 和一个order 参数,并且在发出SQL 时它总是像table.order 一样附加它。我需要改变那个雷区,让它正确理解关系。
最近更新 更多