我正在尝试通过Java和JDBC在postgresql中运行查询。
&#34;活动日期&#34; &#34;表&#34;的列在postgresql中是&#34;时区没有时区&#34;。我尝试使用String来传递日期,但没有工作( org.postgresql.util.PSQLException:ERROR:运算符不存在:没有时区的时间戳&gt;字符变化)。< / p>
我应该用什么类型代替字符串来存储&#34; start_date&#34;和&#34; end_date&#34;并将它们传递给查询?
BTW SELECT COUNT(*) FROM table WHERE activitydate > '2014-11-20' AND activitydate < '2014-11-21' AND zipcode = 12345
在pgadmin中完美运行。
public Response query(
@QueryParam("start_date") String start_date,
@QueryParam("end_date") String end_date,
@QueryParam("zipcode") String zipcode
) throws Exception {
...
...
pstmt = conn.prepareStatement("SELECT COUNT(*) FROM table WHERE activitydate > ? AND activitydate < ? AND zipcode = ?");
pstmt.setString(1, start_date);
pstmt.setString(2, end_date);
pstmt.setString(3, zipcode);
更新: 我将其更改为java.sql.Timestamp但仍然无法工作:
public Response query(
@QueryParam("start_date") Timestamp start_date,
@QueryParam("end_date") Timestamp end_date,
@QueryParam("zipcode") String zipcode
) throws Exception {
...
...
pstmt = conn.prepareStatement("SELECT COUNT(*) FROM table WHERE activitydate > ? AND activitydate < ? AND zipcode = ?");
pstmt.setTimestamp(1, start_date);
pstmt.setTimestamp(2, end_date);
pstmt.setString(3, zipcode);
答案 0 :(得分:3)
您必须使用java.sql.Timestamp
或java.sql.Date
。
答案 1 :(得分:1)
对于使用半开时间跨度的SQL:
"SELECT * FROM tbl WHERE when !< ? AND when < ? ; "
myPreparedStatement.setObject( // Use a prepared statement so you can pass smart objects rather than dumb strings.
1 , // Specify which placeholder is being fulfilled.
LocalDate // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
.parse( "2014-11-20" ) // Parse an input string in standard ISO 8601 format to get a `LocalDate` object.
.atStartOfDay() // Determine the first moment of the day on that date. Returns a `LocalDateTime` object representing a date with time-of-day but lacking any concept of time zone or offset-from-UTC.
) ;
myPreparedStatement.setObject(
2 ,
LocalDate
.parse( "2014-11-21" )
.atStartOfDay()
) ;
当心:我猜您在数据库中使用的列类型错误。 只能使用TIMESTAMP WITH TIME ZONE
跟踪时刻,不能 TIMESTAMP WITHOUT TIME ZONE
跟踪时刻。搜索堆栈溢出以获取更多信息。
Jens的答案现在已过时。如今,您应该使用现代的 java.time 类,该类取代了麻烦的旧的传统日期时间类。
postgresql中的“无时区的时间戳”?
Postgres和SQL标准上的此数据类型故意缺少从UTC偏移或时区的上下文。因此,请注意,这种类型不能表示时刻,不是时间线上的一点。
我将其更改为java.sql.Timestamp
不是,数据类型错误。 java.sql.Timestamp
类不仅是传统,而且在设计上存在严重缺陷,它代表时刻,是时间轴上的特定点。因此,这与您的TIMESTAMP WITHOUT TIME ZONE
类型的列不匹配。
LocalDateTime
您应该改用LocalDateTime
类。此类表示带有日期的日期,但是缺少偏移或时区的任何概念。
要从数据库中检索值。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
向数据库发送值。
myPreparedStatement.setObject( … , ldt ) ;
从表中选择COUNT(*)个活动日期>'2014-11-20'和活动日期<'2014-11-21'
您在这里还有另一个不匹配之处。您提供的是仅日期的值,但是您的列中包含日期与时间的值。
另一个问题:您在应使用智能对象的地方使用了哑字符串。从JDBC 4.2开始,我们可以与数据库交换 java.time 对象。将PreparedStatement
与占位符一起使用,并通过`set
要解决带有日期时间的日期问题,我们需要确定一天的开始时间。使用LocalDateTime
,我们无需考虑任何时区异常。因此,一天总是从00:00开始。不过,我们应该养成要求 java.time 确定一天中开始时间的习惯。
LocalDate startDate = LocalDate.parse( "2014-11-20" ) ;
LocalDate stopDate = LocalDate.parse( "2014-11-21" ) ;
LocalDateTime start = startDate.atStartOfDay() ;
LocalDateTime stop = stopDate.atStartOfDay() ;
使用占位符为您编写SQL。
我建议您改变思维方式,以习惯于定义时间跨度的半开放式方法。在Half-Open中,开头为包含,而结尾为专有。因此,对于20日的一整天,请搜索等于或晚于20日的日期,直到(包括)21日为止。对于第一部分,说“等于或晚于”等于“不早于”,因此我们使用!<
。
String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ;
将sql
字符串输入到准备好的语句中。然后为占位符传递两个LocalDateTime
对象。
myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;