MySQL 中文字段名需用反引号包裹,否则报错“Unknown column”;连接须指定 charset='utf8mb4';SQL 值应使用参数化查询避免转义和乱码。
MySQL 中文字段名执行报错:Unknown column '姓名' in 'field list'
mysql 默认不认中文字段名,除非用反引号包裹。不加 ` 就会当成标识符解析失败,尤其在 select、update、order by 里常见。
- 必须写成
SELECT `姓名`, `城市` FROM users,不能写SELECT 姓名, 城市 FROM users - 建表时也得用反引号:
CREATE TABLE t1 (`姓名` VARCHAR(20)) - 如果字段名含空格或连字符(如
user-name),同样逃不掉反引号 - ORM(如 SQLAlchemy)通常自动加反引号,但原生 SQL 拼接时极易漏掉
Python 执行含中文的 SQL:UnicodeEncodeError 或乱码
本质是连接层编码没对齐。即使数据库和表是 utf8mb4,Python 的 mysql-connector 或 pymysql 默认可能走 latin1。
- 连接时显式指定
charset='utf8mb4':conn = pymysql.connect(..., charset='utf8mb4') - 确保 MySQL 服务端配置支持:
character_set_server=utf8mb4,且建库时用CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 避免用字符串拼接中文字段值,改用参数化查询:
cursor.execute("INSERT INTO t1 VALUES (%s)", ("张三",)),否则引号转义容易出错 - 不要手动用
.encode('utf8').decode('gbk')这类“双转”操作,只会放大乱码
SQL 字符串值里有中文单引号或双引号:SyntaxError 或注入风险
不是所有中文标点都危险,但「’」(U+2019)和「"」(U+201D)这类弯引号会被 SQL 解析器直接拒掉;而真正的 ASCII 单引号 ' 必须转义。
- 用户输入含中文引号?先统一替换为 ASCII 引号:
s.replace('‘', "'").replace('’', "'") - 插入前别自己写
.replace("'", "''")—— 不安全也不必要,交给驱动处理 - 参数化查询天然规避转义问题,
WHERE name = %s传"王阿姨's shop"完全没问题 - 如果非得拼字符串(比如动态列名),只对 ASCII 单引号做
.replace("'", "''"),其他 Unicode 字符无需动
PostgreSQL 中文字段名更严格:必须双引号,且大小写敏感
PostgreSQL 把未加引号的标识符全转小写,SELECT 姓名 FROM t 实际查的是 SELECT "姓名" FROM t 还是 SELECT "xingming" FROM t?取决于建表时是否加了双引号。
- 建表时用了
"姓名",后续所有引用都得带双引号:SELECT "姓名" FROM users - 漏掉双引号就变成查小写的
姓名→xingming,报错column "xingming" does not exist - 双引号还会锁死大小写:
"Name"和"name"是两个字段 - pgAdmin 等工具自动生成建表语句常带双引号,复制后执行容易忽略这点











