以下两个查询返回不同的结果。我知道差异与处理日期的时间部分的方式有关,但为什么这样做呢?
// QUERY ONE
select top 3 OrderDate
from Orders
where OrderDate >= '2013-11-01 04:00'
and OrderDate <= '2013-11-30 05:00'
order by OrderDate
// RESULTS
// 2013-11-01
// 2013-11-01
// 2013-11-01
// QUERY TWO
exec sp_executesql
N'select top 3 OrderDate
from Orders
where OrderDate >= @p__linq__0
and OrderDate <= @p__linq__1
order by OrderDate',
N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7)',
@p__linq__0='2013-11-01T04:00:00',
@p__linq__1='2013-11-30T05:00:00'
// RESULTS
// 2013-11-02
// 2013-11-02
// 2013-11-02
更新
如果我将传递给sp_executesql的参数类型更改为“date”而不是“datetime”,则结果是相同的。
// QUERY THREE
exec sp_executesql
N'select top 3 OrderDate
from Orders
where OrderDate >= @p__linq__0
and OrderDate <= @p__linq__1
order by OrderDate',
N'@p__linq__0 date,@p__linq__1 date',
@p__linq__0='2013-11-01T04:00:00',
@p__linq__1='2013-11-30T05:00:00'
// RESULTS
// 2013-11-01
// 2013-11-01
// 2013-11-01
答案 0 :(得分:6)
Data type precedence正在获取表格中的数据,该数据以日期开头,并将其作为datetime2(7)进行比较。所以你的动态SQL版实际上正在运行它:
WHERE column_as_datetime2 >= @parameter_as_datetime2
因此,由于2013-11-01 00:00:00.0000000
不大于或等于2013-11-01 04:00:00.0000000
,所以11月1日的行将被排除。
最实用的解决方案是使用DATE
参数(首选,因为参数应该与基础数据类型匹配,毕竟),和/或停止传递时间值以及它们。试试这些:
USE tempdb;
GO
CREATE TABLE dbo.Orders(OrderDate DATE);
INSERT dbo.Orders VALUES('2013-11-01'),('2013-11-01'),('2013-11-01'),
('2013-11-02'),('2013-11-02'),('2013-11-02');
exec sp_executesql N'select top 3 OrderDate
from Orders
where OrderDate >= @p__linq__0
and OrderDate <= @p__linq__1
order by OrderDate;
select top 3 OrderDate
from Orders
where OrderDate >= @p2
and OrderDate <= @p3
order by OrderDate;
select top 3 OrderDate
from Orders
where OrderDate >= @p4
and OrderDate <= @p5
order by OrderDate;',
N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7),
@p2 datetime2(7),@p3 datetime2(7),@p4 date,@p5 date',
@p__linq__0='2013-11-01T04:00:00',
@p__linq__1='2013-11-30T05:00:00',
@p2='2013-11-01T00:00:00', -- note no time
@p3='2013-11-30T00:00:00', -- note no time
@p4='2013-11-01',
@p5='2013-11-30';
结果:
OrderDate
----------
2013-11-02
2013-11-02
2013-11-02
OrderDate
----------
2013-11-01
2013-11-01
2013-11-01
OrderDate
----------
2013-11-01
2013-11-01
2013-11-01
答案 1 :(得分:4)
我敢打赌,OrderDate
列的类型为date
,而不是datetime
。
所以当你这样做时
where OrderDate >= '2013-11-01 04:00'
它将'2013-11-01 04:00'
转换为date
,而不是datetime
,因此会丢失时间信息。因此,第一个查询中的条件被解释为'2013-11-01 00:00:00' >= '2013-11-01 00:00:00'
。这是真的。
在第二个查询中,SP接收类型为datetime
的参数,该参数具有时间信息。那里的条件被解释为'2013-11-01 00:00:00' >= '2013-11-01 04:00:00'
,这是错误的。
如果您想在第一个查询中使用相同的行为,请使用datetime
变量而不是字符串。
declare @d1 datetime
declare @d2 datetime
set @d1 = '2013-11-01 04:00'
set @d2 = '2013-11-30 05:00'
select top 3 OrderDate
from Orders
where OrderDate >= @d1
and OrderDate <= @d2
order by OrderDate
答案 2 :(得分:0)
试试这个......
DECLARE @p__linq__0_R datetime2(7) = '2013-11-01T04:00:00'
DECLARE @p__linq__1_R datetime2(7) = '2013-11-30T05:00:00'
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'select top 3 OrderDate
from Orders
where OrderDate >= @p__linq__0_s
and OrderDate <= @p__linq__1_s
order by OrderDate'
exec sp_executesql @sql,
N'@p__linq__0_s datetime2(7),@p__linq__1_s datetime2(7)',
@p__linq__0_s =@p__linq__0_R,
@p__linq__1_s=@p__linq__1_R
修改强>
如果您的列只是Datetime而不是Datetime2,那么sql server正在使用Datetime数据类型对您的列进行隐式转换,因为Datetime2是一个比datetime更高的优先级数据类型。比较两个值Sql server expectes值是否为相同的数据类型。也许这就是造成问题的原因。一种解决方法是,您可以在比较值时将datetime列转换为datetime2。