SQL中单引号必须用两个连续单引号''转义,如'O''Reilly',不可用反斜杠;所有主流数据库均支持该标准写法,动态拼接时应优先使用参数化查询防错防注入。

SQL插入时单引号报错:字符串意外截断或语法错误
直接写 'O'Reilly' 会导致SQL解析失败——单引号被当作字符串边界,中间的 ' 会让引擎以为字符串提前结束了。常见报错如 ERROR: syntax error at or near "Reilly" 或 MySQL 的 You have an error in your SQL syntax。
最稳妥的做法是**用两个单引号连续表示一个字面单引号**(SQL标准),例如:O''Reilly。不是反斜杠、不是双引号,就是重复单引号。
- PostgreSQL、SQL Server、Oracle、SQLite 都严格支持该写法
- MySQL 默认也支持,但需确认
sql_mode不含ANSI_QUOTES(否则双引号才表示字符串) - 不要写成
O\'Reilly—— 这在多数SQL方言中不合法,仅部分客户端(如psql)做预处理,不可靠
使用参数化查询才是根本解法
拼接字符串永远有风险,尤其当内容来自用户输入。哪怕转义正确,也可能因编码、多层解析(如PHP + PDO + MySQL)导致二次注入或乱码。
所有主流语言都有参数化接口,本质是把值和SQL结构分离:
- Python + psycopg2:
cursor.execute("INSERT INTO book(title) VALUES (%s)", ["O'Reilly's Guide"]) - Java + JDBC:
ps.setString(1, "O'Reilly's Guide"); ps.executeUpdate(); - Node.js + pg:
client.query("INSERT INTO book(title) VALUES ($1)", ["O'Reilly's Guide"])
此时你完全不用操心单引号、反斜杠、NULL字节——驱动自动按目标数据库协议编码。
特殊字符如反斜杠、换行符、Unicode怎么办?
单引号只是冰山一角。遇到 \n、\t、中文、emoji(如 ??)甚至控制字符时,单纯双单引号不够用。
关键看三点:
- 数据库字符集是否支持(如MySQL要设
utf8mb4,而非旧的utf8) - 连接层是否声明了对应编码(如JDBC加
?characterEncoding=utf8mb4) - 参数化查询能透传这些字符;手工拼接则必须确保整个SQL语句文本本身也以相同编码保存和传输(比如.py文件存为UTF-8,且没被IDE误转)
示例:插入带换行的地址,用参数化最省心:INSERT INTO user(address) VALUES (?),传入 "Room 101\nBuilding A" 即可,换行符原样入库。
为什么有些教程教用反斜杠转义?
MySQL在旧版本(5.7之前)默认开启 NO_BACKSLASH_ESCAPES 模式以外,允许 'O\'Reilly'。但这属于MySQL特例,且已标记为过时行为。
- PostgreSQL 不认
\',会报错unrecognized escape sequence - SQL Server 启用
QUOTED_IDENTIFIER OFF时才可能接受,但严重不推荐 - 现代ORM(Django、Rails、TypeORM)底层全部走参数化,根本不碰手动转义
依赖反斜杠=绑定MySQL+老配置+无其他数据库迁移需求,实际项目里等于给自己埋兼容性雷。
真正麻烦的从来不是单引号本身,而是混合了用户输入、多层框架、不同数据库和历史配置的上下文——参数化查询把这个问题从“每次都要想怎么转义”变成“只管传值”,这才是值得花五分钟学会的关键动作。

















