2011-01-05 107 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