选择在30天内到期的记录-sql语句

时间:2019-02-05 16:38:12

标签: java date derby

数据类型:timestamp 列名称:dlExpiryDate

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

尝试了大量查询以获取答案,但无法正常工作。任何人都可以解决这个问题。得到了我在上面尝试过的示例,但是它不起作用。 打印出堆栈跟踪:

  

严重:java.sql.SQLSyntaxErrorException:语法错误:遇到   第1行第93列的“ 1”。   org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(未知   来源)   org.apache.derby.client.am.SqlException.getSQLException(未知   来源)位于org.apache.derby.client.am.Statement.executeQuery(未知   来源)   org.apache.jsp.viewQualification_jsp._jspService(viewQualification_jsp.java:105)     在   org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:790)处   org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:411)     在   org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:473)     在org.apache.jasper.servlet.JspServlet.service(JspServlet.java:377)     在javax.servlet.http.HttpServlet.service(HttpServlet.java:790)处   org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)     在   org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)     在   org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)     在   org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)     在   org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)     在com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)处   org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)     在   org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)     在   org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)     在   com.sun.enterprise.v3.services.impl.ContainerMapper $ HttpHandlerCallable.call(ContainerMapper.java:459)     在   com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)     在   org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)     在   org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)     在   org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)     在   org.glassfish.grizzly.filterchain.ExecutorResolver $ 9.execute(ExecutorResolver.java:119)     在   org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)     在   org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)     在   org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)     在   org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)     在   org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)     在   org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)     在   org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)     在   org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)     在   org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access $ 100(WorkerThreadIOStrategy.java:56)     在   org.glassfish.grizzly.strategies.WorkerThreadIOStrategy $ WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)     在   org.glassfish.grizzly.threadpool.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:591)     在   org.glassfish.grizzly.threadpool.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:571)     在java.lang.Thread.run(Thread.java:745)造成原因:   org.apache.derby.client.am.SqlException:语法错误:遇到“ 1”   在第1行的第93列。   org.apache.derby.client.am.Statement.completeSqlca(来源未知)   org.apache.derby.client.net.NetStatementReply.parsePrepareError(未知   来源)   org.apache.derby.client.net.NetStatementReply.parsePRPSQLSTTreply(未知   来源)   org.apache.derby.client.net.NetStatementReply.readPrepareDescribeOutput(未知   来源)   org.apache.derby.client.net.StatementReply.readPrepareDescribeOutput(未知   来源)   org.apache.derby.client.net.NetStatement.readPrepareDescribeOutput_(未知   来源)   org.apache.derby.client.am.Statement.readPrepareDescribeOutput(未知   来源)位于org.apache.derby.client.am.Statement.flowExecute(未知   来源)位于org.apache.derby.client.am.Statement.executeQueryX(未知   来源)...还有36个

有人对此有答案吗?谢谢

2 个答案:

答案 0 :(得分:1)

如果要以与数据库无关的方式进行该查询,请解析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));

答案 1 :(得分:1)

时区

请注意,Derby中的TIMESTAMP类型类似于SQL标准类型TIMESTAMP WITHOUT TIME ZONE(至少看起来这样,文档编写得很差)。意思是,该类型缺少time zoneoffset-from-UTC的任何概念。因此,此类型 not 并不代表特定时刻,即时间轴上的一个点。相反,它代表了大约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).

使用LocalDateTime丢弃有价值的区域/偏移信息

我们可以剥离时区信息,在LocalDateTime对象中仅保留日期和时间。

LocalDateTime ldt = zdt.toLocalDateTime()

当天开始

如果搜索一个月,则可能要从一天开始。暂时,我们让 java.time 确定一天的第一时刻,因为由于诸如夏令时(DST)之类的异常,一天并非总是从00:00开始。但是在LocalDateTime缺少区域/偏移的情况下,我们无法解决此类异常情况。所以我们只去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和更高版本开始,我们可以使用setObjectgetObject与数据库直接交换 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,它既适合嵌入式用途,也适合服务器。如果您想要为重型企业级质量的工作而构建的开源数据库服务器,建议使用Postgres


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore