这是我的第一个问题,请原谅任何可能发生的错误:)
我制作了一个C#程序,它使用Datatables从SQL Server数据库收集数据,然后使用Interop将结果导出到Excel电子表格。
该计划本身运行良好,并按计划进行;但是,当我尝试选择Date
列小于或等于2014-05-31 23:59:59
的数据时,我发现了一些错误。
据说我试图将所有数据提供到2014年5月1日。
我的代码首先启动"开始日期"后面使用的SQL命令的参数如下:
var firstDay = new DateTime(today.Year, today.Month, 1); //2014-05-01 00:00:00`
基于firstDay
,它会启动参数
var periodTo = firstDay.AddSeconds(-1);`
我调试并得到了我想要的时间:2014-04-30 23:59:59
为数据条件添加更多参数后,它会执行使用提供的参数运行查询的方法。
queryResult = medicore.GenerateRegister(ConfigurationManager.AppSettings["queryDir"], ConfigurationManager.AppSettings["queryName"]);`
periodTo
参数将映射到SQL脚本中的@EDate
变量。 @EDate
被声明为Datetime
。 @Edate
在这里发挥作用:
Select columns
From tables
Where Voucher.Date <= @EDate
我认为,该脚本看起来像Where Voucher.Date <= '2014-04-30 23:59:59'
问题是,生成的Excel文件中的结果还包含来自'2014-05-01'
的数据,这些数据不应该存在...至少基于我设置的标准。
C#和SQL Server之间是否发生了某种舍入?
谢谢!
答案 0 :(得分:3)
原因可能是Voucher.Date
是SMALLDATETIME
,因此您隐式将'2014-04-30 23:59:59'
转换为SMALLDATETIME
:
SET DATEFORMAT MDY;
SELECT CONVERT(SMALLDATETIME, '2014-04-30 23:59:59')
这给出了&#39; 2014-05-01&#39;。
为什么不使用Less than运算符,而不是小于或等于?
SET DATEFORMAT MDY;
SELECT ...
WHERE Voucher.Date < '2014-05-01';
NB我已经发表了DATEFORMAT
,因为yyyy-MM-dd
(尽管是ISO标准)对于SQL Server中的DATETIME
和SMALLDATETIME
数据类型不是文化不变的,如果(像我一样)您所在的国家/地区的默认日期格式为DMY
,那么SELECT CONVERT(SMALLDATETIME, '2014-04-30')
会给您转换错误。 yyyyMMdd
是这两种类型的唯一文化不变日期格式。
一篇优秀且非常相关的文章是Aaron Bertrand的Bad habits to kick : mis-handling date / range queries