在大小写严格敏感的数据库(如达梦case_sensitive=1、postgresql、snowflake)中,不加引号的标识符会被引擎强制转换为默认大小写(达梦转大写、postgresql转小写),若建表时使用双引号定义大小写混合名(如"user_info"或"userinfo"),则后续所有引用必须完全一致加双引号,否则报“对象不存在”;唯一跨库兼容方案是统一用小写字母加下划线命名且全程不加引号。

直接说结论:在大小写严格敏感的数据库(如达梦 CASE_SENSITIVE=1、PostgreSQL、Snowflake)里,不加引号的标识符会出错,加错引号或漏加引号更会出错。这不是SQL写得“不够规范”的问题,而是引擎解析规则本身决定的——它根本不会帮你做大小写归一。
达梦数据库中表名/列名大小写不匹配就报“对象不存在”
达梦默认 CASE_SENSITIVE=1,未加双引号的 SELECT * FROM user_info 实际查的是 USER_INFO;如果你建表时用的是 CREATE TABLE "user_info"(带双引号),那必须用 SELECT * FROM "user_info" 才能命中。
- 查当前设置:
SELECT CASE_SENSITIVE();—— 返回1就是敏感模式 - 建表时不加引号 → 存为大写 → 后续所有引用都必须大写,或不加引号(自动转大写)
- 建表时加了
"UserInfo"→ 必须全程用"UserInfo",哪怕只差一个字母大小写都会失败 - 迁移脚本里混用大小写(比如 MySQL 导出的
user_info直接扔到达梦)大概率报对象不存在
PostgreSQL里不加引号等于强制小写
PostgreSQL 解析器会在语法分析阶段把所有没引号的标识符转成小写,所以 CREATE TABLE User 实际建出来的是 user 表,SELECT * FROM User 能查到,但 SELECT * FROM "User" 就找不到——因为后者找的是严格叫 User 的表。
- ORM 自动生成的 SQL 如果带双引号(比如 Django 的
"auth_user"),而你本地开发用的是小写建表,生产就会挂 -
pg_dump默认导出带双引号的标识符,直接还原可能和原始建表语句不一致 - 字段别名也受此影响:
SELECT name AS "UserName" FROM users,后续ORDER BY "UserName"没问题,但ORDER BY UserName会被转成username,报错
字符串值比较别依赖 UPPER/LOWER 做条件过滤
在达梦或 PostgreSQL 中,WHERE UPPER(name) = UPPER('Alice') 看似能绕过大小写问题,但实际埋了三个雷:
- 索引失效:除非你提前建了函数索引(如
CREATE INDEX idx_upper_name ON t (UPPER(name))),否则必走全表扫描 - 校对规则冲突:如果字段用了
_cs或BINARYcollation,UPPER()可能直接报错或返回空 - 中文/数字无效:达梦里
UPPER('张三')还是张三,只对 ASCII 字母生效,业务逻辑容易误判
跨数据库迁移时最保险的命名实践
不是“建议用小写”,而是“必须统一用小写 + 下划线,且全程不加任何引号”。这是唯一能同时兼容 MySQL(lower_case_table_names=1)、PostgreSQL(自动转小写)、达梦(CASE_SENSITIVE=0 时也认小写)、Snowflake(小写无需引号)的方案。
- 表名写成
order_detail,不是OrderDetail或"order_detail" - 字段名同理:
created_at,不是createdAt或"created_at" - 一旦用了双引号,就必须在所有 DML、DCL、索引定义、视图、存储过程中保持完全一致——连空格都不能多一个
- CI/CD 流水线里加个检查脚本,grep 出所有
"[A-Z]或`,比事后 debug 强十倍
真正麻烦的不是“怎么写对”,而是“怎么让所有人持续写对”——引号、大小写、下划线,这些细节在单人开发时无所谓,一旦进到团队协作或跨环境部署,就是最常被忽略、又最难排查的硬伤。











