我有SQL Server 2008 R2,Windows 7 OS。
在服务器内,我有一个con1通过以下SQL语句创建的表。
con1
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。
t1
1.
where t1.digit <> 1
但是以上似乎不对,所以有人能解释以上SQL的执行顺序吗?
这是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联接的前导行。在这样做的同时,它知道只需要拉col2和即可 function on col1。它可能col1只是为了稍后运行该函数,或者对于像CAST这样琐碎的事情,SQL Server可能还会在流处理过程中转换数据。
col2
function on col1
col1
可以肯定的是,这种策略确实使SQL Server在某些查询中快了一点。但是从纯粹的逻辑角度来看,我将其称为错误。