Prepared Statement 预编译语句

先把 SQL 语句的结构传给数据库编译,再把用户输入作为参数填进去的编码技术。数据库知道”这是结构,那是数据”,不会把数据当代码执行 —— 这就堵死了 SQL injection

拼字符串 vs Prepared Statement

危险写法(拼字符串):

"SELECT * FROM users WHERE name = '" + userInput + "'"

用户输入 ' OR '1'='1 就完蛋。

安全写法(prepared statement):

SELECT * FROM users WHERE name = ?

然后单独传 userInput 作为参数。数据库永远把 ? 当数据,不当代码。

为啥这是 SQL Injection 的克星

SQL injection 的本质是”用户输入被当成代码执行”。Prepared statement 在协议层就把代码和数据分开了 —— 不是过滤、不是转义,而是结构上不可能被注入。

主流语言里的写法

语言/框架API
PHPPDO prepare() + execute()
Pythoncursor.execute(sql, params)
JavaPreparedStatement
Node.jsmysql2? 占位符
Godb.Query(sql, args...)

注意

  • ORM(如 SQLAlchemy、Prisma)底层都是 prepared statement,但字符串拼接绕过 ORM 一样危险
  • Table name、column name 不能参数化,需要白名单校验

跟输入验证(input validation)配合使用,纵深防御