📄 一句话概括
设计先于录入——先定【建哪些表、每张表有哪些列、各列什么类型与约束】,再往里放数据。
📝 本节和前面几节的关系
三方分工明确了,本节回到管家的工作台上:数据库的第一道工序是设计,不是录数据。
一、表格三件套
表:一类事物的集合(学生表、图书表); 列:事物的一个特征(学号、姓名、年级),每列定一个类型; 行:一条具体记录(一名学生)。 这和 6.2 的数组、6.6 的结构体是同一套思维:先定形状,再装数据——只不过这里装进了磁盘。
二、类型与约束
类型按数据本性选:数字用 INTEGER、文字用 TEXT、日期用 DATE——类型是给管家的第一道规矩; 约束把规矩写进表定义:NOT NULL(不许空)、PRIMARY KEY(不许重复)、CHECK(取值范围); 约束写在表上,任何人想违规都会被 DBMS 当场拦下——数据质量的第一道闸。
三、为什么设计必须在前
表结构定下之后,所有数据都按这个模子摆——中途改模子的代价极高(数据要搬家、程序要改口径)。 5.8 说【先在纸上考虑算法】,7.7 说【图纸先行】——数据库同理:设计先行是省钱的铁律。 设计时还要想清楚:哪些信息进哪些表、表之间靠什么关联(8.4、8.5 就是干这个的)。
四、动手 Demo:设计一张学生表
给图书管理设计学生表:定列、定类型、定约束,建成后立刻验收结构。
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE student ("
"id INTEGER PRIMARY KEY, "
"name TEXT NOT NULL, "
"grade INTEGER)")
for col in con.execute("PRAGMA table_info(student)"):
print(col)
实跑输出:
--------------------------------------------------------------------
设计数据库——先把表结构定下来
--------------------------------------------------------------------
设计数据库的第一步: 决定【建哪些表、每张表有哪些列】。
给图书管理设计一张【学生表】, 真建一次看结构:
CREATE TABLE student (id INTEGER PRIMARY KEY, name TEXT NOT NULL, grade INTEGER);
列名 类型 说明
--------------------------------------------
id INTEGER 学号, 主键(唯一标识)
name TEXT 姓名, NOT NULL 不许空
grade INTEGER 年级
建完立刻验收结构:
0 id INTEGER 非空=0 主键=1
1 name TEXT 非空=1 主键=0
2 grade INTEGER 非空=0 主键=0
设计要点: 列名见名知意、类型按数据本性选、约束(主键/非空)写进表定义。
表结构一旦定下, 后面所有数据都按这个模子摆——所以设计要在前面。
PRAGMA table_info 是【查结构】的探头——设计完当场验收,别等录了数据才发现少一列。 【⚠️ 2026 现状】真实项目里表结构用迁移脚本(migration)管理,每一次改动都留有版本记录。
30 秒实验
- 给【图书】设计一张表:想清楚需要哪几列、各列什么类型、哪列当主键。
- 说出三种约束各自拦下什么样的坏数据。
常见误区
- 以为设计就是先建个表凑合用——结构定下后再改,数据要搬家,代价翻倍。
- 以为类型随便选——类型错了不仅浪费空间,还会让查找和比较出怪结果。
自测三问(点开对答案)
1. 数据库设计的三个决定? —— 建哪些表、每张表有哪些列、各列的类型与约束。 2. 约束起什么作用? —— 把数据规矩写进表定义,违规数据被 DBMS 当场拦下。 3. 为什么设计要在录数据之前? —— 结构一定,数据都按模子摆,中途改结构代价极高。- ☐ 下一节(8.4 通过拆表和整理数据实现规范化)
相关笔记
- LX_CH5_58 — 先在纸上考虑,设计先行的老规矩
- LX_CH7_77 — UML 图纸先行,与表设计同理
- 💻 计算机是怎样跑起来的 · 索引