2011-01-05 17 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) 

それは次のようになり、その中にいくつかの行があります:私はチェックして確認するためにLINQを使用してい

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') 

recalc戻っnは現在

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

:指定された日付は既にこのテーブルに存在する場合日付が真夜中から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

奇妙な、上記の 'executeql'ステートメント**私のために働く** 1行)... – rsenna

+0

...実際には、上記のあなたの最後のステートメントも私のために働いていません( 'case'式は2010-12-29行の' true'を返しますが、where部分、行は返されません)! – rsenna

+0

申し訳ありませんがSQL文を実行すると、私がやっていたいくつかのテストから残されました。私は今そこにあったはずのものを反映するように編集しました。 'とVSPRDate = '2010-12-29 19:21:26.8120000 -05:00''を含めると、クエリは機能します。私は違いが何であるか分からない。 – Mykroft

答えて

1

私はそれがDATETIMEOFFSET時間、より「標準」タイプDATETIMEDATEの間の変換については、SQL Server上のバグだと言うだろう...

私は、次のさを見つける持っているもの:

我々はDATETIMEOFFSETを使用し続ける場合は、全く問題がないことを意味

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を検索するのではなく、特定の日にすべてのレコードを検索する必要があるようです。

ので、おそらくもう少し便利な、この作品も:

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句が関数呼び出しまたはハードコード変換を行っているときは不可能です)。

編集私はSQLのためのLINQのために利用可能なBETWEENオペレータはありません忘れてしまった - ちょうどWHERE [t0].[VSPRDate] >= @p0 AND [t0].[VSPRDate] <= @p1'ようなものを使用するが、それは修正するのは簡単です...また、thisだから、それを実装するために拡張メソッドを宣言することですが、それが動作するかどうかわかりません...

+0

私はLinqを 'VSPRDate> = oDate.Date && VSPRDate Mykroft

関連する問題