
在 Java 中使用 PreparedStatement 时,若手动为参数添加单引号(如 '679223'),会导致 SQL 实际执行为 WHERE segment1 = '''679223''',引发语法错误或匹配失败;正确做法是直接传入原始值,由 JDBC 驱动自动处理转义与类型适配。
在 java 中使用 preparedstatement 时,若手动为参数添加单引号(如 `'679223'`)会导致 sql 实际执行为 `where segment1 = '''679223'''`,引发语法错误或匹配失败;正确做法是直接传入原始值,由 jdbc 驱动自动处理转义与类型适配。
PreparedStatement 的核心优势之一,就是将 SQL 结构与参数值完全分离。当你写:
String query = "SELECT sales_order_id FROM mtl_sales_orders WHERE segment1 = ?"; PreparedStatement stmt = connection.prepareStatement(query); stmt.setString(1, segmentValue); // ✅ 正确:只传纯值
JDBC 驱动会自动将 segmentValue(例如 "679223")以安全、类型兼容的方式嵌入到预编译语句中——对字符串类型,底层会自动加上单引号并处理特殊字符(如撇号、反斜杠),无需、也不应由开发者手动拼接。
而你原来的写法:
String segmentValue = "'" + l_order_number + "'"; // ❌ 错误:人为加引号 stmt.setString(1, segmentValue); // 实际传入的是 "'679223'"
会导致最终执行的 SQL 等效于:
WHERE segment1 = '''679223''' -- 外层引号是 JDBC 加的,内层是你加的 → 字符串字面量变成 '679223'(带引号!)
数据库会尝试匹配字段 segment1 是否字面等于带单引号的字符串 '679223'(即长度为 8 的字符串),而非数值 679223(长度为 6)。这几乎必然导致无结果返回,rs.next() 为 false,进而输出 “No rows found”。
✅ 正确修正方式如下:
String query = "SELECT sales_order_id FROM mtl_sales_orders WHERE segment1 = ?";
PreparedStatement stmt = connection.prepareStatement(query);
// 直接传入原始字符串值(不加引号!)
String segmentValue = String.valueOf(l_order_number); // 或直接用 l_order_number(若为 String)
stmt.setString(1, segmentValue);
ResultSet rs = stmt.executeQuery();
if (rs.next()) { // ✅ 推荐用 next() 判断是否存在首行,isBeforeFirst() 不适用于判断结果集是否为空
long salesOrderId = rs.getLong("sales_order_id");
System.out.println("sales_order_id: " + salesOrderId);
} else {
System.out.println("No rows found for segment1 = " + segmentValue);
}
? 关键注意事项:
- PreparedStatement 的 setXxx() 方法(如 setString, setLong)已内置 SQL 注入防护和类型转换逻辑,绝不要手动拼接 SQL 特殊符号(引号、括号、分号等);
- rs.isBeforeFirst() 仅表示游标位置,并非结果集非空的可靠判断方式;应始终用 rs.next() 检查是否有数据;
- 若 l_order_number 是 long/int 类型,也可直接用 setLong(1, l_order_number),语义更清晰且避免隐式转换风险;
- 建议启用 JDBC 日志(如 HikariCP 的 logStatements=true 或数据库驱动 trace)验证实际执行的 SQL,便于快速定位绑定问题。
遵循这一原则,不仅能解决当前查询为空的问题,更能保障代码安全性与可维护性。











