使用JDBC时触发MySQLSyntaxErrorException的问题排查
SQL语法错误排查与修复方案
报错信息
MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'Name,Enrol no,Department,Mobile No,Email) values(Effie,1051,CE,123456789,121...' at line 1
问题代码
String Create() { String sql; Scanner sc = new Scanner(System.in); System.out.println("Enter name:"); String name = sc.nextLine(); System.out.println("Enter enrl:"); long enrl = sc.nextInt(); sc.nextLine(); System.out.println("Enter department:"); String dept = sc.nextLine(); System.out.println("Enter mobile no:"); String mono = sc.nextLine(); System.out.println("Enter mail:"); String mail = sc.nextLine(); sql="Insert into stud_details(First Name,Enrol no,Department,Mobile No,Email) values("+name+","+enrl+","+dept+","+mono+","+mail+");"; return sql; }
错误原因分析
- 带空格的字段名未转义:SQL中字段名包含空格(如
First Name、Mobile No)时,必须用反引号(`)包裹,否则数据库会将空格后的内容识别为无效语法。 - 字符串值未加引号:SQL中字符串类型的字段值必须用单引号(')包裹,直接拼接变量会导致字符串变成裸文本,触发语法错误。
- SQL注入风险:直接拼接用户输入到SQL语句中,存在严重的SQL注入漏洞,可能导致数据泄露或破坏。
修复方案
临时语法修复(不推荐,仍有注入风险)
仅解决语法错误,但未修复安全问题:
String Create() { String sql; Scanner sc = new Scanner(System.in); System.out.println("Enter name:"); String name = sc.nextLine(); System.out.println("Enter enrl:"); long enrl = sc.nextInt(); sc.nextLine(); System.out.println("Enter department:"); String dept = sc.nextLine(); System.out.println("Enter mobile no:"); String mono = sc.nextLine(); System.out.println("Enter mail:"); String mail = sc.nextLine(); // 用反引号包裹带空格的字段名,字符串值添加单引号 sql = "Insert into stud_details(`First Name`,`Enrol no`,`Department`,`Mobile No`,`Email`) values('" + name + "'," + enrl + ",'" + dept + "','" + mono + "','" + mail + "');"; return sql; }
安全修复方案(推荐,使用参数化查询)
使用PreparedStatement实现参数化查询,同时解决语法错误和SQL注入问题:
// 建议将输入获取与JDBC操作分离,此处为示例整合写法 PreparedStatement createStudDetails(Connection conn) throws SQLException { Scanner sc = new Scanner(System.in); System.out.println("Enter name:"); String name = sc.nextLine(); System.out.println("Enter enrl:"); long enrl = sc.nextLong(); sc.nextLine(); System.out.println("Enter department:"); String dept = sc.nextLine(); System.out.println("Enter mobile no:"); String mono = sc.nextLine(); System.out.println("Enter mail:"); String mail = sc.nextLine(); // 用?作为参数占位符,字段名用反引号包裹 String sql = "Insert into stud_details(`First Name`,`Enrol no`,`Department`,`Mobile No`,`Email`) values(?,?,?,?,?)"; PreparedStatement pstmt = conn.prepareStatement(sql); // 按顺序设置参数 pstmt.setString(1, name); pstmt.setLong(2, enrl); pstmt.setString(3, dept); pstmt.setString(4, mono); pstmt.setString(5, mail); return pstmt; } // 主类调用示例(需先获取数据库连接) // Connection conn = DriverManager.getConnection("url", "user", "password"); // PreparedStatement pstmt = createStudDetails(conn); // pstmt.executeUpdate(); // 执行插入操作 // pstmt.close(); // conn.close();
参数化查询是Java操作数据库的标准规范,能自动处理字符串引号、特殊字符转义等问题,同时从根源上避免SQL注入攻击。
内容的提问来源于stack exchange,提问作者Effie
相关产品推荐
相关产品推荐

