为什么我的sql日期比较返回0结果

时间:2011-01-05 15:29:30

标签: sql linq-to-sql sql-server-2008

如果这个问题太长,我会事先道歉但是我想确保我已经包含了我所遵循的所有步骤来达到这一点。

我的SQL Server 2008数据库中有以下表格:

CREATE TABLE [VSPRRecalc](
    [VSPRDate] [datetimeoffset](7) NOT NULL,
    [CalcType] [int] NOT NULL,
CONSTRAINT [PK_VSPRRecalc] PRIMARY KEY CLUSTERED ([VSPRDate] ASC)

它的一些行看起来像这样:

INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-15 10:17:49.5780000 -05:00','3')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-16 07:44:03.3750000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-17 07:40:40.1090000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-18 16:29:02.2203744 -05:00','2')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-20 09:58:50.1250000 -05:00','1')
INSERT [vsprrecalc](VSPRDate,CalcType) VALUES('2010-12-29 19:21:26.8120000 -05:00','1')

我正在使用linq检查并查看此表中是否已存在给定日期:

var recalc = (from re in VSPRRecalcs
              where re.VSPRDate.Date == oDate.Value.Date
              select re).SingleOrDefault();

当日期在午夜的5小时之内时,当前recalc返回null(就像上面插入语句中的12-29情况一样)。我检查了以下sql正在执行:

exec sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
                     FROM [dbo].[VSPRRecalc] AS [t0]
                     WHERE 
                     CONVERT(DATE, [t0].[VSPRDate]) = @p0',N'@p0 datetime',@p0='2010-12-29'

返回0条记录。我修改了查询以使测试更容易使用,并提出以下内容:

declare @t as date
set @t =  '2010-12-29'

select *, 
case  when  CONVERT(DATE, [VSPRDate]) = @t then 'true' else 'false' end  
from VSPRRecalc where 
CONVERT(DATE, [VSPRDate]) = @t 

该查询适用于表格中的任何其他日期,但不适用于午夜5小时内的任何日期(再次参见上面的12-29)。如果我在没有where子句的情况下运行上述查询,那么12-29行确实显示了'true',因此布尔值正在评估我在select语句中所期望的方式,而不是where子句中的方式。为什么会这样?

1 个答案:

答案 0 :(得分:1)

我会说这是SQL Server上的一个错误,关于DATETIMEOFFSET时间和更多“标准”类型DATETIMEDATE之间的转换......

我发现以下内容:

有效:

EXEC sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
                     FROM [dbo].[VSPRRecalc] AS [t0]
                     WHERE [t0].[VSPRDate] = @p0',

                     N'@p0 DATETIMEOFFSET(7)',
                     @p0 = '2010-12-29 19:21:26.8120000 -05:00'

这意味着当我们继续使用DATETIMEOFFSET时,没有任何问题......但是,您似乎需要查找给定日期内的所有记录,而不是搜索确切的DATETIMEOFFSET,正确?

所以,可能更有用一点,这个也有效:

EXEC sp_executesql N'SELECT [t0].[VSPRDate], [t0].[CalcType]
                 FROM [dbo].[VSPRRecalc] AS [t0]
                 WHERE [t0].[VSPRDate] BETWEEN @p0 AND @p1',

                 N'@p0 DATETIMEOFFSET, @p1 DATETIMEOFFSET',
                 @p0 = '2010-12-29 00:00:00.0000000 -05:00',
                 @p1 = '2010-12-30 00:00:00.0000000 -05:00'

我想这里的秘诀是继续使用DATETIMEOFFSET数据类型(它的CLR等效,System.DateTimeOffset)。这样你就不会遇到这个转换问题......

(顺便说一下,你应该使用BETWEEN来根据日期搜索记录。这允许DBMS在该列上使用索引,这在你的{{1}时是不可能的。 }子句正在进行函数调用或硬编码转换。)

编辑我忘了没有WHERE运算符可用于Linq for SQL - 但这很容易修复,只需使用类似BETWEEN的内容...另外,{{ 3}}所以问题是关于声明扩展方法以实现它,但我不知道它是否有效......