【问题标题】:ERROR: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax;错误:java.sql.SQLSyntaxErrorException:您的 SQL 语法有错误;
【发布时间】:2020-03-10 17:36:11
【问题描述】:

我读过很多类似的问题,但没有适合我的解决方案。

我正在使用 jersey 为 CRUD 编写 RESTful API,因此我需要实现 SQL 语句来执行事务。但是对于每个事务,都会发生相同的错误,即程序说我的 SQL 语法错误。

我已经搜索了很多解决方案,但没有一个适合我,我没有发现我的 SQL 代码有任何问题

(其他 3 个操作包括创建、删除和更新显示熟悉的错误)

以下是我的 Java 阅读代码:

  public HotelBean read(int hotelId, int roomId) {
    List<RoomBean> lBean = new ArrayList<RoomBean>();
    try {
      Connection conn = DBFactory.connectDB().getConn();
      Statement statement = conn.createStatement();
      ResultSet rs = statement.executeQuery("SELECT T1.HOTEL_ID, HOTEL_NAME, ROOM_ID, ROOM_NAME, OCCUPANCY, VACANCY, TOTAL_ROOM FROM HPMSDB.ROOM_INFO T1 INNER JOIN HPMSDB.HOTEL_INFO T2 ON T1.HOTEL_ID=T2.HOTEL_ID" + " WHERE T2.HOTEL_ID =" + hotelId + "AND T2.ROOM_ID="+ roomId);
      while (rs.next()) {
        RoomBean roomBean = new RoomBean();
        roomBean.setHotelId(rs.getInt(1));
        roomBean.setHotelName(rs.getString(2));
        roomBean.setRoomId(rs.getInt(3));
        roomBean.setRoomName(rs.getString(4));
        roomBean.setOccupancy(rs.getInt(5));
        roomBean.setVancancy(rs.getInt(6));
        roomBean.setTotalRoom(rs.getInt(7));
        lBean.add(roomBean);
      }
      conn.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    HotelBean hotelBean = new HotelBean();
    hotelBean.setRoomBean(lBean);
    return hotelBean;
  }

以下是我的数据库:

CREATE DATABASE HPMSDB DEFAULT CHARACTER SET UTF8
DEFAULT COLLATE UTF8_GENERAL_CI;

DROP TABLE IF EXISTS HPMSDB.HOTEL_INFO;
CREATE TABLE HPMSDB.HOTEL_INFO (
HOTEL_ID INT NOT NULL,
HOTEL_NAME VARCHAR(64),
RESORT_MANAGE VARCHAR(64),
PRIMARY KEY(HOTEL_ID)
);
DROP TABLE IF EXISTS HPMSDB.ROOM_INFO;
CREATE TABLE HPMSDB.ROOM_INFO (
HOTEL_ID INT NOT NULL,
ROOM_ID INT NOT NULL,
ROOM_NAME VARCHAR(64) NOT NULL,
OCCUPANCY INT,
VACANCY INT,
TOTAL_ROOM INT,
PRIMARY KEY(HOTEL_ID, ROOM_ID)
);

以下是阅读的错误信息:

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'T2.ROOM_ID=2' at line 1

以下是创建的错误信息:

java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE HOTEL_ID =2 AND ROOM_ID=1' at line 1

我真的很困惑,所有创建、更新、读取和删除都显示相同的错误。

感谢您的宝贵时间,祝您有美好的一天!

【问题讨论】:

  • 你能改变 =" + hotelId + "AND To =" + hotelId + " AND 你需要在 id 和 "AND" 之间留一个间距
  • 对于初学者 mysql sql server。它们是完全不同的 DBMS。但无论您使用哪个 DBMS,您的查询都存在可悲的缺陷。您正在构建一个字符串并执行它。这就是 sql 注入发生的方式,您的公司作为最新的数据泄露受害者出现在晚间新闻中。您需要使用参数化查询。
  • @ZacharyMcGee 感谢您的回复。但是我尝试了很多间距格式,它们都不适合我。

标签: java mysql sql sql-server rest


【解决方案1】:

问题是双重的..

一个是你的字符串连接中的AND关键字之前没有空格:

SELECT T1.HOTEL_ID, HOTEL_NAME, ROOM_ID, ROOM_NAME, OCCUPANCY, VACANCY, TOTAL_ROOM 
FROM HPMSDB.ROOM_INFO T1 INNER JOIN HPMSDB.HOTEL_INFO T2 
ON T1.HOTEL_ID=T2.HOTEL_ID" + " WHERE T2.HOTEL_ID =" + hotelId + "AND T2.ROOM_ID="+ roomId

会变成这样:

SELECT T1.HOTEL_ID, HOTEL_NAME, ROOM_ID, ROOM_NAME, OCCUPANCY, VACANCY, TOTAL_ROOM 
FROM HPMSDB.ROOM_INFO T1 INNER JOIN HPMSDB.HOTEL_INFO T2 
ON T1.HOTEL_ID=T2.HOTEL_ID WHERE T2.HOTEL_ID =1234AND T2.ROOM_ID=9999
                                              ^^^^^^^
                                              LOOK!

但更大的问题是您使用字符串 concat 将值放入 SQL 中。这是上线时被黑客入侵的绝佳方式

请使用parameterized queries

上面链接的网站提供了有关使用 PreparedStatement 的建议。请记住,如果您遇到一种情况,您认为“我想使用参数,但我只需要通过字符串 concat 构建此 SQL;没有其他方法” - 请记住 没有什么可以阻止您连接参数 然后用一个值填充参数;始终避免将 连接到 SQL 中

假设你有两个数组:

columns[0] = "hotelid";
values[0] = "RoyalPalace";
columns[1] = "roomnum";
values[1] = "99";

你可能认为你必须让你的 sql 像这样:

string sql = "select * from hotels where 1=1 ";
for(int i=0; i<columns.length; i++){
  sql = sql + " AND " + columns[i] + " = " + values[i]; // no no; do not concat values in!
}

concat 中的参数,并设置它们(Hibernate 语法):

string sql = "select * from hotels where 1=1 ";
for(int i=0; i<columns.length; i++){
  sql = sql + " AND " + columns[i] + " = :p" + i; // yes, concat a parameter named pX in!
}
Query query = session.createQuery(sql);

for(int i=0; i<columns.length; i++){
  query.setString(":p"+i, values[i]); // give the parameters a value
}

我知道这是一个蹩脚的例子。但以防万一你发现自己处于一个你认为你需要连接值的场景中——你永远不会这样做

【讨论】:

  • 感谢您的回答!但是一个问题是我的其他代码也显示了同样的错误,像这样:String sql = "UPDATE HPMSDB.ROOM_INFO SET OCCUPANCY = OCCUPANCY + " + roomBean.getOccupancy() + ", VACANCY = VACANCY - " + roomBean.getOccupancy() + " WHERE HOTEL_ID =" + roomBean.getHotelId() + " AND ROOM_ID=" + roomBean.getRoomId();
  • 您需要将生成的 SQL 转储到日志中,然后将其粘贴到可以针对 db 运行它的东西中。由于某些类似的原因,它将失败,例如其中一个 getXXX() 返回“”或 null 等,这意味着您的 SQL 有语法错误。请使用参数。使用参数时也很容易看出哪里出错了,因为您的 SQL 就像 UPDATE HPMSDB.ROOM_INFO SET OCCUPANCY = OCCUPANCY + :occu, VACANCY = VACANCY - :occu WHERE HOTEL_ID = :hotelid AND ROOM_ID= :roomid 即语法现在是正确的,无论参数中的值是什么。
  • 而且,当您尝试签入名为 Patrick O'Leary 的人时,您的 SQL 也不会爆炸
猜你喜欢
  • 2017-09-07
  • 2019-12-03
  • 1970-01-01
  • 2020-09-21
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
  • 2016-01-24
  • 2018-08-29
相关资源
最近更新 更多