select 条记录将在未来 30 天内到期 - sql 声明

select records expiring within the next 30 days - sql statement

数据类型:timestamp 列名:dlExpiryDate

SELECT * 
  FROM QUALIFICATION  
 WHERE dlExpiryDate >= NOW() 
   AND dlExpiryDate < NOW() + INTERVAL 1 MONTH;

尝试了无数次查询来获得答案,但没有奏效。任何人都得到了解决这个问题的答案。有一个我在上面试过的例子,但它不起作用。 打印出堆栈跟踪:

Severe: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "1" at line 1, column 93. at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source) at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source) at org.apache.derby.client.am.Statement.executeQuery(Unknown Source) at org.apache.jsp.viewQualification_jsp._jspService(viewQualification_jsp.java:105) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283) at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167) at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206) at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235) at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.derby.client.am.SqlException: Syntax error: Encountered "1" at line 1, column 93. at org.apache.derby.client.am.Statement.completeSqlca(Unknown Source) at org.apache.derby.client.net.NetStatementReply.parsePrepareError(Unknown Source) at org.apache.derby.client.net.NetStatementReply.parsePRPSQLSTTreply(Unknown Source) at org.apache.derby.client.net.NetStatementReply.readPrepareDescribeOutput(Unknown Source) at org.apache.derby.client.net.StatementReply.readPrepareDescribeOutput(Unknown Source) at org.apache.derby.client.net.NetStatement.readPrepareDescribeOutput_(Unknown Source) at org.apache.derby.client.am.Statement.readPrepareDescribeOutput(Unknown Source) at org.apache.derby.client.am.Statement.flowExecute(Unknown Source) at org.apache.derby.client.am.Statement.executeQueryX(Unknown Source) ... 36 more

有人知道这个问题的答案吗?谢谢

如果您想以与数据库无关的方式执行该查询,请解析 Java 代码中的 2 个日期并使用 PreparedStatement.

提供它们
LocalDate today = LocalDate.now();
String sql = "SELECT *" +
              " FROM QUALIFICATION" +
             " WHERE dlExpiryDate >= ?" +
               " AND dlExpiryDate < ?";
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
    stmt.setDate(1, java.sql.Date.valueOf(today));
    stmt.setDate(2, java.sql.Date.valueOf(today.plusMonths(1)));
    try (ResultSet rs = stmt.executeQuery()) {
        // code here
    }
}

根据 JDBC 驱动程序(例如不是 Microsoft),您还可以使用 setObject.

stmt.setObject(1, today);
stmt.setObject(2, today.plusMonths(1));

时区

请注意 TIMESTAMP type in Derby is akin to the SQL-standard type TIMESTAMP WITHOUT TIME ZONE (at least it seems that way, the documentation is poorly written). Meaning, that type lacks any concept of time zone or offset-from-UTC。因此,此类型 而不是 表示特定时刻,即时间轴上的一个点。相反,它表示 潜在的 时刻,时间跨度约为 26-27 小时,即全球时区范围。

例如,如果您存储的是 2019 年 1 月 23 日的中午,我们不知道您指的是日本东京的中午,还是印度加尔各答的中午。或者你可能是指几个小时后,法国巴黎的中午。或者再过几个小时,当中午到达魁北克蒙特利尔时。这种类型的值意味着 23 日中午 任何地方,对于 26-27 小时范围内的任何时刻。

因此,与当前时刻相比,对该类型进行查询 毫无意义。

但是……

如果您一直在处理应用程序中的时区,并假装数据库中的所有值都属于某个时区,请在捕获当前时刻时使用该时区。

ZonedDateTime

java.time类中,我们用ZonedDateTime来表示特定区域(时区)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone).

丢弃有价值的 zone/offset 信息 LocalDateTime

我们可以去除时区信息,只在 LocalDateTime 对象中留下日期和时间。

LocalDateTime ldt = zdt.toLocalDateTime()

一天开始

如果搜索一个月,您可能希望从当天的开始开始。暂时,我们会让 java.time 确定一天的第一个时刻,因为由于夏令时等异常情况,一天并不总是从 00:00 开始时间(夏令时)。但是由于 LocalDateTime 缺少 zone/offset,我们无法解释此类异常情况。所以我们就用 00:00.

LocalDateTime ldtStartOfDay = ldt.with( LocalTime.MIN ) ;

日期时间数学

要添加您的月份,我们可以使用 plus…minus… 方法进行日期时间计算。

LocalDateTime ldtMonthLater = ldtStartOfDay.plusMonths() ;

SQL 占位符

传递这些值以替换准备好的语句中 SQL 中的占位符。

SELECT * 
FROM QUALIFICATION  
WHERE dlExpiryDate >= ?
AND dlExpiryDate < ?
;

JDBC 4.2

从 JDBC 4.2 开始,我们可以使用 setObject & [=27= 直接与数据库交换 java.time 对象].无需使用可怕的遗产 类,例如 java.sql.Timestamp

myPreparedStatement.setObject( 1 , ldtStartOfDay) ;
myPreparedStatement.setObject( 2 , ldtMonthLater) ;

检索时。

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

考虑其他数据库

您可能要考虑使用其他数据库。 Oracle 停止将 Derby 捆绑为 Java DB,因为发现它不适合生产使用。

如果你想要一个用 Java 编写的开源数据库,我建议 H2 Database Engine, suitable for both embedded use as well as a server. If you want an open-source database server built for heavy-duty enterprise-quality work, I suggest Postgres.


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类.

在哪里获取java.time类?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.