我的mssql数据库中有一个表,其中一列为smalldatetime数据类型。
smalldatetime数据类型不具有秒精度。按照其documentation:
ss是两位数字,范围从00到59,代表第二位。小于等于29.998秒的值将四舍五入到最接近的分钟,大于等于29.999秒的值将四舍五入到最接近的分钟。“
我有一个表em_test,其中包含列description(varchar)和startTime(smalldatetime)。
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');
如果我运行查询: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
使用prepared语句的同一查询将返回不同结果。
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 prepare语句返回的结果不同。 下面是分析:
'2018-08-02 00:00:00' and '2018-08-02 11:59:59'
不会四舍五入,并且不会返回最后两个结果。create procedure smalldatetimetest @startDate datetime2, @endDate datetime2 AS print 'Start Date in Datetime2 format : ' + Convert(varchar(50), @startDate); print 'End Date in Datetime2 format: ' + Convert(varchar(50), @endDate); print 'Start Date in smalldatetime format: ' + Convert(varchar(50), cast(@startDate as smalldatetime)); print 'End Date in smalldatetime format: ' + Convert(varchar(50), cast(@endDate as smalldatetime)); select * from em_test where datetime1 between @startDate and @endDate; GO
执行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
我的理解正确吗?如果准备了陈述,是否有任何解决方法来解决差异?
答案 0 :(得分:0)
以下变通办法似乎对我有用:
代替提供java.sql.Timestamp
参数值
ps.setTimestamp(1, ts);
以字符串形式提供
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
ps.setString(1, sdf.format(ts));
这导致JDBC生成的查询使用nvarchar(4000)
参数而不是datetime2
参数
exec sp_executesql N'SELECT COUNT(*) AS n FROM #tmp WHERE foo<=@P0 ',N'@P0 nvarchar(4000)',N'2018-08-11 02:59:59.001'
并且结果似乎与具有字符串文字日期/时间值的纯文本查询的结果相匹配,就像您所提问的一样。