MySQL单行注释#无需空格,--必须后跟空格;跨库兼容优先用--(带空格);多行注释/.../可插语句中间但不可嵌套;客户端、ORM或代理可能剥离注释导致“失效”。

单行注释用 # 还是 --?关键看空格和兼容性
MySQL 支持两种单行注释语法,但行为细节有差异:# 是 MySQL 特有,-- 是 SQL 标准(但 MySQL 要求其后必须跟一个空格,否则会被忽略)。
-
#后面直接写注释,无需空格:例如#查询商品ID和采购价 -
--后**必须加空格**,否则整条语句可能报错或被截断:正确写法是-- 查询商品ID和采购价;错误写法如--查询商品ID和采购价在某些客户端(如老版本 mysql CLI 或部分 ORM)会触发语法错误 - 如果要写跨数据库兼容的 SQL(比如将来迁移到 PostgreSQL 或 SQL Server),优先用
--(带空格),避免用#
多行注释 /* ... */ 可以嵌套在语句中间,但不能嵌套自身
/* */ 注释最实用的地方是「插在语句中间」,比如临时屏蔽某字段、加说明,或者调试时注释掉条件片段。
- 支持跨行,换行符不影响解析:
SELECT product_id, /* purchase_price, -- 暂不查采购价 */ sale_price FROM Product; - 不能嵌套:写
/* 外层 /* 内层 */ 外层 */会导致语法错误——MySQL 只认第一个*/就结束注释,后面内容变成裸 SQL,大概率报错 - 可在任意位置插入,包括字段名后、逗号后、
WHERE子句中:WHERE status = 'active' /* and deleted = 0 */
注释能放哪儿?哪些地方容易“静默失效”
理论上注释可出现在 SQL 任意位置,但实际执行中几个常见“失效点”值得警惕:
- 在
DELIMITER改变后、存储过程体内部,某些客户端(如 phpMyAdmin)对#注释解析不稳定,建议统一用--或/* */ - 在命令行工具(
mysql -e "...")中传入含换行的/* */注释,需确保 shell 正确转义,否则换行被截断导致注释不闭合 - ORM(如 SQLAlchemy、MyBatis)可能预处理 SQL,自动剥离注释——这时你写的
--或/* */在真正发给 MySQL 前就被删了,调试时别只信日志里看到的语句 - 注释里的特殊字符(如
*/出现在字符串值中)不会被识别为注释结束,安全;但若动态拼接 SQL,得防注入伪造*/提前闭合注释
为什么注释有时“看不见效果”?其实是客户端或协议层拦截了
不是所有环境都原样把注释发给 MySQL 服务端。比如:
- MySQL 8.0+ 的
performance_schema.events_statements_history默认不记录注释,查慢日志或审计日志时会发现注释“消失”了 - 某些连接池(如 HikariCP)或代理(如 ProxySQL)会做 SQL 归一化(normalization),把注释全去掉再路由,方便缓存匹配
- 如果你在 Navicat / DBeaver 中写了注释却没生效,先试试切换到原生
mysqlCLI 执行——排除 GUI 工具的预处理干扰
注释看着简单,但混在复杂查询、自动化流程或多人协作脚本里时,-- 少打的那个空格、/ 忘写的那个 /、或者 ORM 里以为留着的调试注释,都可能变成半夜排查的起点。










