2011-01-05 121 views
1

如果这个问题太长,我提前表示歉意,但是我想确保我包含了所有我遵循的步骤来达到这一点。为什么我的sql日期比较返回0结果

我下表在我的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(); 

当前recalc返回n只要日期在午夜5小时内(如上面插入语句中的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子句中的值。为什么会发生?

+0

奇怪的是,上面的'executionql'声明**为我工作**(它返回1行)... – rsenna 2011-01-05 15:37:48

+0

...但是,的确,您上一条语句也不适用于我(2010-12-29行的'case'表达式返回'true',但如果我包含where部分,没有行被返回)! – rsenna 2011-01-05 15:44:11

+0

对不起,执行sql语句是从我正在做的一些测试中遗留下来的。我现在编辑它反映应该在那里。如果包含'和VSPRDate ='2010-12-29 19:21:26.8120000-05:00'',则查询确实有效。我不知道有什么不同。 – Mykroft 2011-01-05 15:47:26

回答

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可以使用该列上的索引,当您的WHERE子句正在进行函数调用或硬编码转换时,这是不可能的)。

编辑我忘了有没有BETWEEN运营商可对LINQ的SQL - 但是这很容易解决,只需使用类似WHERE [t0].[VSPRDate] >= @p0 AND [t0].[VSPRDate] <= @p1' ...另外,this SO问题是关于声明一个扩展方法来实现它,但我不知道它是否工作...

+0

我将Linq改为'VSPRDate> = oDate.Date && VSPRDate Mykroft 2011-01-05 22:02:14