🗄️ 第五章 引入数据库-数据库的结构与表的设计
📄 一句话概括

收官之作:给三张表配类型、上约束、定属性,写下完整的 CREATE TABLE——从 5-16 的需求清单走到这里,书评网站设计全线贯通,本章全部工序在此合龙。

📝 本节和前面几节的关系

5-14(配型四问法)、5-15(命名规则)、5-18(表清单)三股绳拧成最终成品。落表之后顺手在 SQLite 里建出来、灌数据、跑第三章的查询——设计篇和操作篇在此会师。

一、逐列配型决策(四问法实录)

列 类型 决策理由
users.user_id INT(自增) 造号,4-11
users.nickname VARCHAR(20) NOT NULL 变长短文,昵称必须有
users.email VARCHAR(50) NOT NULL UNIQUE 登录凭证:不许空不许重
users.password VARCHAR(60) NOT NULL 存哈希后的串(60 位放散列)
books.isbn CHAR(13) NOT NULL 定长编码当主键,4-3
books.title VARCHAR(50) NOT NULL 变长
books.published DATE 只记日
reviews.score DECIMAL(3,1) 0~10 一位小数
reviews.body TEXT 评论文长度不定
reviews.created_at DATETIME NOT NULL 精确到秒

二、最终成品 DDL

CREATE TABLE users (
    user_id   INT PRIMARY KEY,                 -- SQLite 隐式自增
    nickname  VARCHAR(20) NOT NULL,
    email     VARCHAR(50) NOT NULL UNIQUE,
    password  VARCHAR(60) NOT NULL
);

CREATE TABLE books (
    isbn      CHAR(13) PRIMARY KEY,
    title     VARCHAR(50) NOT NULL,
    author    VARCHAR(30),
    published DATE
);

CREATE TABLE reviews (
    review_id  INT PRIMARY KEY,                -- 隐式自增
    user_id    INT NOT NULL,
    isbn       CHAR(13) NOT NULL,
    score      DECIMAL(3,1) NOT NULL,
    body       TEXT,
    created_at DATETIME NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(user_id),
    FOREIGN KEY (isbn) REFERENCES books(isbn)
);

(SQLite 环境记得先 PRAGMA foreign_keys = ON;——4-13 的提醒。)

三、约束复查:每条都有出处

约束 出处 拦什么
email UNIQUE + NOT NULL 5-17 登录决策 重复账号
user_id/isbn NOT NULL(外键列) 5-17「必须登录才能评」 匿名评论
score DECIMAL(3,1) 5-14 99.9 这类非法分值之外,格式也守住
两把外键 5-18 给不存在的书/人评论

四、动手 Demo:全线贯通

-- 建表(上面三条 DDL)后灌数据、跑查询
INSERT INTO books VALUES ('9787111558422', 'C++ Primer', 'Lippman', '2013-01-01');
INSERT INTO users VALUES (1, '张三', '[email protected]', 'hash123');
INSERT INTO reviews VALUES (1, 1, '9787111558422', 9.5, '经典!', '2026-09-24 09:15:00');

-- 需求 3:某书全部评论+平均分(3-17 的 AVG)
SELECT body, score FROM reviews WHERE isbn = '9787111558422';
SELECT AVG(score) FROM reviews WHERE isbn = '9787111558422';

-- 需求 4:某用户全部书评(3-20 的 JOIN 露一手)
SELECT b.title, r.score, r.body
FROM reviews r
JOIN books b ON r.isbn = b.isbn
WHERE r.user_id = 1;

需求清单上的每一条,都能在这套表上跑出 SQL——这就是设计完成的定义。

五、30 秒实验

往 reviews 塞一条 user_id=99(不存在的用户)——外键报错拦截。再想想:这条防线是谁在哪一节设计出来的?(5-17 定「必须登录」→ 5-19 落 NOT NULL + FOREIGN KEY。)

六、常见误区

自测三问 1. ISBN 为什么是 CHAR(13) PRIMARY KEY?(定长天然唯一——不用自增造号) 2. reviews 的两把外键各指向谁?(users.user_id、books.isbn) 3. 设计完成的标志是什么?(需求清单每条都能跑出 SQL)

相关笔记