🦏 第9章 列的属性
📄 一句话概括

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 秒实验

  1. id INT COMMENT '编号' 在这边建表为什么不报错?它实际被存成了什么?
  2. -- 用户手机号 这行注释写进建表脚本,能在数据库里查到吗?为什么?
  3. 没有列注释功能时,你最该优先靠什么?为什么它比注释可靠?

常见误区

  1. 以为不报错就是生效了。 注释被吞进类型名,看着一切正常,实际什么都没存成注释。
  2. 拿 SQL 注释当列说明。 -- 执行时就被丢掉,数据库里根本查不到,改表的人看不到。
  3. 注释写了三年不更新。 结构改了注释没改,比没注释更误导人。注释也要跟着改。
自测三问(点开对答案) 1. 本沙箱里 `COMMENT` 会怎样? —— 不报错,但被当成类型名的一部分存进 `type` 列,并没有变成注释。 2. `--` 注释和列注释差在哪? —— `--` 是给读语句的人看的,执行时就丢掉;列注释是存在表定义里的元数据,可以查出来。 3. 没有列注释功能,最该优先靠什么? —— 列名。列名改不动、会被全项目引用,比注释可靠得多。

九个属性都过完了,最后一篇讲「表已经建好了、怎么补上这些约束」:9.10 操作已有的表。

相关笔记