Java向PostgreSQL插入Date类型数据报错:列类型不匹配
向PostgreSQL的autore表插入date类型字段失败的解决方法
问题现象
向PostgreSQL的autore表插入记录时,datanascita(date类型)列插入失败,核心报错提示:
org.postgresql.util.PSQLException: ERROR: 列"datanascita"是date类型,但表达式是integer类型
提示: 你需要重写或转换表达式。
位置: 90
插入执行代码
Connection connection = DatabaseConnection.getInstance().getConnection(); ResultSet result = null; try { Statement statement = connection.createStatement(); statement.executeUpdate(query,Statement.RETURN_GENERATED_KEYS); result = statement.getGeneratedKeys(); } catch (SQLException e) { e.printStackTrace(); } finally { return result; }
调用代码
String authorName = "Paul"; String authorSurname = "Mac"; DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyy-MM-dd" ) ; LocalDate date = LocalDate.parse ( "2017-09-24" , f ); String query = "Insert into autore(nome_autore, cognome_autore, datanascita) values('"+authorName+"', '"+authorSurname+"', "+date+")";
完整报错栈
org.postgresql.util.PSQLException: ERROR: column "datanascita" is of type date but expression is of type integer Suggerimento: You will need to rewrite or cast the expression. Posizione: 90 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413) at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:333) at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:319) at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:1259) at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:1240) at projectRiferimentiBibliografici/com.ProjectRiferimentiBibliografici.DatabaseConnection.QueryManager.executeUpdateWithResultSet(QueryManager.java:113) at projectRiferimentiBibliografici/com.ProjectRiferimentiBibliografici.DAOImplementation.AuthorDaoPostgresql.insertAuthor(AuthorDaoPostgresql.java:136) at projectRiferimentiBibliografici/com.ProjectRiferimentiBibliografici.Main.MainCe.main(MainCe.java:43)
问题原因
拼接SQL时,LocalDate对象直接拼接会生成2017-09-24格式的字符串,但因为没有包裹单引号,PostgreSQL会将其识别为2017-9-24的算术运算,结果为整数1984,与date类型的列不匹配,从而抛出类型错误。
解决方案
方法1:手动给日期加单引号(不推荐)
修改SQL拼接逻辑,给date变量添加单引号,让PostgreSQL识别为日期字符串:
String query = "Insert into autore(nome_autore, cognome_autore, datanascita) values('"+authorName+"', '"+authorSurname+"', '"+date+"')";
该方法仅临时解决问题,存在SQL注入风险,且日期格式不符合要求时仍会出错,不建议生产环境使用。
方法2:使用PreparedStatement(推荐)
采用预编译语句绑定参数,既能自动处理类型转换,又能彻底避免SQL注入:
修改插入执行代码
Connection connection = DatabaseConnection.getInstance().getConnection(); ResultSet result = null; try (PreparedStatement pstmt = connection.prepareStatement( "Insert into autore(nome_autore, cognome_autore, datanascita) values(?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) { pstmt.setString(1, authorName); pstmt.setString(2, authorSurname); // 两种参数绑定方式任选其一 pstmt.setObject(3, date); // 直接绑定LocalDate,JDBC驱动自动转换 // pstmt.setDate(3, java.sql.Date.valueOf(date)); // 转换为java.sql.Date绑定 pstmt.executeUpdate(); result = pstmt.getGeneratedKeys(); } catch (SQLException e) { e.printStackTrace(); } finally { return result; }
调用代码调整
无需手动拼接SQL,直接传入参数即可(yyyy-MM-dd是LocalDate.parse的默认格式,可省略格式化器):
String authorName = "Paul"; String authorSurname = "Mac"; LocalDate date = LocalDate.parse("2017-09-24");
内容的提问来源于stack exchange,提问作者yellowood
相关产品推荐
相关产品推荐

