JDBC操作PostgreSQL执行ResultSet.updateRow时出现near "("语法错误如何解决?
问题原因排查
- PostgreSQL JDBC驱动对可更新ResultSet的语法有严格限制,仅单表查询、包含主键、无窗口函数/子查询/多表连接/聚合操作的ResultSet才支持
updateRow()操作。你的res1使用了多层嵌套子查询、窗口函数ROW_NUMBER()、多表关联,驱动无法自动生成合法的UPDATE语句,所以执行updateRow()时抛出语法错误。 - 你第二个查询的过滤条件硬编码了
hb."bookedbyclientID"=107,没有使用传入的clientID参数,属于逻辑bug。 - 直接拼接SQL参数存在SQL注入风险,Statement没有做参数校验,不符合安全规范。
最优解决方案
放弃使用可更新ResultSet,直接通过主键执行UPDATE语句,逻辑更简单、性能更高、兼容性更强:
public void showRoomBookings(int clientID) { Scanner myObj = new Scanner(System.in); // 存储查询到的预订主键ID,和展示序号对应 List<Integer> bookingIdList = new ArrayList<>(); // 使用try-with-resources自动关闭资源 try (Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); ResultSet res = st.executeQuery("SELECT rb.\"hotelbookingID\",rb.\"roomID\",rb.\"bookedforpersonID\",rb.checkin,rb.checkout,rb.rate " + "FROM roombooking rb ,hotelbooking hb " + "where rb.\"bookedforpersonID\"=hb.\"bookedbyclientID\" " + "AND hb.\"bookedbyclientID\"="+clientID+" " + "order by rb.\"hotelbookingID\"")) { int j=1; while(res.next()) { bookingIdList.add(res.getInt(1)); System.out.println(j+")roomID:"+res.getInt(2) +" bookedforpersonID:"+res.getInt(3)+" checkin:"+res.getDate(4)+" checkout:"+res.getDate(5) +" rate:"+res.getInt(6)); j++; } System.out.println("Enter the number of the room you want to update:"); int answer = myObj.nextInt(); // 校验输入合法性 if (answer <1 || answer > bookingIdList.size()) { System.out.println("输入序号不合法"); return; } Integer targetBookingId = bookingIdList.get(answer - 1); // 直接执行更新语句,使用PreparedStatement避免注入 try (PreparedStatement pst = conn.prepareStatement("UPDATE roombooking SET rate = ? WHERE \"hotelbookingID\" = ?")) { pst.setInt(1,40); pst.setInt(2,targetBookingId); pst.executeUpdate(); System.out.println("更新成功"); } } catch (SQLException e) { e.printStackTrace(); } }
可选兼容方案(仅需可更新ResultSet时使用)
如果必须使用updateRow()方法,需要修改res1的查询逻辑为仅查询单表roombooking,通过第一个查询拿到的hotelbookingID主键直接查询对应单条记录,符合可更新ResultSet的要求即可正常执行更新。
内容的提问来源于stack exchange,提问作者Gn gnk
相关产品推荐
相关产品推荐

