Prepared Statement防SQL注入效果及特定参数执行结果问询
关于DB2 JDBC PreparedStatement参数注入的疑问解答
放心,这种情况不会导致所有记录的薪资被翻倍,这正是PreparedStatement设计用来避免SQL注入问题的核心特性所在。
核心原理说明
PreparedStatement采用预编译+参数绑定的机制:
- 当你调用
con.prepareStatement("UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=?")时,数据库会先解析这个SQL模板,把?当作纯粹的参数占位符,而非SQL语句的一部分。 - 后续调用
setString(1, "35 OR Salary<100000")时,数据库会把这个字符串当作单一的字面量值处理,不会解析其中的SQL语法(比如OR关键字)。
实际执行的逻辑
你第二次执行的SQL等价于:
UPDATE PERS SET Salary=Salary*2.0 WHERE PNR='35 OR Salary<100000'
而你的数据表中PNR是整数类型(示例里的34、35都是整数),这个字符串无法匹配任何PNR值,所以这次executeUpdate()不会修改任何记录——连John的薪资都不会被第二次更新。
反例:如果用字符串拼接SQL会怎样?
如果是用普通Statement拼接SQL的写法:
String sql = "UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=" + args[0]; Statement stmt = con.createStatement(); stmt.executeUpdate(sql);
当args[0]是"35 OR Salary<100000"时,实际执行的SQL就会变成:
UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=35 OR Salary<100000
这时候才会触发批量更新:所有薪资低于10万的记录(也就是示例里的Tim和John)都会被翻倍。但PreparedStatement从根源上避免了这种风险。
结合你的代码流程
再梳理下你代码的实际执行结果:
- 第一次调用
pStmt.setInt(1, 35)并执行:John的薪资从45000变成90000。 - 第二次调用
pStmt.setString(1, "35 OR Salary<100000")并执行:因为参数是字符串,无法匹配整数类型的PNR,所以没有任何记录被更新。
内容的提问来源于stack exchange,提问作者noobcoder
相关产品推荐
相关产品推荐

