MySQL 的 COMMENT '说明' 会把文字存进表定义里,SHOW FULL COLUMNS 能看到,
information_schema.columns 也能查。
本沙箱把它吞进了类型名:id INT COMMENT '编号' 的 type 就是 INT COMMENT '编号'。
不报错,也不是注释。
SQL 里的 -- 和 /* */ 是另一种东西:给读语句的人看的,执行时就丢掉,不进表结构。
前面八个属性都真的拦数据,这一篇讲唯一一个「只管说明」的。 它最值得学的地方不是语法,是那个现象: 一个语法在某个引擎里「能跑」,不代表它有你以为的那个效果。 这种静默失败在前面已经出现过两次了。
一、MySQL 写 COMMENT,这里被吞进类型名
CREATE TABLE 表 (列 类型 COMMENT '说明'),MySQL 会把这段文字存进表定义里,
SHOW FULL COLUMNS FROM 表 能看到。
本沙箱里这句不报错,但 PRAGMA table_info 的 type 列写的是 INT COMMENT '编号'。
注释被当成了类型名的一部分,一句提醒都没有。
它既没报错,也没变成注释。 这是本篇最该记住的一处:
一个语法在这个引擎里「能跑」,不代表它有你以为的那个效果。
判断办法只有一个——去查它的元数据,看它到底被存成了什么。
二、注释不是元数据,查不出来
MySQL 的注释存在 information_schema.columns 的 column_comment 里,
可以查、可以导出成数据字典,甚至能用它做「找出所有没写注释的列」这种巡检。
SQLite 没有这个机制:建表语句里塞什么,它就原样存进 sqlite_master 的 sql 列,
没有任何地方能「单独取出注释」。 想拿到只能去解析那句建表语句的字符串,非常不可靠。
三、SQL 里的注释是另一种东西
-- 这是单行注释 和 /* 这是块注释 */ 是给读语句的人看的,执行时被丢掉。
它们不会存进表结构,重启就没了。
所以别拿它们当列说明:
写在建表脚本里的 -- 用户手机号,在数据库里查不到。 要看的人得去翻那个脚本文件。
但它们有一个注释做不到的好处:
可以写多行、可以写「为什么这么设计」的来龙去脉。
实际的建表脚本里,一个复杂的表前面常常有十几行块注释。
四、没有注释功能时怎么替代
一是靠列名。 created_at、is_deleted、
order_no 这种名字本身就说明白了,比注释还管用——
注释会被复制粘贴带走,列名不会。 改列名时全项目都会报错,改注释时没人知道。
二是建一张数据字典表:table_name、column_name、comment 三列,
自己维护一份说明,需要时连表查出来。
这是很多团队的通行做法,尤其是字段多、跨团队协作的时候。
三是把说明写进代码仓库的文档里,
跟建表脚本放一起,改表就改文档。 缺点是容易和实际结构脱节,得靠评审盯着。
一个实用的小办法是:把「新增列必须同时更新文档」写进提交检查。
五、注释的真实用途
一是给「名字说明不了的东西」补充:status 这一列存 0/1/2 各是什么意思,
不写下来没人知道,写了新人少问十次。
二是留「为什么这么设计」的线索:
amount 为什么是整数?因为存的是「分」不是「元」。
这种信息代码里看不出来,注释里一句话省掉一堆猜测。
三是标明单位和口径:
长度是毫米还是厘米、时间是本地还是 UTC、金额含不含税——
这三样不清不楚,是数据出错最常见的来源。 尤其是「金额含不含税」,一个歧义能让报表全错。
六、动手 Demo:撞一次 COMMENT,看它到底被存成了什么
Demo 四段:用 MySQL 的 COMMENT 写法建一张表、用 PRAGMA 看它被存成了什么、讲 SQL 注释的区别、
最后给三种替代做法。
第二段那张表是全篇的重点——type 那一列会告诉你真相。
import _q46 as Q
c = Q.blank()
# MySQL 的写法:这里不报错,但注释被吞进了类型名
Q.run(c, "CREATE TABLE demo_cm (id INT COMMENT '编号', name TEXT)")
Q.show(c, "PRAGMA table_info(demo_cm)")
# SQL 注释是另一回事:执行时就被丢掉,不进表结构
# -- 这是单行注释
# /* 这是块注释 */
实跑输出:
--------------------------------------------------------------------
第五十课:注释——写给人看的那一个属性
--------------------------------------------------------------------
MySQL 写 COMMENT
**`CREATE TABLE 表 (列 类型 COMMENT '说明')`**,**MySQL 会把这段文字存进表定义里**,
`SHOW FULL COLUMNS FROM 表` 能看到。
SQL> CREATE TABLE demo_cm (id INT COMMENT '编号', name TEXT)
完成
SQL> PRAGMA table_info(demo_cm)
cid name type notnull dflt_value pk
------------------------------------------------------------------------------
0 id INT COMMENT '编号' 0 NULL 0
1 name TEXT 0 NULL 0
(2 行)
**看 `type` 那一列:`INT COMMENT '编号'`。** **注释被当成了类型名的一部分,一句提醒都没有。**
**它既没报错,也没变成注释。**
**这是本篇最该记住的一处:一个语法在这个引擎里「能跑」,不代表它有你以为的那个效果。**
注释不是元数据,查不出来
**MySQL 的注释存在 `information_schema.columns` 的 `column_comment` 里**,
**可以查、可以导出成数据字典。**
**SQLite 没有这个机制**:**建表语句里塞什么,它就原样存进 `sqlite_master` 的 `sql` 列**,
**没有任何地方能「单独取出注释」。**
SQL 里的注释是另一种东西
**`-- 这是单行注释`** 和 `/* 这是块注释 */` **是给读语句的人看的,执行时被丢掉。**
**它们不会存进表结构,重启就没了。**
**所以别拿它们当列说明**:
**写在建表脚本里的 `-- 用户手机号`,在数据库里查不到。** **要看的人得去翻那个脚本文件。**
没有注释功能时怎么替代
**一是靠列名**:`created_at`、`is_deleted`、
`order_no` **这种名字本身就说明白了,比注释还管用**——**注释会被复制粘贴带走,列名不会。**
**二是建一张数据字典表**:`table_name`、`column_name`、`comment` 三列,
**自己维护一份说明,需要时连表查出来。**
**这是很多团队的通行做法,尤其是字段多、跨团队协作的时候。**
**三是把说明写进代码仓库的文档里**,
**跟建表脚本放一起,改表就改文档。** **缺点是容易和实际结构脱节,得靠评审盯着。**
注释的真实用途
**一是给「名字说明不了的东西」补充**:`status` 这一列存 0/1/2 各是什么意思,
**不写下来没人知道,写了新人少问十次。**
**二是留「为什么这么设计」的线索**:
**`amount` 为什么是整数?因为存的是「分」不是「元」。**
**这种信息代码里看不出来,注释里一句话省掉一堆猜测。**
**三是标明单位和口径**:
**长度是毫米还是厘米、时间是本地还是 UTC、金额含不含税**——
**这三样不清不楚,是数据出错最常见的来源。**
第一段建表成功,一点报错都没有。
第二段 type 显示 INT COMMENT '编号'——注释被当成了类型名的一部分。
后面三段没有 SQL,讲的是 information_schema 里的注释、SQL 注释与列注释的区别,
以及三种替代做法。
30 秒实验
id INT COMMENT '编号'在这边建表为什么不报错?它实际被存成了什么?-- 用户手机号这行注释写进建表脚本,能在数据库里查到吗?为什么?- 没有列注释功能时,你最该优先靠什么?为什么它比注释可靠?
常见误区
- 以为不报错就是生效了。 注释被吞进类型名,看着一切正常,实际什么都没存成注释。
- 拿 SQL 注释当列说明。
--执行时就被丢掉,数据库里根本查不到,改表的人看不到。 - 注释写了三年不更新。 结构改了注释没改,比没注释更误导人。注释也要跟着改。
自测三问(点开对答案)
1. 本沙箱里 `COMMENT` 会怎样? —— 不报错,但被当成类型名的一部分存进 `type` 列,并没有变成注释。 2. `--` 注释和列注释差在哪? —— `--` 是给读语句的人看的,执行时就丢掉;列注释是存在表定义里的元数据,可以查出来。 3. 没有列注释功能,最该优先靠什么? —— 列名。列名改不动、会被全项目引用,比注释可靠得多。九个属性都过完了,最后一篇讲「表已经建好了、怎么补上这些约束」:9.10 操作已有的表。
- ☐ (本篇完,下一篇 9.10 操作已有的表)