数据库内表名及字段名的特殊符号支持哪些
数据库内表名及字段名的特殊符号支持哪些,关键不在“这个符号能不能出现”,而在“是否使用了数据库认可的定界符”。跨库最稳妥的命名是小写字母、数字和下划线,并且不要以数字开头,例如 user_profile、order_item_id。连字符 -、空格、点号 .、括号、中文、保留字、$、#、@ 等在不少数据库中可以通过反引号、双引号或方括号使用,但会增加 SQL 书写、ORM 映射、迁移、备份恢复和报表工具的成本。生产库若没有强业务原因,建议统一使用 snake_case;必须使用特殊符号时,要按当前数据库的引用规则固定写法,并在所有查询、迁移脚本和工具配置中保持一致。
先判断:普通标识符还是定界标识符
表名、字段名、索引名、视图名等都属于数据库标识符。普通标识符是不加任何引用符就能直接写进 SQL 的名称,例如 user_order;定界标识符是用数据库指定符号包起来的名称,例如 MySQL 的 `order-detail`、PostgreSQL 的 "order-detail"、SQL Server 的 [order-detail]。
可执行信息:建表前先用目标数据库执行一条最小 SQL:CREATE TABLE、INSERT、SELECT、ALTER TABLE 各跑一次,确认创建、查询、改名、导出都能正常识别。判断标准:如果名称包含空格、连字符、点号、括号、运算符、保留字或大小写敏感写法,就按“需要定界符”处理。场景差异:单库内部系统可控性高,可以接受少量特殊符号;多数据库兼容、SaaS、数据中台、BI 报表和 ORM 项目应尽量不用。注意事项:定界符不是装饰,一旦创建了带特殊符号或大小写敏感的名称,后续每一次引用都可能必须按原样书写。
常见特殊符号支持结论
符号或字符
通常是否可用于表名/字段名
判断和用法
注意事项
_ 下划线
推荐使用
多数数据库普通标识符直接支持,适合分隔单词。
跨库命名首选,例如 created_at。
- 连字符
可用但通常要引用
未引用时常被解析为减号,例如 order-detail 可能被当成表达式。
不建议常规表结构使用;必须用时每次查询都要加定界符。
. 点号
可用但强烈不建议
SQL 中点号通常用于 schema.table.column 分隔。
如果点号是名称的一部分,必须引用单个组件,例如 "order.detail"。
空格
可用但必须引用
例如 "unit price" 或 [unit price]。
报表列别名可以用空格,真实字段名不建议用。
() 圆括号
部分数据库引用后可用
未引用时用于函数调用、表达式分组或语法结构。
字段名里出现括号会降低可读性,也容易影响生成 SQL 的工具。
[] 方括号
SQL Server/SQLite 常见
SQL Server 中 [name] 是定界标识符。
MySQL、PostgreSQL、Oracle 不把方括号作为通用标识符引用方式。
$
部分支持
MySQL、PostgreSQL、Oracle、SQL Server 对 $ 的规则不同。
跨库项目避免使用;MySQL 新版本不建议未引用名称以 $ 开头。
#
部分支持
SQL Server 中 # 开头常表示临时表。
不要把 SQL Server 普通业务表命名为 #xxx,语义会混乱。
@
谨慎使用
SQL Server 中 @ 常用于变量或参数。
字段名、表名中使用 @ 会影响可读性和工具识别。
中文或其他非拉丁字符
很多数据库支持
需要看字符集、排序规则、驱动和工具链。
内部数据字典可接受;面向多语言研发、迁移和接口输出时不建议。
保留字
引用后通常可用
例如 "select"、`order`、[user]。
能避开就避开,保留字最容易造成迁移和兼容问题。
可执行信息:优先选择 ^[a-z][a-z0-9_]*$ 这类规则作为团队建表校验。判断标准:只要符号在 SQL 中本身有语法含义,就不要把它当成普通命名字符。场景差异:列别名可以更灵活,真实表名和字段名应更保守。注意事项:不要把“某个数据库能创建成功”误认为“所有工具都能稳定使用”。
主流数据库差异对照
数据库
普通标识符常见规则
特殊符号引用方式
关键注意事项
MySQL
未引用标识符通常支持字母、数字、下划线、美元符号及部分 Unicode 字符。
使用反引号:`order-detail`;启用 ANSI_QUOTES 后也可用双引号。
表名大小写可能受操作系统和 lower_case_table_names 影响;库名、表名、列名不能以空格结尾。
PostgreSQL
普通名称以字母或下划线开头,后续可包含字母、数字、下划线、美元符号。
使用双引号:"order-detail"。
未引用名称会按小写处理;双引号名称区分大小写,"User" 和 user 不是同一种写法。
Oracle
未引用名称以字母开头,后续可包含字母、数字、下划线、美元符号、井号。
使用双引号:"order-detail"。
未引用名称通常按大写存储;Oracle 不推荐滥用 quoted identifier,并应避免 SYS_、ORA_ 前缀。
SQL Server
普通名称可包含字母、数字、下划线、@、#、$ 等,但开头符号有特殊语义。
使用方括号或双引号:[order-detail]、"order-detail"。
@ 常表示变量,# 常表示临时对象;双引号受 QUOTED_IDENTIFIER 设置影响,方括号更常用。
SQLite
规则较宽松,对关键字也有兼容处理。
标准方式是双引号,也兼容方括号和反引号。
不要依赖 SQLite 的宽松兼容行为;未来迁移到 MySQL、PostgreSQL 或 SQL Server 时可能失败。
可执行信息:如果项目可能换库,直接按 PostgreSQL/标准 SQL 更保守的规则设计:小写、下划线、不用保留字。判断标准:一个名称如果必须依赖某个数据库独有引用符才可用,就不适合作为跨库公共模型名称。场景差异:SQL Server 老项目常见方括号,MySQL 老项目常见反引号,PostgreSQL 和 Oracle 常见双引号。注意事项:迁移时不要只替换引用符,还要检查大小写折叠、保留字列表、最大长度和工具生成 SQL 的规则。
点号、连字符和空格最容易出错
点号、连字符和空格是用户最常问的三类特殊符号,也是最容易让 SQL 解析器误判的符号。点号通常表示层级限定,连字符通常表示减法,空格通常表示 token 分隔。它们并非完全不能用,而是必须引用,并且要清楚引用的是“整个名称”还是“名称的一部分”。
-- PostgreSQL:点号是表名的一部分
SELECT "unit-price"
FROM "sales"."order.detail";
-- MySQL:每个组件分别引用
SELECT `unit-price`
FROM `sales-db`.`order.detail`;
-- SQL Server:方括号引用特殊字段名
SELECT [unit price]
FROM [sales].[order.detail];
可执行信息:凡是名称里有 .、-、空格,统一在建表阶段评审,不允许随手创建。判断标准:如果一个新同事看到名称后不能马上判断它是表路径、表达式还是字段名,就应该改名。场景差异:导入 Excel 或第三方 API 字段时,可先建临时落地表保留原字段,再清洗到规范字段。注意事项:不要把 sales.order.total 当成一个字段名,这会和 schema、table、column 的限定写法冲突。
生产命名建议
生产数据库的命名目标不是“尽量炫技”,而是让 SQL 可读、工具可识别、迁移可预测。推荐规则是:表名和字段名只使用小写字母、数字、下划线;以字母开头;不使用数据库保留字;不使用连续下划线;长度控制在 30 到 60 个字符内;布尔字段使用清晰前缀,如 is_deleted、has_paid;时间字段统一使用 created_at、updated_at。
可执行信息:把命名规则写进 migration lint、代码评审清单或数据库建模工具校验中。判断标准:名称应能直接表达业务含义,例如 payment_status 比 p-status 更适合长期维护。场景差异:OLTP 业务库更强调稳定和兼容;临时分析表可适度宽松,但也应在入仓后规范化。注意事项:不要因为前端展示需要就把数据库字段命名成 Order Amount ($),展示名称应交给报表层、接口层或数据字典处理。
ORM、迁移和动态 SQL 的处理
带特殊符号的表名和字段名会放大 ORM 和动态 SQL 的风险。很多 ORM 默认假设字段名是普通标识符,如果模型字段叫 order-detail 或 unit price,就需要额外配置列名映射。动态 SQL 更不能用普通字符串拼接标识符,否则既容易语法错误,也可能引入 SQL 注入风险。
可执行信息:需要动态拼接表名或字段名时,使用数据库驱动或框架提供的 identifier quote 能力,例如 SQL Server 的 QUOTENAME、查询构造器的列名包装函数,或 ORM 的显式列映射。判断标准:参数值可以用 bind parameter,表名和字段名不能当普通值参数处理,必须走标识符白名单。场景差异:用户输入生成筛选值时用参数绑定;用户选择排序字段时用后端白名单映射到真实字段名。注意事项:不要允许用户直接提交 ORDER BY 字段名原文,即使只是字段名也可能破坏 SQL 结构。
创建前快速校验清单
名称是否匹配 ^[a-z][a-z0-9_]*$?能匹配则优先使用。
是否包含空格、连字符、点号、括号、斜杠、百分号、引号?包含则默认改名。
是否是数据库保留字,例如 select、order、user、group?是则改名或加业务前后缀。
是否依赖大小写区分?如果依赖,确认所有 SQL 和 ORM 都能稳定输出引用符。
是否会跨 MySQL、PostgreSQL、Oracle、SQL Server、SQLite 迁移?会迁移则禁止使用数据库独有符号规则。
是否只是为了展示好看?如果是,把展示名放到前端、BI、元数据表或接口文档里。
可执行信息:建表脚本合并前跑一次 lint,并在测试库执行完整迁移。判断标准:能不用引用符稳定完成建表、查询、索引、外键、导入导出,就是更好的命名。场景差异:临时表、外部表、数据湖落地表可以保留源字段,但核心业务表应规范化。注意事项:不要只测试 CREATE TABLE 成功,还要测试 ALTER TABLE、备份恢复、数据同步和报表查询。
常见问题
MySQL 表名能不能用中横线?
可以,但要用反引号,例如 CREATE TABLE `order-detail` (...)。不加反引号时,- 容易被解析为减号。生产环境更推荐改成 order_detail。
字段名有空格能不能查?
能查,但每次都要按数据库规则引用,例如 PostgreSQL/Oracle 写 "unit price",SQL Server 写 [unit price],MySQL 写 `unit price`。如果是业务字段,建议改成 unit_price。
PostgreSQL 里为什么建了 “UserName”,查询 username 报错?
因为 PostgreSQL 的未引用名称会按小写处理,而双引号名称保留大小写。创建了 "UserName" 后,查询时也必须写 "UserName"。长期看,建议统一使用 user_name。
点号能放在字段名里吗?
引用后通常可以,例如 "order.total" 或 [order.total]。但点号在 SQL 中主要用于分隔 schema、表和列,真实字段名不建议使用点号,否则阅读和迁移成本都很高。
中文表名和中文字段名适合生产库吗?
技术上很多数据库支持中文标识符,但生产环境要考虑驱动、字符集、排序规则、脚本编码、监控系统和跨团队协作。内部报表库可以谨慎使用;核心业务库、跨系统接口库更建议使用英文小写加下划线。
参考文献
MySQL 8.4 Reference Manual: Schema Object Names
PostgreSQL Documentation: Lexical Structure
Microsoft Learn: Database Identifiers – SQL Server
Oracle Database SQL Language Reference: Database Object Names and Qualifiers
SQLite Documentation: Keywords and Identifier Quoting