使用ADO和SQL Server时未正确评估日期参数

时间:2011-09-09 20:53:55

标签: sql-server delphi ado

我有以下SQL语句:

SELECT 420, DueDate, ISNULL(Amount, 0) 
FROM Payments
WHERE CurveID = ? AND DueDate >= ?;

我正在使用Delphi 2010和TADODataset执行。语句正确执行,但条款DueDate >= ?的评估不正确。如果我传入Date()Now()作为第二个参数,我会在DueDate字段中返回日期早于今天的值。

在SSMS中,如果我将日期参数替换为格式为“2011-09-09”的字符串,我可以成功运行此SQL查询:

SELECT 420, DueDate, ISNULL(Amount, 0) 
FROM Payments
WHERE CurveID = 19 AND DueDate >= '2011-09-09';

然而,回到Delphi,即使我将参数值设置为此格式的日期的字符串化版本,我得到的结果也不正确(可能是因为TADODataset正确地将字符串转换回日期)。

我必须做什么,除了使用硬编码到SQL中的日期构建动态SQL以正确评估它?

6 个答案:

答案 0 :(得分:2)

使用(命名)参数,例如

Query.CommandText := 'SELECT 420, DueDate, ISNULL(Amount, 0) FROM Payments '+
                     'WHERE CurveID = :CurveID AND DueDate >= :DueDate';
Query.Prepared := True;
Query.Parameters.ParamValues['CurveID'] := 19;
Query.Parameters.ParamValues['DueDate'] := EncodeDate(2011, 9, 9);
Query.Active := True;

这也允许您在系统不正确的情况下设置参数的类型,即

Query.Parameters.ParamByName('DueDate').DataType := ftDate;

另请注意,ADODataSet的ParamCheck属性必须为true(默认)才能使用:name样式参数。

答案 1 :(得分:0)

请试试这个:

AND DueDate >= CONVERT(datetime,?);

答案 2 :(得分:0)

Delphi客户端和SQL Server之间的区域设置是否不同?这可能导致返回无效日期。虽然我承认,如果在“9/9/2011”中月份=年份,那应该不重要。

我们使用法国加拿大C#客户端与美英数据库服务器通信时遇到了类似问题。客户端将2011年4月1日格式化为“1/4/2011”,数据库将其解释为2011年1月4日。

答案 3 :(得分:0)

零日期在OS和DB中不同,01/01/1900 v / s 30/12/1899。您需要+/- 2天,具体取决于选择/更新。

答案 4 :(得分:0)

以下是我的问题的解决方案:

我正在使用TADOCommand对数据库执行SQL(而不是TADODataset,因为我错误地在问题中写道,oops)。切换到TADOQuery解决了这个问题。这两个类之间的执行SQL接口是不同的,TADOQuery明确地查看数据集的Parameters属性以获取它的参数。 TADOCommand有一个Parameters属性,但也接受一个Parameter数组作为.Execute()方法的参数。

使用TQuery,我的参数输入正确,而不需要额外的努力。这适用于位置或命名参数。

答案 5 :(得分:0)

我注意到的是使用Delphi TDateTime值分配ParamByName和ParamValues之间的行为差​​异

var
  MyDate: TDateTime

AdoQuery1.ParamByName('DueDate').AsDateTime := MyDate // works with US English
//vs 
AdoQuery1.ParamValues['DueDate'] := MyDate // works with various date formats

当您的ShortDate设置为英语US时没有区别,但如果不是,则ParamByName不会对所有设置进行正确的转换。

ParamValues正确进行转换。我猜测变体的转换代码比Delphi TDateTime值和ADO DateTime值之间的转换“更好” - 这就是为什么我在我的应用程序中不再使用ParamByName。