SQL中单引号报错本质是字符串未闭合,而非字符非法;正确写法为用两个单引号表示一个字面量单引号,如'O''Reilly',该标准被MySQL、PostgreSQL、SQL Server、Oracle等全部支持,且应优先使用参数化查询避免拼接风险。

SQL INSERT中单引号报错:不是语法错,是配对失败
直接拼接 INSERT INTO users (name) VALUES ('O'Reilly') 会报错,不是因为数据库不支持单引号,而是 SQL 解析器把 'O' 当成字符串开头,遇到下一个 ' 就认为字符串结束,后面 Reilly') 变成非法语法。本质是引号没闭合,不是“字符非法”。
正确做法是用两个单引号表示一个字面量单引号:'O''Reilly'。SQL 标准规定,连续两个 ' 被解析为单个字符 ',不是转义符,也不是字符串连接。
- MySQL、PostgreSQL、SQL Server、Oracle 全部支持该写法
- 不要用反斜杠
'—— MySQL 默认禁用该行为(除非启用了NO_BACKSLASH_ESCAPES模式) - 双引号
"O'Reilly"在绝大多数数据库里是标识符(列名/表名)语法,不是字符串,会直接报错
批量插入含换行、制表符、反斜杠时数据被截断或变形
换行符
、制表符 、反斜杠 本身在 SQL 字符串中合法,但问题常出在「谁先处理它们」:
- Python 中用
cursor.execute("INSERT ... VALUES ('" + user_input + "')"):Python 先解析成换行,再拼进 SQL,结果可能多出一行导致语法错误 - psql 命令行里写
INSERT INTO log(msg) VALUES ('line1 line2');:如果 shell 或 psql 自身做了预处理,可能被丢弃或转义 - 反斜杠在字符串里要双重转义:想存
C:Windows,得写'C:\Windows'(否则W被当无效转义)
根本解法:一律走参数化查询。例如 PostgreSQL + psycopg2:cursor.execute("INSERT INTO log(msg) VALUES (%s)", [user_input]),所有字符原样交给数据库引擎处理,不经过客户端字符串解析。
Oracle 中 & 符号执行时报“请输入变量值”
Oracle 把 & 当作变量占位符,不是字符串内容。执行 INSERT INTO dept(name) VALUES ('R&D') 时,Oracle 会停住,提示你输入变量 R 的值。
有三种可靠解法:
- 用字符串拼接:
INSERT INTO dept(name) VALUES ('R'||'&'||'D') - 用
CHR(38)替代:INSERT INTO dept(name) VALUES ('R'||CHR(38)||'D') - 临时关闭变量替换:
SET DEFINE OFF;(仅限 SQL*Plus / SQL Developer CLI 场景,不适用于 JDBC 或其他驱动)
注意:SET DEFINE OFF 对 JDBC 连接无效,Java 应用里必须用前两种方式之一。
用 AddNew 或存储过程写入时为什么不用处理单引号
ADO Recordset 的 AddNew 方法、SQL Server 存储过程参数、JDBC PreparedStatement 都绕过了 SQL 文本拼接阶段。数据以二进制或绑定参数形式传入,数据库驱动负责底层编码和类型适配,单引号、&、