Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
sp_executesql返回与直接查询不同的结果_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

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

sp_executesql返回与直接查询不同的结果,sql,sql-server,sql-server-2008,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 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
//查询一个
选择前3个订单日期
从命令
其中OrderDate>=“2013-11-01 04:00”
和OrderDate试试这个

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
DECLARE@p_uuulinq_uu0_ur datetime2(7)='2013-11-01T04:00:00'
声明@p_uuulinq_uu1_ur datetime2(7)='2013-11-30T05:00:00'
声明@sql NVARCHAR(最大值);
设置@sql=N'选择前三名订单日期
从命令
其中OrderDate>=@p\u linq\u 0\u s

而OrderDate我打赌
OrderDate
列的类型是
date
,而不是
datetime
。 所以当你这么做的时候

where OrderDate >= '2013-11-01 04:00'
它将
'2013-11-01 04:00'
转换为
日期
,而不是
日期时间
,因此会丢失时间信息。因此,第一个查询中的条件被解释为
'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
declare@d1 datetime
声明@d2日期时间
设置@d1='2013-11-01 04:00'
设置@d2='2013-11-30 05:00'
选择前3个订单日期
从命令
其中OrderDate>=@d1
OrderDate将表中的数据作为日期开始,并将其作为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';

如果将参数传递为simple
datetime
,会发生什么情况?如果使用第二个查询中的数据类型,第一个查询将返回什么结果?是否可以发布运行查询所针对的部分或全部数据?列类型的表结构也可能有所帮助。(我想知道为什么第一次查询没有返回11/2数据。)@YuriyGalanter如果我将参数作为simple datetime传递,我会得到相同的结果。如果OrderDate是日期,为什么在任何值中都包含时间?这仍然会给出2013-11-02作为第一个结果。datetime列的数据类型是什么?OrderDate列的类型是Date。@AaronBertrand它回答了为什么结果不同的问题-在query1中时间被截断,在query2中不是。它没有回答为什么query2没有截断时间(但我猜这是因为query2正在将日期转换为日期时间,而不是相反)。在修改它之前,原始答案并没有直接解决实际问题,它只是解释了为什么第一个版本的查询有效。另外,当基础数据类型为
DATE
时,为什么建议使用
DATETIME
参数?为什么要在参数值中包含时间?“太令人困惑了。”阿伦伯特朗的问题是“为什么它会这样运作?”。我只是向他解释了为什么第一个查询返回的结果与第二个不同。我不建议他使用
datetime
参数。这只是在
select
中复制第二个查询结果的一种方法,而不是在
sp_executesql
中复制结果。将其切换到正确答案。数据类型优先级是真正的解释。要回答您关于参数为什么有时间值的问题,这是因为查询是由linq To实体生成的。Order模型类将OrderDate作为C#DateTime,EF查询在where子句中使用C#DateTimes。既然这是数据类型,为什么模型类没有日期?EF真的不允许您使用模型公开的类型以外的类型吗?如果这些不匹配,您不能自己编写查询吗?每次我在这里看到一个问题,涉及到EF对你施加的另一个限制,我都想知道从一开始使用它到底节省了多少时间。。。
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