![](/img/trans.png)
[英]PostgreSQL Parameter error (timestamp with time zone, timestamp without time zone)
[英]What should the type of parameter be in Java when it is a “timestamp without time zone” in postgresql?
我正在尝试通过 Java 和 JDBC 在 postgresql 中运行查询。
postgresql中“table”的“activitydate”列是“timestamp without time zone”。 我尝试使用 String 传递日期但没有用( org.postgresql.util.PSQLException: ERROR: operator does not exist: timestamp without time zone > character changed) 。
我应该使用什么类型而不是String来存储“start_date”和“end_date”并将它们传递给查询?
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);
对于使用半开放时间跨度的 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 ) ;
SELECT COUNT(*) FROM table WHERE activitydate > '2014-11-20' AND activitydate < '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。
我建议你改变你的想法,养成使用半开放方法来定义时间跨度的习惯。 在半开中,开头是包容的,而结尾是独占的。 因此,对于 20 日的整个一天,搜索等于或晚于 20 日的日期,并运行到(但不包括)21 日。 至于第一部分,“等于或以后”的更简短的说法是“不在之前”,因此我们使用!<
。
String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ;
将该sql
字符串提供给您准备好的语句。 然后为占位符传递两个LocalDateTime
对象。
myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;
您必须使用java.sql.Timestamp
或java.sql.Date
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.