1

我有 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的执行顺序吗?

4

2 回答 2

4

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

请参阅:SQL Server 不应引发不合逻辑的错误

实际上,有时这样做是有充分理由的。考虑连接两个表,其中 A 比 B 小得多。

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

如果您检查生成的查询计划,无论对错,SQL Server 都会将来自 A 的数据作为前导行流式传输以与 B 连接。这样做时,它知道它只需要拉取col2function on col1. 它可能col1只是为了稍后运行该函数,或者对于像 CAST 这样微不足道的事情,SQL Server 还不如在流式处理过程中转换数据。

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

于 2012-10-03T00:47:35.670 回答
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 的结果集中过滤掉了。

于 2012-10-03T00:40:56.550 回答