You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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从根源上避免了这种风险。

结合你的代码流程

再梳理下你代码的实际执行结果:

  1. 第一次调用pStmt.setInt(1, 35)并执行:John的薪资从45000变成90000。
  2. 第二次调用pStmt.setString(1, "35 OR Salary<100000")并执行:因为参数是字符串,无法匹配整数类型的PNR,所以没有任何记录被更新。

内容的提问来源于stack exchange,提问作者noobcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:42:59