最稳妥的做法是用两个单引号连续表示一个字面单引号,这是sql标准写法,所有主流数据库均支持;批量插入应使用参数化查询避免拼接;json字段中单引号无需特殊转义,但双引号需按json规则用反斜杠转义。

SQL插入单引号时直接报错怎么办
单引号在SQL里是字符串边界符,遇到 'O'Reilly' 这种数据,不处理就会被解析成 'O' + Reilly',导致语法错误。最稳妥的做法是**用两个单引号连续表示一个字面单引号**,这是SQL标准写法,所有主流数据库(PostgreSQL、SQL Server、SQLite、Oracle)都支持,MySQL在ANSI模式下也支持。
例如插入用户姓名 O'Reilly,应写成:
INSERT INTO users (name) VALUES ('O''Reilly');
注意不是反斜杠转义,也不是双引号包裹——除非你明确启用了特定SQL模式(如MySQL的ANSI_QUOTES),否则双引号通常用于标识符(如列名),不是字符串字面量。
批量插入含特殊字符(换行、制表符、反斜杠)的数据
换行符(
)、制表符( )、反斜杠()本身在SQL字符串中不会引发语法错误,但会影响数据语义和后续读取。关键在于:这些字符是否被客户端或驱动程序提前解释了?比如用Python的cursor.execute()拼接SQL字符串时,Python会先解析
为换行,再交给数据库;而如果用参数化查询,就完全由数据库引擎处理,更安全。
- ❌ 避免字符串拼接:
"INSERT INTO log(msg) VALUES ('" + user_input + "');"—— 危险且无法正确处理嵌入的'或 - ✅ 必须用参数化查询:
cursor.execute("INSERT INTO log(msg) VALUES (?)", [user_input])(SQLite)或%s占位符(MySQL/PostgreSQL) - ⚠️ 如果非得手写SQL(如psql命令行),需对反斜杠做双重转义:
'C:\Windows\System32'→ 实际存入的是C:WindowsSystem32;而'line1 line2'在多数数据库中会存为带换行的字符串(前提是客户端未过滤)
MySQL里单引号转义为什么有时失效
因为MySQL默认使用NO_BACKSLASH_ESCAPES关闭状态,允许用'转义单引号,但这不是标准SQL,且容易和字符串内真正的反斜杠冲突。一旦服务器启用了NO_BACKSLASH_ESCAPES SQL模式,'就不再被识别为转义,反而变成字面量',导致数据错乱。
所以不要依赖'。统一用标准双单引号写法,或更推荐——
- 开发阶段一律走参数化查询,彻底隔离SQL语法和数据内容
- 运维执行SQL脚本时,用
sed或脚本预处理:把输入中的每个'替换成''(两个单引号) - 检查MySQL当前模式:
SELECT @@sql_mode;,若含NO_BACKSLASH_ESCAPES,就别碰'
JSON字段里嵌套单引号和引号怎么存
当目标字段类型是JSON(如MySQL 5.7+ 的JSON类型、PostgreSQL的jsonb),插入的必须是合法JSON字符串。这意味着:外层SQL字符串用单引号包裹,内层JSON字符串必须用双引号,且单引号无需转义——因为它不在JSON字符串边界上。
例如要存:{"name": "O'Reilly", "desc": "It's "great"!"}
正确写法是:
INSERT INTO api_logs (data) VALUES ('{"name": "O''Reilly", "desc": "It''s \"great\"!"}');
注意两点:JSON内部的双引号必须用转义(因外层SQL用单引号),而JSON内部的单引号可直接写,但若它出现在SQL字符串中,仍要按SQL规则写成''。最稳的方式仍是参数化:把整个JSON对象作为参数传入,由驱动自动处理嵌套转义。
真正容易被忽略的,是不同层级的转义责任归属——SQL解析器管外层字符串边界,JSON解析器管内层结构,二者不能混为一谈。手动拼接时,漏掉任一层都会导致数据损坏或语法错误。











