在 Postgres 表中插入时间戳的问题

问题描述 投票:0回答:6

我正在尝试通过 Java 在 postgres 表中插入一个值。列类型是时间戳。

代码是这样的:

SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String gameStartedTime = format.format(new Date());

String query= "UPDATE gameStatus g SET g.status ='" + gameStatus
    + g.gameStartTime= to_date('"
            + gameStartedTime  + "','yyyy-MM-dd HH:mm:ss')"
    // Doesn't matter much
+ " WHERE g.status = 'STARTED' AND " + "g.condition="+ game.getCondition();

现在,当我尝试执行此语句时,它失败了,我收到如下消息:

错误:格式字符串中“mm”字段的值冲突。 详细信息:此值与同一字段类型的先前设置相矛盾。

我不知道出了什么问题!!

对此的任何帮助都会很有用。 提前致谢。 -乙脑

java postgresql jdbc
6个回答
8
投票

mm
 
to_date()
 功能的月份。 
mm
MM

之间没有区别(与 Java 的 SimpleDateFormat 不同)。

您需要使用 
mi

来表示分钟数。

手册中提供了所有模式的完整列表:http://www.postgresql.org/docs/current/static/functions-formatting.html#FUNCTIONS-FORMATTING-DATETIME-TABLE

但是您一开始就不应该使用“动态”SQL。最好使用 
PreparedStatement
java.sql.Timestamp
setTimestamp()

来代替。这可以帮助您避免任何格式问题并防止 SQL 注入。

2
投票

这样做。

java.sql.Date date=new Date(); Timestamp timestamp = new Timestamp(date.getTime()); this.date = timestamp;

然后将
this.date

添加到数据库中..

2
投票

尝试一下:

ps.setTimestamp(position, new Timestamp(System.currentTimeMillis()));

1
投票

尝试从查询中分离日期部分并尝试比较这些值。
看来(至少从我看来)代表分钟的mm, 
不符合
g.gameStartTime= to_date

如果您将这部分拉到查询之外,您可以检查这些值,也许您会发现问题所在。

1
投票

使用当前时间,这种方式对我有用:

String query = "INSERT INTO table1 (id,t) VALUES (?, ?)"; //update table1 set t=? where id=? Connection con = null; PreparedStatement ps = null; try{ con = dataSource.getConnection(); ps = con.prepareStatement(query); ps.setLong(1, 1234); // update ps.setLong(2, 1234); Calendar cal = Calendar.getInstance(); Timestamp timestamp = new Timestamp(cal.getTimeInMillis()); ps.setTimestamp(2,timestamp); // ps.setTimestamp(1,timestamp); int out = ps.executeUpdate(); if(out !=0){ System.out.println("Record saved"); } }catch(SQLException e){ e.printStackTrace(); }finally{ try { ps.close(); con.close(); } catch (SQLException e) { e.printStackTrace(); } }

或者,您可以使用以下几行建立特定的时间戳:

Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, 2015); cal.set(Calendar.MONTH, 0); // 0 january cal.set(Calendar.DAY_OF_MONTH, 26); cal.set(Calendar.HOUR_OF_DAY, 10); cal.set(Calendar.MINUTE, 47); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); Timestamp timestamp = new Timestamp(cal.getTimeInMillis());

0
投票

列的数据类型错误

列类型为时间戳。

TIMESTAMP WITHOUT TIME ZONE
,在 Postgres 中也称为 
TIMESTAMP

,是记录时间轴上某个时刻的错误数据类型。

要记录某个时刻,您必须使用 
TIMESTAMP WITH TIME ZONE

类型,因为它在 Postgres 和 SQL 标准中都是已知的。

避免遗留日期时间类

Java 中存在严重缺陷的日期时间类已被 JSR 310 中定义并内置于 Java 8+ 中的现代 java.time

类所取代。

切勿使用 
Date
Calendar
Timestamp
SimpleDateFormat

java.time

要在 Java 中捕获当前时刻,我们可以使用 
java.time.Instant
Instant

表示与 UTC 的偏移量为零时-分-秒的时刻。
Instant instant = Instant.now() ;  // Current moment as seen in UTC.

但是,虽然 JDBC 4.2 及更高版本要求每个 JDBC 驱动程序都支持 java.time

 类,但 
Instant
 未映射。相反,JDBC 将 
java.time.OffsetDateTime
 类映射到 SQL 标准类型 
TIMESTAMP WITH TIME ZONE

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;

术语:偏移量仅仅是 UTC 时间子午线之前/之后的小时数、分钟数、秒数。时区是一个命名的(
Continent/Region
,例如:
Europe/Paris)历史,记录了特定地区的人民所使用的偏移量的过去、现在和未来的变化,由他们的政治家决定。 SQL 标准的作者并没有很好地理解日期时间处理,并且误用了术语“时区”,而他们真正的意思是“偏移”。 避免SQL注入

你说:

String query= "UPDATE gameStatus g SET g.status ='" + gameStatus + g.gameStartTime= to_date('" + gameStartedTime + "','yyyy-MM-dd HH:mm:ss')"

不要像这样连接文本来生成 SQL。这个坏习惯会让你容易受到
SQL注入
攻击。相反,使用传递到

prepared 语句中的参数。 使用对象,而不是文本

并使用智能对象而不是哑字符串。我们将 Java 中的日期时间对象映射到 SQL 和 Postgres 中的日期时间类型。因此,请勿将文本转换为文本。

现代 Java 现在提供

文本块

来减轻编写 SQL 的繁琐工作。

String sql = """ UPDATE order_ SET order_.when_ = ? WHERE … ; """ ; … myPreparedStatement.setObject( 1 , odt ) ;


© www.soinside.com 2019 - 2024. All rights reserved.