获取日期时间差异的异常
Posted
技术标签:
【中文标题】获取日期时间差异的异常【英文标题】:Getting an exception with datetime diff 【发布时间】:2016-08-26 14:18:52 【问题描述】:我的网页上有 2 个按钮。当我点击第一个按钮时,系统时间在我的 sql 表的starttime
中更新,当我停止时,必须更新结束时间,并且两者之间的差异应该在另一个表中更新。我使用了以下查询。
更新结束时间和更新总时间。
update breakstable set endtime = ?, TotalBreakTime = (? - StartTime) where userid = ?
and endtime is NULL
这里的前 2 个?
s 指的是发生的一次按钮点击,另一个?
指的是从会话中捕获的已登录用户 ID。
用totalbreaktime
的总和更新另一个表。
MERGE Time_Tracker as target using (SELECT USERID, CONVERT(NUMERIC(10,2),
SUM(DATEDIFF(Second, '19000101', TotalBreakTime))/60.0) as ColumnWithBreaksCount FROM
BreaksTable where CONVERT(Date, StartTime) = CONVERT(Date, GETDATE()) GROUP BY USERID)
as source ON target.USERID = source.USERID WHEN MATCHED THEN UPDATE
SET BREAKS = source.ColumnWithBreaksCount;"
问题:
我开始我的时间,休息一个半小时后返回,然后按下停止按钮。它没有更新表格,而是给了我下面的异常。
com.microsoft.sqlserver.jdbc.SQLServerException: datediff 函数导致溢出。分隔的日期部分数 两个日期/时间实例太大。尝试使用带有 less 的 datediff 精确的日期部分。
JDBC 异常(对于 Java 人员)如下。
com.microsoft.sqlserver.jdbc.SQLServerException: datediff 函数 导致溢出。分隔两个的日期部分的数量 日期/时间实例太大。尝试使用带有 less 的 datediff 精确的日期部分。在 com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1454) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:388) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:338) 在 com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4026) 在 com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1416) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:185) 在 com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:160) 在 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:306) 在 org.DAO.UpdateEndTimeDAO.UpdateEndTimeDetails(UpdateEndTimeDAO.java:48) 在 org.servlet.UpdateEndTime.doPost(UpdateEndTime.java:38) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:648) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 Filter.MyFilter.doFilter(MyFilter.java:58) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) 在 org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(未知来源) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(未知来源) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Unknown Source)
异常指向我的问题中声明的第二个查询。
如果时间更短,比如 2 分钟或 3 分钟,它正在更新,没有任何问题。
请问我哪里出错了,我该如何解决这个问题。
我的休息表如下所示
这应该是按钮单击时捕获的结束时间,而不是 null
我的时间跟踪器如下所示。
而不是上面截图中的4.97
,它应该是我第一个截图中totalbreaktime
的总和。
谢谢
【问题讨论】:
据我所知,您正在计算 1900 年 1 月 1 日和某个日期之间的差异。datediff
只能跨越 68 年的秒数,请参阅 msdn.microsoft.com/en-us/library/ms189794(v=sql.110).aspx 反正你除以 60,为什么不直接使用 datediff(minutes, ...)
或重新考虑你在做什么。
因为从 1900 年 1 月 1 日到当前日期和时间之间的秒数约为 3,681,185,640。这比 32 位整数可以容纳的要大,datediff
函数仅限于此。
顺便说一句:我建议您也发布 1) 使用示例值的代码和 2) 插入的值。
嗨@MarkRotteveel,感谢您指出。附上我桌子的屏幕
嗨@CharlesBretana,Mark Rotteveel,是的,我现在看到了,但请告诉我如何解决这个问题?
【参考方案1】:
这是因为 DATETIME 函数(如 DATEDIFF、DATEADD 等)接受并返回整数 (INT) 数据类型。数据类型的限制是 2^31 (-2,147,483,648) 到 2^31-1 (2,147,483,647)。
因此,如果您将 -2147483648 添加到 TotalBreakTime。它返回“1948-08-08 14:01:46.000”
SELECT DATEADD(SS,CAST(-2147483648 AS BIGINT),'2016-08-26 17:15:54.000');
还有更多数据类型的限制返回ERROR。
Arithmetic overflow error converting expression to data type int.
因为查询中的日期之间以秒为单位的日期差异太大(超出数据类型的限制)。它返回错误。
SELECT CONVERT(NUMERIC(10,2),
SUM(CAST(DATEDIFF(Second, '19000101', '2016-08-26 17:15:54.000') AS BIGINT))/60.0)
我建议与您的团队讨论逻辑以相应地解决问题。
谢谢
【讨论】:
【参考方案2】:试试这个:
MERGE Time_Tracker as target
using
(SELECT USERID,
Sum(cast(cast(TotalBreakTime as float)
* 86400 as bigint)) ColumnWithBreaksCount
FROM BreaksTable b
Where datediff(day, StartTime, GETDATE()) = 0
GROUP BY USERID) source
ON target.USERID = source.USERID
WHEN MATCHED THEN UPDATE
SET BREAKS = source.ColumnWithBreaksCount;"
【讨论】:
以上是关于获取日期时间差异的异常的主要内容,如果未能解决你的问题,请参考以下文章