sp_executesql返回与直接查询不同的结果

MCS*_*MCS 4 sql sql-server sql-server-2008

以下两个查询返回不同的结果.我理解差异与处理日期的时间部分的方式有关,但为什么它以这种方式工作?

// 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
Run Code Online (Sandbox Code Playgroud)

UPDATE

如果我将传递给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
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 6

数据类型优先级是将表中的数据作为日期开始,并将其作为datetime2(7)进行比较.所以你的动态SQL版本实际上是这样运行的:

WHERE column_as_datetime2 >= @parameter_as_datetime2
Run Code Online (Sandbox Code Playgroud)

那么,既然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';
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)