我的 mssql 数据库中有一个表,其中一列是 smalldatetime 数据类型。
smalldatetime 数据类型没有秒精度。根据其文档:
ss 是两位数,范围从 00 到 59,表示秒。小于等于 29.998 秒的值向下舍入到最接近的分钟,大于等于 29.999 秒的值向上舍入到最接近的分钟。”
我有一个包含列 description(varchar) 和 startTime(smalldatetime) 的表 em_test。
I inserted following entries in table :
insert into em_test values('e1-2018-08-01 23:59:59', '2018-08-01 23:59:59');
insert into em_test values('e2-2018-08-02 00:00:00', '2018-08-02 00:00:00');
insert into em_test values('e3-2018-08-02 01:00:00', '2018-08-02 01:00:00');
insert into em_test values('e4-2018-08-02 23:59:59', '2018-08-02 23:59:59');
insert into em_test values('e5-2018-08-03 00:00:00', '2018-08-03 00:00:00');
如果我运行 query : select * from em_test where startTime between '2018-08-02 00:00:00' and '2018-08-02 11:59:59'
,将获得以下结果:
name startTime
e1-2018-08-01 23:59:59 2018-08-02 00:00:00 (Rounded up)
e2-2018-08-02 00:00:00 2018-08-02 00:00:00
e3-2018-08-02 01:00:00 2018-08-02 01:00:00
e4-2018-08-02 23:59:59 2018-08-03 00:00:00 (Rounded up)
e5-2018-08-03 00:00:00 2018-08-03 00:00:00
使用准备好的语句的相同查询返回不同的结果。
name startTime
e1-2018-08-01 23:59:59 2018-08-02 00:00:00 (Rounded up)
e2-2018-08-02 00:00:00 2018-08-02 00:00:00
e3-2018-08-02 01:00:00 2018-08-02 01:00:00
我调试了 mssql-jdbc-6.4.0-jre7.jar 源代码,以了解为什么普通 sql 查询和 sql 准备语句返回的结果不同。下面是分析:
- 每当必须执行准备好的语句时,都会在内部创建一个运行时存储过程来包装查询。查询输入参数变为存储过程输入参数。
- 在形成准备好的语句时,我们将 smalldatetime 值设置为时间戳为 ps.setTimeStamp('2018-08-01 23:59:59')。
- 在形成运行时存储过程时,确定输入参数数据类型。TimeStamp映射到 mssql datetime2。
- 因此,在 datetime2 的情况下,args
'2018-08-02 00:00:00' and '2018-08-02 11:59:59'
不会四舍五入,并且不会返回最后两个结果。 - 尝试用很少的日志模拟运行时过程:
创建过程 smalldatetimetest @startDate datetime2, @endDate datetime2 作为 print 'Datetime2 格式的开始日期:' + Convert(varchar(50), @startDate); print 'Datetime2 格式的结束日期:' + Convert(varchar(50), @endDate); print 'smalldatetime 格式的开始日期:' + Convert(varchar(50), cast(@startDate as smalldatetime)); print 'smalldatetime 格式的结束日期:' + Convert(varchar(50), cast(@endDate as smalldatetime)); select * from em_test where datetime1 在@startDate 和@endDate 之间; 去
执行exec smalldatetimetest '2018-08-02 00:00:00','2018-08-02 23:59:59'
打印以下日志:
Start Date in Datetime2 format : 2018-08-02 00:00:00.0000000
End Date in Datetime2 format: 2018-08-02 23:59:59.0000000
Start Date in smalldatetime format: Aug 2 2018 12:00AM
End Date in smalldatetime format: Aug 3 2018 12:00AM
我的理解是否正确,是否有任何解决方法来解决准备好的声明中的差异?