库 → 表 → 数据,三层。 前七章全在最底下那层转, 这一章上移一层,动「表」本身。
create/alter/drop 是 DDL,insert/update/delete 是 DML。
两类语句脾气完全不同:DDL 多数不能回滚、执行时会锁表、大表上可能锁很久。
改结构前问三句:丢不丢数据?锁不锁表?能不能先在一张副本表上试一遍? 第三句最管用。
第 1~6 章全是「取」,第 7 章是「改数据」。 这一章开始改「装数据的容器」。 这一章的错和上一章不一样:上一章改错了弄丢几行, 这一章改错了可能整张表都用不了。 所以这一章的七个 Demo,一半在讲语法,一半在讲「别急着动手」。
一、三个层级:库、表、数据
库(database)里放表,表里放数据。 前七章动的全是「数据」这一层——select 取它、
insert 加它、update 改它。
这一章动「表」这一层:建表、看表、改表、复制表、删表。
表是数据的容器,容器一换,里面装的东西跟着受影响。
风险也上了一个量级:数据改错了还能从备份里捞出某几行;表结构改错了,整个表都读不出来。
二、DDL 与 DML:两类语句,两个脾气
insert/update/delete 属于 DML(数据操作语言),
改的是行,表结构不动。 create/alter/drop 属于 DDL(数据定义语言),
改的是结构,表本身在变。
DDL 有三个和 DML 不一样的地方:多数数据库里它不能回滚(MySQL 8 有原子 DDL,但仍有边界);
执行时会锁表;大表上改结构可能锁几分钟到几小时。
第三点最容易被忽略:一条 alter table 在小表上是零点几秒,
在千万行的表上可能是半小时,这半小时里业务全在等。
所以 DDL 的时间成本要按「表的行数」估,不是按「语句的长度」估。
三、动手前问三句
第一句:这个改动会不会丢数据? 删列、改类型、加非空约束,都会丢——删列最直接,整列没了。
第二句:会不会锁表? 加索引、改类型、加列,都可能在执行期间挡住写入。
业务高峰做这些动作,等于自己造一次故障。
第三句最管用:能不能先在一张副本表上试一遍?
拿真实数据量的副本跑一次,才知道真实耗时和副作用。
Demo 里那句 WHERE 1 = 0 就是造副本的手法,第 8.6 篇讲。
四、看当下有哪些表
动结构前先看清楚现状,这是唯一能防「改错表」的动作。 一张表名打错一位,改的就是另一张。
MySQL 写 SHOW TABLES;,本沙箱查 sqlite_master——Demo 里列出六张样例表:classes、goods、
order_detail、orders、scores、students。
记住这个思路:
「看有哪些表」本质是「查一张记录表的表」。 MySQL 也有 information_schema.tables 可以查,
比 SHOW TABLES 更灵活——能加条件、能排序、能连表。
五、一个反直觉的地方:改结构也被外键管着
外键不只拦删数据,也拦改结构。 想删掉 classes 表,
students 指着它,删不掉。 想改 classes.id 的类型,也可能被拒。
所以改结构前,先查一遍「谁在引用这张表」——
这一步在真实项目里往往要翻代码,因为外键不一定写在数据库里,也可能只写在程序逻辑里。
第 10 章讲多表时会专门看这个话题。
六、这一章的七篇怎么排
8.2 库的操作 → 8.3 建表 → 8.4 查看表 → 8.5 改表 → 8.6 复制表 → 8.7 删表。 顺序就是「从上到下、从建到删」,按这个顺序读,每一篇用到的表都是前一篇留下来的。 8.2 那一篇特殊:本沙箱没有「库」这一层(一个文件就是一个库), 所以它全是教材原码,一条都不在这里执行——正文会逐句标清楚。 这也是全书唯一一篇「只看不跑」的。
七、动手 Demo:列一遍表,看清自己在哪一层
Demo 只跑一句查询:把这个库里所有表名列出来。 它是这一章的起点——后面六篇每动一次表,都会回到这句看一眼变化。
import _q46 as Q
c = Q.con()
# 这个库里有哪些表(MySQL 的 SHOW TABLES 在这里的等价写法)
Q.show(c, "SELECT name FROM sqlite_master "
"WHERE type = 'table' ORDER BY name")
实跑输出:
--------------------------------------------------------------------
第三十五课:改结构,比改数据更需要想清楚
--------------------------------------------------------------------
三个层级:库、表、数据
**库(database)里放表,表里放数据。** 前面七章都在最底下那层转,
**这一章上移一层,动「表」本身。**
**这一层一旦改错,后果和改数据不一样**:
**数据改错了还能从备份里捞某几行;表结构改错了,整个表可能都用不了。**
DDL 与 DML:两类语句,两个脾气
**`insert`/`update`/`delete` 属于 DML**(数据操作语言),**改的是行,表结构不动。**
**`create`/`alter`/`drop` 属于 DDL**(数据定义语言),**改的是结构,表本身在变。**
**DDL 有几个特点和 DML 不一样**:**多数数据库里 DDL 不能回滚**(MySQL 8 之前是这样,
8.0 有原子 DDL 但仍有边界)、**执行时会锁表**、**大表上改结构可能锁几分钟到几小时。**
**所以改结构前要问三句**:
**这个改动会不会丢数据?会不会锁表?能不能先在一张副本表上试一遍?** 第三句最管用——
**在副本上试过,才知道真实耗时和副作用。**
看当下有哪些表:一条查询就够
SQL> SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name
name
-------------
classes
goods
order_detail
orders
scores
students
(6 行)
**六张样例表都在。** **这句话是 MySQL 的 `SHOW TABLES` 在本沙箱的等价写法**——
**SQLite 没有 `SHOW` 语句,表的名字都记在 `sqlite_master` 这张系统表里。**
**记住这个思路**:**「看有哪些表」本质是「查一张记录表的表」**,
MySQL 也有 `information_schema.tables` 可以查,比 `SHOW TABLES` 更灵活。
一个反直觉的地方:改结构也会被外键管着
**外键不只拦删数据,也拦改结构。** 比如想删掉 `classes` 表,`students` 指着它,
**删不掉。** **想改 `classes.id` 的类型,也可能被拒。**
**所以改结构前,先查一遍「谁在引用这张表」**——**这是第 9 章讲外键时会专门看的。**
这一章的七篇怎么排
**8.2 库的操作 → 8.3 建表 → 8.4 查看表 → 8.5 改表 → 8.6 复制表 → 8.7 删表。**
**顺序就是「从上到下、从建到删」**,**按这个顺序读,每一篇用到的表都是前一篇建好的。**
**本沙箱没有「库」这一层**(一个文件就是一个库),所以 8.2 那一篇全是教材原码,
不在这里执行——**正文会逐句标清楚。**
六张样例表都在:classes、goods、order_detail、orders、scores、students。
这一句是 MySQL SHOW TABLES 在本沙箱的等价写法——SQLite 没有 SHOW 语句,
表名都记在 sqlite_master 这张系统表里。
剩下四段没有 SQL,讲的是三层结构、DDL 与 DML 的差别、动手前那三句,以及外键为什么也管改结构。
30 秒实验
DROP TABLE classes在这套样例库里会成功吗?为什么?- DDL 和 DML 最实际的两个差别是什么?为什么这两个差别会影响你「什么时候动手」?
- 改结构前那三句里,哪一句最管用?它能替你回答另外两句吗?
常见误区
- 把改结构当改数据,随手在生产库上
alter。 改数据还能回滚或从备份捞, 改结构往往连表都读不出来。 - 以为 DDL 报错就等于什么都没发生。 大表上改结构中途失败,可能已经改了一半, 得先看清现状再决定下一步。
- 不看行数、不试副本,直接上大表。 小表零点几秒的语句,在千万行的表上可能是半小时的锁表。
自测三问(点开对答案)
1. 库、表、数据三层里,前七章动的是哪一层?这一章动哪一层? —— 前七章动「数据」层,这一章动「表」层——建表、看表、改表、复制表、删表。 2. DDL 与 DML 的三个差别是什么? —— DDL 多数不能回滚、执行时锁表、大表上耗时可能很长;DML 改的是行,可以回滚,锁的范围也小得多。 3. 为什么改结构前要先造一张副本表试一遍? —— 副本上能拿到真实数据量下的耗时与副作用,而真表上试的代价可能是业务停摆。三层里最上面那层是「库」。 下一篇 8.2 讲库的增删改查——教材那四条语句,本沙箱一条都跑不了。
- ☐ (本篇完,下一篇 8.2 数据库的操作)