SQL Server语句执行顺序

时间:2012-10-03 00:22:26

标签: sql sql-server-2008

我有SQL Server 2008 R2,Windows 7操作系统。

在服务器中,我有一个表con1,它是通过以下SQL语句创建的。

CREATE TABLE [dbo].[con1](
    [digit_str] [nvarchar](50) NULL
) ON [PRIMARY]

con1表中,我有以下值:

 digit_str
----------------
    1
    1
    2
    3
    4
    5
    1.

我确实对数据库执行了以下SQL语句:

SELECT t1.digit FROM
(
select CAST(digit_str as int) as digit from con1 where RIGHT(digit_str,1) <> '.'
) as t1
where t1.digit <> 1

服务器给我以下错误消息:

  

转换nvarchar值'1'时转换失败数据类型为int。

我认为我的内部SQL首先执行并创建了临时表t1,因此表1.中不包含t1,然后SQL解析器将使用where t1.digit <> 1来过滤临时表t1

但上面似乎不对,所以任何人都解释了上述SQL的执行顺序吗?

2 个答案:

答案 0 :(得分:4)

这是SQL Server的一个已知“功能”。不要假设WHERE子句在SELECT子句之前执行。

请参阅:SQL Server should not raise illogical errors

有时这样做有充分的理由。考虑加入两个表,A比B小得多。

select CAST(A.col1 as int), A.col2, B.col3
from A join B ...
where ... isnumeric(A.col1) = 1

如果您正确或错误地检查生成的查询计划,SQL服务器将从A流式传输数据作为要加入B的前导行。这样做时,它知道它只需要拉col2function on col1。它可以使col1只是为了稍后运行该函数,或者对于像CAST一样微不足道的东西,SQL Server也可以在流式传输过程中转换数据。

有一件事是肯定的,这种策略确实使SQL Server在某些查询中更快一点。但从纯粹的逻辑角度来看,我称之为一个错误。

答案 1 :(得分:0)

我无法解释这种行为,但以下内容可以帮助您:

SELECT t1.digit FROM
(
select CAST(digit_str as int) as digit 
  from con1 
 where RIGHT(digit_str,1) <> '.' 
   AND digit_str <> '1'
) as t1

我不确定为什么最后的 where 子句会导致执行转换,因为它看起来应该已经从t1的结果集中过滤掉了。