获取日期时间差异的异常

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;" 

【讨论】:

以上是关于获取日期时间差异的异常的主要内容,如果未能解决你的问题,请参考以下文章

如何比较日期和时间并获取差异,然后在 Javascript 中将其设置为秒

Kotlin:获取两个日期之间的差异(现在和以前的日期)

Mongodb,按日期差异分组并获取小时

JS获取日期及修改日期方法汇总

如何获取 MySQL 上两个日期之间的差异天数?

我需要从 mysql 数据库中获取日期并打印今天和获取日期之间的差异