必须用参数化查询,其他所有字符串拼接方案都不可靠;因单引号会提前截断字符串导致语法错误或注入,而参数化能同时防止解析错误和sql注入,且各语言需严格按规范使用占位符与绑定机制。

必须用参数化查询,其他所有字符串拼接方案都不可靠。 单引号本身不是问题,问题是它会提前截断字符串字面量,导致语法错误或SQL注入——而只有参数化能同时拦住这两类风险。
为什么直接拼接 'O'Reilly' 会报错
SQL解析器把第一个 ' 当作字符串起始,第二个 ' 当作结束,Reilly' 就成了孤立的非法token。典型错误是 ERROR: unterminated quoted string 或类似提示。这不是数据脏,是语法结构崩了。
- 手动替换
'为''(双单引号)仅解决字面量闭合问题,但漏掉分号、--、/*等注入点 - 用
\'在 PostgreSQL 默认配置下直接报错;MySQL 虽支持,但依赖sql_mode设置,跨环境极易失效 - JSON 字段、日志模板、嵌套SQL等场景中,多层转义极易漏掉某一层
各语言参数化查询怎么写才不踩坑
不同驱动对占位符和类型绑定的要求差异很大,写错就退化成裸拼。
- Java JDBC:用
?占位 +PreparedStatement.setString(1, userInput),别用addBatch混用字符串拼接 - Python psycopg2:必须用
%s占位 +cursor.execute("...", [userInput]),f"WHERE name = '{userInput}'"是高危操作 - SQL Server / C#:命名参数用
@name,但必须显式指定类型如SqlDbType.NVarChar,否则隐式转换可能失败 - Oracle:只认
?,不认:name(那是PL/SQL块里的绑定变量) - Django ORM 的
filter(name__contains=...)自动参数化,但extra()或raw()仍需手动处理
实在要拼字符串时,'' 是唯一可接受的转义形式
仅限完全可控场景:比如生成静态DDL脚本、调试日志、数据库内建函数调用(如 QUOTE()),且必须满足三个硬约束。
- 只用于字符串字面量,绝不能用于表名、列名(那些该用双引号或方括号)
- 严格按 SQL 标准:每个
'替换为'',不是\',也不是" - MySQL 可用
QUOTE('O''Reilly')辅助生成,但这是服务端函数,不能替代应用层参数化
真正难的从来不是怎么转义单引号,而是你根本不确定输入是否被前端、网关、中间件、日志系统反复解析过——这种边界模糊的链路里,只有参数化查询能守住最后一道防线。










