【问题标题】:Same query provides different results in SQL Server client and JDBC client相同的查询在 SQL Server 客户端和 JDBC 客户端提供不同的结果
【发布时间】:2021-03-15 08:18:48
【问题描述】:

我在我的项目中使用 SQL Server,我试图检索表中两个时间戳之间的条目。该表的架构如下:

CREATE TABLE ENTRY (
    ID INTEGER IDENTITY(1,1) NOT NULL,
    NAME VARCHAR (2000),
    USER_ID VARCHAR (31) NOT NULL,
    ADDED_TIME DATETIME NOT NULL
);

我需要获取在特定时间戳和当前时间戳之后添加的条目。为此,我尝试了下面提到的查询:

SELECT * FROM ENTRY WHERE
ADDED_TIME>$parameter1 AND ADDED_TIME<$currentTime ORDER BY ADDED_TIME DESC

SELECT * FROM ENTRY WHERE
ADDED_TIME>'12/03/2020 12:13:08.583' AND ADDED_TIME<'12/03/2020 13:36:05.159' ORDER BY ADDED_TIME DESC

直接在 SQL 客户端上执行此查询时,我得到了所有预期的结果。但是当我从 Java JDBC 客户端执行相同的查询时,resultset 包含 ADDED_TIME 等于 parameter1 的条目。

这是客户端的Java代码:

String sql = "SELECT * FROM ENTRY WHERE ADDED_TIME>? AND ADDED_TIME<? ORDER BY ADDED_TIME DESC";
Date to = new Date();
PreparedStatement statement = conn.prepareStatement(sql);
statement.setTimestamp(1, new Timestamp(Long.parseLong("1606977788583")));
statement.setTimestamp(2, new Timestamp(to.getTime()));
ResultSet results = statement.executeQuery();

结果集包含具有ADDED_TIME1606977788583 的条目。只有当我使用 Java JDBC 客户端执行它时才会返回它。这可能是什么原因。

感谢您对此的任何帮助,

【问题讨论】:

  • 我不太确定这些查询是否相同;一个使用字符串文本作为日期,而另一个似乎使用日期和时间参数。根据定义,它们是不同的。使用字符串文字时,对于日期,您需要确保也使用模棱两可的文字;在 yyyyMMddyyyy-MM-ddThh:mm:ss.nnnnnnn 的 SQL 服务器中。
  • 您需要提供示例数据,并以比较苹果和苹果的方式编写示例代码。
  • 顺便说一下,MS SQL Server 中的DATETIME 类型 代表片刻,不是 时间轴上的特定点。该类型是日期和时间,但缺少任何时区概念或与 UTC 的偏移量。因此,将这些值与当前时刻进行比较是值得怀疑的。要跟踪时刻,您应该在 MS SQL Server 中使用类型 datetimeoffset,该类型类似于 SQL 标准类型 TIMESTAMP WITH TIME ZONE

标签: java sql-server jdbc mssql-jdbc


【解决方案1】:

JDBC Java客户端给出不同结果的原因是:

SQL Server 中有两种数据类型支持日期时间格式:

  1. 日期时间
  2. 日期时间2

ADDED_TIME 列的数据类型是 DATETIME。但是当使用PreparedStatement.setTimestamp() 设置参数时,参数会隐式映射到 DATETIME2 类型。使用setTimestamp() 方法时,似乎无法将其设置为 DATETIME 类型。这也在 [1] 中进行了讨论。

通过如下更正查询来修复它:

String sql = "SELECT * FROM ENTRY WHERE 
              ADDED_TIME> CONVERT(DATETIME, ?) AND 
              ADDED_TIME< CONVERT(DATETIME, ?) 
              ORDER BY ADDED_TIME DESC";

[1]https://github.com/microsoft/mssql-jdbc/issues/443

【讨论】:

  • setTimestamp 方法是 Java 是与 Java 的最早版本捆绑在一起的可怕日期时间类的一部分,现在是遗留的。仅使用现代 Java 中的 java.time 类,使用 PreparedTransaction::setObject 方法。
猜你喜欢
  • 2014-07-28
  • 1970-01-01
  • 2017-05-02
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-06
  • 2014-03-02
相关资源
最近更新 更多