2015-07-06 48 views
2

我打电话给一个存储过程,并在我的Windows应用程序中传入2个日期作为参数。它返回所有行,而不是我期待的2行。sp_executesql vs手动执行给出不同的结果

存储过程是:

ALTER procedure [dbo].[Get_Entries] 
    @Start_Date datetime=null, 
    @End_Date datetime=null 
as 
begin 
    SELECT * 
    FROM MyTable 
    WHERE (MyTable.Date BETWEEN @Start_Date AND @End_Date 
     OR (@Start_Date IS NULL AND @End_Date IS NULL)) 
    ORDER BY MyTable.Date desc 
end 

以下sp_executesql查询返回的所有行:如果我从Management Studio中手动运行存储过程

exec sp_executesql N'Get_Entries', N'@Start_Date datetime, @End_Date datetime', 
        @Start_Date='2015-06-06 11:35:06.437', 
        @End_Date='2015-07-06 11:35:06.437' 

但是我得到预期的2行:

USE [MyDatabase] 
GO 

DECLARE @return_value int 

EXEC @return_value = [dbo].[Get_Entries] 
     @Start_Date = N'2015-06-06 11:35:06.437', 
     @End_Date = N'2015-07-06 11:35:06.437' 

SELECT 'Return Value' = @return_value 
GO 

任何想法为什么sp_executesql isn' t返回过滤的列表?它返回所有行。

+0

考虑使用动态SQL执行此任务,以避免次优的计划和参数嗅探。请参阅http://www.sommarskog.se/dyn-search.html。 –

回答

3

解决这个问题的方法是使用(稍作改动)ISO-8601日期由SQL Server支持的格式 - 这种格式的作品总是 - 不管你的SQL Server的语言和日期格式设置。

ISO-8601 format由SQL Server支持有两种形式:

  • YYYYMMDD只是日期(没有时间部分);请注意:没有破折号!,这非常重要! YYYY-MM-DD不是独立于您的SQL Server中的dateformat设置,并将在所有情况下工作!

或:

  • YYYY-MM-DDTHH:MM:SS的日期和时间 - 这里需要注意:这种格式破折号(但他们可以可省略),并固定T的日期和时间之间的分隔符你的部分DATETIME

这对SQL Server 2000及更新版本有效。

如果你使用SQL Server 2008或更高版本和DATE数据类型(仅DATE - !DATETIME),那么你的确可以同时使用YYYY-MM-DD格式,将工作,也与任何设置在你的SQL Server 。

不要问我为什么这整个话题如此棘手,有点令人困惑 - 这就是它的方式。但使用YYYYMMDD格式,对于任何版本的SQL Server以及SQL Server中的任何语言和dateformat设置,都应该可以。

我对SQL Server 2008及更新版本的建议是,如果您只需要日期部分,则使用DATE;如果需要日期和时间,则使用DATETIME2(n)。你应该尝试启动即使有淘汰DATETIME数据类型可能

1

在你的情况值不传递给存储过程,并使用默认值运行。

如果去掉你会得到以下错误在存储过程中的默认值: 过程或函数“Get_Entries”需要参数“@start_date”,但未提供。

sp_executesql用于使代码可重用。使用sp_executesql执行存储过程提供任何好处。

sp_executesql executes a Transact-SQL statement or batch that can be reused many times, or that has been built dynamically.

你可以找到周围使用下面

Declare @statement nvarchar(max) 
set @statement = N'Get_Entries ''2010-06-06 11:35:06.437'', ''2015-07-06 11:35:06.437''' 
exec sp_executesql @statement 
0

定的代码让我们来看看你的sp_executesql陈述道:

exec sp_executesql N'Get_Entries', 
    N'@Start_Date datetime, @End_Date datetime', 
    @Start_Date='2015-06-06 11:35:06.437', 
    @End_Date='2015-07-06 11:35:06.437' 

这个查询告诉SQL Server执行下面的查询:

'Get_Entries' 

要调用sp_executesql的方式说,查询使用下列参数:

'@Start_Date datetime,@End_Date datetime' 

但是,查询字符串“Get_Entries”不使用这些参数。因此,SQL Server不会将参数放入查询中。结果查询等效于下面的代码:

exec Get_Entries 

不指定任何参数,存储过程将返回所有行。

要使用的参数,你需要将它们在动态SQL查询像下面。我改名为动态SQL参数以使其更清晰,他们在查询中使用:

exec sp_executesql N'Get_Entries @Start_Date = @StartDateParm, @End_Date = @EndDateParm', 
    N'@StartDateParm datetime, @EndDateParm datetime', 
    @StartDateParm='2015-06-06 11:35:06.437', 
    @EndDateParm='2015-07-06 11:35:06.437' 

注意,你不需要把一个存储过程调用在调用sp_executesql。直接调用该过程会更高效。