令人费解的SQL服务器行为 – 如果WHERE子句中有1 <> 2表达式,则会产生不同的格式

我有两个几乎相同的SELECT语句.我在SQL Server 2012上使用服务器排序规则Danish_Norwegian_CI_AS和数据库排序规则Danish_Norwegian_CI_AS运行它们.数据库以设置为SQL Server 2005(90)的兼容级别运行.

我通过SQL Server 2012 Management Studio在同一客户端上运行这两个查询.客户端是Windows 8.1笔记本电脑.

令人费解的是,尽管语句几乎相同,但结果集不同,如下所示(一个返回24小时格式时间,另一个返回AM / PM,在这种情况下会截断tpo P).唯一的区别是WHERE子句中的’和1<> 2’表达式.我上下打量,在谷歌搜索,尽可能深地挖掘,找不到解释.尝试COLLATE强制转换,没有帮助.如果我使用108强制CONVERT调用格式化,那么结果集是相似的.但不知道为什么这不起作用的原因是让我活着.

在SqlFiddle,SQL Server 2008上重新创建的问题:

http://sqlfiddle.com/#!3/a97f8/1

有人为此解释一下吗?

结果之后的SQL DDL和语句可用于重新创建问题.该脚本创建一个包含两列的表,插入一些行,并进行两次选择.

在我的机器上,没有1<> 2表达式的sql返回:

Id          StartTime
----------- ---------
2           2:00P
2           2:14P

具有1<> 2表达式的sql返回:

Id          StartTime
----------- ---------
2           14:00
2           14:14



if NOT EXISTS (Select * from sysobjects where name = 'timeVarchar')
begin
    create table timeVarchar (
        Id int not null,
        timeTest datetime not null
    )
end

if not exists (select * from timeVarchar) 
begin
    -- delete from timeVarchar
    print 'inserting'
    insert into timeVarchar (Id, timeTest) values (1, '2014-04-09 11:37:00')
    insert into timeVarchar (Id, timeTest) values (2, '1901-01-01 14:00:00')
    insert into timeVarchar (Id, timeTest) values (3, '2014-04-05 15:00:00')
    insert into timeVarchar (Id, timeTest) values (2, '1901-01-01 14:14:14')
end

select
        Id,
        convert ( varchar(5), convert ( time, timeTest)) as 'StartTime'
from
     timeVarchar
where
     Id = 2



select
     Id, 
        convert ( varchar(5), convert ( time, timeTest)) as 'StartTime'
from
     timeVarchar
where
     Id = 2 and
     1                       <>    2

最佳答案 我无法回答为什么会发生这种情况(至少目前还没有),但明确设置转换格式确实解决了这个问题:

select Id,
       convert (varchar(5), convert (time, timeTest), 14) as "StartTime"
from timeVarchar
where Id = 2;

select Id, 
       convert (varchar(5), convert (time, timeTest), 14) as "StartTime"
from timeVarchar
where Id = 2 
and  1 <> 2; 

通过执行计划,这两个查询的结果确实非常不同.

第一个传递2作为参数,(!)传递值为CONVERT_IMPLICIT.第二个将它作为查询本身的一部分传递给它!

最后,在第一种情况下运行的实际查询实际上显式地执行CONVERT(x,y,0).对于美国语言环境,这不是问题,因为0是不变(~US)文化.但是在美国之外,你突然使用0而不是4(德国).

所以,当然,有一点需要考虑的是,看起来非常相似的查询可以完全不同地执行.

第二件事是 – 始终使用特定格式的转换.默认值似乎并不完全可靠.

编辑:啊,最后从MSDN中捕获的东西:

http://msdn.microsoft.com/en-us/library/ms187928.aspx

In earlier versions of SQL Server, the default style for CAST and
CONVERT operations on time and datetime2 data types is 121 except when
either type is used in a computed column expression. For computed
columns, the default style is 0. This behavior impacts computed
columns when they are created, used in queries involving
auto-parameterization, or used in constraint definitions.

由于第一个查询是作为参数化查询调用的,因此它获取默认样式0而不是121.此行为在兼容级别110(即SQL SERVER 2012)中得到修复 – 在这些服务器上,默认值始终为121.


点赞