码上问学问代码之理,学编程之道

第 1 章 · 数据库与 MySQL 入门

写一个网站,第一件绕不开的事就是「数据放哪儿」。用 Excel?人一多、量一大立刻散架。这一章把「古典文学网」的数据地基打好:弄清数据库到底解决什么问题,认识库、表、行、列、主键这些基本概念,把 MySQL 装好、连上,亲手创建 hiwen 库并学会正确地删除它,导入我们在整门课里要一直用的 hiwen.sql,然后敲出第一条查询。学完这一章,你的电脑上就有一个真能跑、由你自己建出来的数据库了。

为什么需要数据库

先说清楚它替代了什么
先讲为什么假设你要做「古典文学网」,一开始很自然地会想:数据存 Excel 里不就行了?一个 作品.xlsx,几行几列,想改就改,多省事。
这个方案在只有你一个人、只有几十行数据的时候确实能跑。但网站一上线,用户一多,它马上崩:三个人同时编辑,Excel 要么锁文件、要么后保存的覆盖先保存的;作品涨到五万篇,打开文件都要转半分钟;想看「李白的所有作品」,还得手动筛;更要命的是,你的 Python/Flask 后端根本没法方便地从 xlsx 里安全地取一条记录。
数据库就是为解决这些问题而生的:专门存数据、专门管并发、专门给程序读写的软件。

库、表、行、列、主键

拿 article 表当例子
数据库的层级:一间图书馆(hiwen)→ 书架(表)→ 一本书(行)库 database = hiwen(一间图书馆)usercategoryarticle ← 放大看commentfavoriteuser_likebanner表 table = article(一张 Sheet)idtitleauthordynasty行 row = 一部作品:1 | 静夜思 | 李白 | 唐2 | 春望 | 杜甫 | 唐主键 id列:类型 varchar一行 = 一条记录主键:这一行的「身份证号」,全表唯一外键:指向另一张表的主键(article.category_id → category.id)
先讲为什么你已经很熟悉 Excel 那一套:一个文件里有好几张工作表(Sheet),每张表有列标题,一行就是一条数据。关系型数据库完全是同一套思路,只是换了名字——理解了这层对应关系,后面所有术语都不用死记。
动手做先不看结构文档,直接取两行数据出来,感受一下「一行=一篇作品,一列=一种属性」。
看两行.sqlsql可运行
SELECT id, title, author, dynasty FROM article LIMIT 2;
查询结果SQL 执行结果
运行结果: id | title | author | dynasty 1 | 静夜思 | 李白 | 唐 2 | 春望 | 杜甫 | 唐 -- 共 2 行
讲透
  • 上面这段其实就是「库 → 表 → 列 → 行」走了一遍:在 hiwen 这个库里,取 article 这张表的 id / title / author / dynasty 四列,只看前两行。
  • 为什么要有主键:两篇作品可能重名(古人「无题」一大堆),但 id 永远不会重复。所以后端页面的地址往往是 /article/detail?id=3,靠 id 而不是标题来定位。
  • 为什么要把「分类」单独建一张表:如果把分类名直接写在作品表里,改一次「唐诗」得改一堆行,还可能写成「唐诗 」「唐 诗」。拆成 category 表 + category_id,改一次就够了——这就是第 5 章「多表连接」要处理的事。
避坑新手最容易犯的错,是拿「业务上有意义的东西」当主键。比如为了好看,把 title 设成主键——结果库里一旦出现两篇同名作品,第二条就插不进去了。主键就老老实实用 id,它只负责唯一,不负责好看。

MySQL 是什么、装在哪

选型与安装要点
先讲为什么数据库是一类软件,MySQL 是其中最有名的一个。「关系型」是说它按「二维表」来组织数据(就是你刚学的那种行列结构),而 MySQL 是开源免费、资料最多、招聘需求最大的那一款,中小型网站(包括我们的古典文学网)用它完全够。
先把结论摆这儿:本课程全程使用 MySQL 8.x,你电脑上装 8.0 及以上的任意小版本都行。
动手做(1)装好之后,先确认命令能不能用打开终端(macOS)或 CMD/PowerShell(Windows),敲一句版本检查。这一步能同时验证「装没装」和「加没加到系统路径」两件事。
检查版本.shbash可运行
# Windows 和 macOS 都是这一句
mysql --version
终端输出命令行执行结果
运行结果: mysql Ver 8.0.36 for macos13.6 on arm64 (Homebrew) -- 版本号末位可能不同,只要是 8.0 以上就没问题 -- Windows 上显示形如:mysql Ver 8.0.36 for Win64 on x86_64 (MySQL Community Server - GPL)
动手做(2)把数据库服务启动起来MySQL 是常驻后台的服务,装完不一定在跑。先启动,再去连它。
启动服务-Windows.cmdbash可运行
# 需要「以管理员身份运行」CMD,否则会提示拒绝访问
net start MySQL80
net stop MySQL80
终端输出命令行执行结果
运行结果: MySQL80 服务正在启动 . MySQL80 服务已经启动成功。 -- 停止时的输出:MySQL80 服务已成功停止。
启动服务-macOS.shbash可运行
brew services start mysql
brew services stop mysql
brew services list
终端输出命令行执行结果
运行结果: ==> Successfully started `mysql` (label: homebrew.mxcl.mysql) -- brew services list 会显示当前状态,started 就是已经跑起来了
讲透
  • 服务端和客户端是两个东西。MySQL Server 在后台听着端口(默认 3306),客户端(命令行 mysql、Navicat、DBeaver、甚至你写的 Flask 程序)连上去、发指令。所以「连不上」要分两步排查:服务起了吗?客户端参数对吗?
  • 字符集一定要用 utf8mb4。我们要存「念奴娇·赤壁怀古」这类中文,旧的 utf8 存不下 emoji 和部分生僻字,utf8mb4 才是真正的 UTF-8。我们的 hiwen.sql 已经替你设好了。
  • 本课统一约定:MySQL 8.x、端口 3306、库名 hiwen。后面所有章节的示例都建立在这个前提上。
避坑两个最常见的安装坑:① 3306 端口被占用——常见于同时装了 MySQL 8 和旧版 MySQL、或者装过 XAMPP/WAMP。启动失败时先看错误日志里的「port already in use」。② root 密码忘了——不要急着重装,先尝试用图形客户端里已保存的连接,或者在命令行用 --skip-grant-tables 方式跳过校验改密码。密码这种事,第二次开始请记到密码管理器里。

怎么连上数据库

命令行 + 图形客户端
连接的本质:客户端把 SQL 发给服务器上的 mysqld(默认端口 3306)命令行客户端mysql -u root -p服务器上敲,最直接图形客户端Navicat / DataGrip / DBeaver写 SQL 舒服,教学演示用它程序里的驱动pymysql(Python)第 10 章再学SQL 语句MySQL 服务器mysqld 进程端口 3306账号 + 密码验证读写磁盘上的数据文件(hiwen 库)一个服务器可以建多个库;一个库可以有多张表——像一台电脑多个硬盘分区
动手做连数据库的最小命令就是 mysql -u root -p:-u 指定用户名,-p 表示「回车之后再输密码」(这样密码就不会留在命令历史里)。
连接终端.shbash可运行
mysql -u root -p
终端输出命令行执行结果
运行结果: Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 12 Server version: 8.0.36 MySQL Community Server - GPL Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> -- 看到 mysql> 提示符就说明连上了;connection id 每次连接都不一样
动手做(2)连上以后,先看看机器上有哪些库数据库软件自己也会带几个系统库,别慌,那不是你的。
看有哪些库.sqlsql可运行
SHOW DATABASES;
查询结果SQL 执行结果
运行结果: Database information_schema mysql performance_schema sys -- 共 4 行 -- 导入 hiwen.sql 之后,这份列表里会多出一个 hiwen(见本章最后一节)
讲透
  • 连接三要素:主机 + 端口 + 账号密码。本机就是 127.0.0.1:3306。完整写法是 mysql -h 127.0.0.1 -P 3306 -u root -p,参数都能省,省了就取默认值——所以你平时只写 mysql -u root -p。
  • 图形客户端怎么填:Navicat 里「新建连接 → MySQL」,DBeaver 里「新建连接 → MySQL」,两者填的东西一模一样:主机 127.0.0.1、端口 3306、用户名 root、密码就是你安装时设的。点「测试连接」出现 Success 即可。
  • 命令行 vs 图形客户端:图形客户端适合「看数据、改几行」;命令行适合「跑脚本、做自动化」。考试和面试考的是 SQL 语句本身,客户端只是壳,两边都能用,本课以命令行为准。
  • 退出:命令行里敲 exit 或 \q。
避坑在命令行里敲 SQL,末尾必须写分号。如果你敲完一句没打分号就回车,提示符会从 mysql> 变成 ->,意思是「你这句还没完,我等着呢」。这时候补一个分号就能执行;实在乱了就敲 \c 取消重来。另一种连不上的情况是报 Access denied for user 'root'@'localhost'——那不是服务没起,是密码错了。

SQL 的四大分类

先看清地图,再走路线
SQL 地图:先认全四大家族,再按需深入SQLDDL 数据定义建库建表改结构CREATE · ALTER · DROPDQL 数据查询只查不改SELECTDML 数据操作增删改数据行INSERT · UPDATE · DELETEDCL 数据控制权限与安全GRANT · REVOKE学习路线:DDL 建好舞台 → DQL 查(重点 60%)→ DML 改 → DCL 了解即可本课重点:SELECT 一族 + JOIN + 聚合,占日常工作的绝大多数
先讲为什么SQL 是你和数据库对话的「普通话」,但它里面其实分四类活儿:建结构、改数据、查数据、管权限。这四类的学习顺序不一样——查数据(DQL)你用一辈子,管权限(DCL)可能一辈子只碰几次。
所以先知道地图长什么样,你才知道这一章、乃至整门课走在哪条路上。
动手做把四类各挑一句放在一起看。下面这段会真的改数据(先插一条分类、再把它删掉,所以最终还是原样),重点是让你看清四类语句长得完全不一样。
四大分类.sqlsql可运行
-- ① DDL 管结构:建表 / 加列 / 删表
CREATE TABLE t_demo (id INT PRIMARY KEY, name VARCHAR(20));
ALTER TABLE t_demo ADD COLUMN price DECIMAL(10,2);
DROP TABLE t_demo;

-- ② DML 管行:增 / 改 / 删(这里插完又删掉,结果回到原样)
INSERT INTO category (name, sort) VALUES ('赋', 6);
UPDATE category SET sort = 60 WHERE name = '赋';
DELETE FROM category WHERE name = '赋';

-- ③ DQL 只管取数,不改任何东西
SELECT name, sort FROM category ORDER BY sort;

-- ④ DCL 管权限(仅示意,本课不要求跑)
-- CREATE USER 'reader'@'localhost' IDENTIFIED BY '123456';
-- GRANT SELECT ON hiwen.* TO 'reader'@'localhost';
查询结果SQL 执行结果
运行结果: name | sort 唐诗 | 1 宋词 | 2 元曲 | 3 散文 | 4 小说 | 5 -- 共 5 行 -- ② 里插入的「赋」已经被 DELETE 掉了,所以结果还是原来的 5 条分类
讲透
  • 「本章以后怎么用」这张地图:第 2 章开始全是 DQL(SELECT 的各种花样),第 6 章回到 DML(安全地增删改),第 7~8 章是 DDL(真正设计表结构、索引、视图),第 10 章落到 DCL 的影子——SQL 注入与预处理语句。
  • 为什么把 DQL 学在 DML 前面:因为改错数据是不可逆的。先学会「看清楚」,再动手「改」——这是工程师的基本纪律。
  • 查数据是网站的日常:古典文学网首页打开一次,背后至少十几条 SELECT;而 INSERT/UPDATE 只在用户点「发布书评」「点赞」时才发生。
避坑DROP 和 DELETE 只差一个字母,后果差得远:DELETE FROM article 是「清空这张表的所有行」,DROP TABLE article 是「把这张表连结构一起铲平」,而 DROP DATABASE hiwen 是「整个库都没了」,都没有撤销键。动手前先 SELECT 一遍确认影响范围,这条习惯将来能救你的饭碗。

创建数据库:CREATE / USE / DROP

DDL 的第一课,也是真正动手的第一步
先讲为什么上一节说 SQL 分四类,其中 DDL(数据定义语言)管的是「结构」:CREATE 建、ALTER 改、DROP 删。
而在数据库世界里,你要做的第一件事一定是「建库」——库是装表的盒子,没有盒子就放不进表。这跟你在硬盘上新建一个 Excel 文件、然后才能在里面建 Sheet 是一模一样的顺序。
从这一节开始,你敲的每一条语句都是可以立刻验证的:建完库,再用 SHOW 看它是不是真的在那儿。
动手做(1)先看看现在有哪些库刚装好的 MySQL 里已经有一批自带的库,先认一认,别稀里糊涂就往里写东西。
看有哪些库.sqlsql可运行
SHOW DATABASES;
查询结果SQL 执行结果
运行结果: Database information_schema mysql performance_schema sys -- 共 4 行
讲透
  • 这 4 个是 MySQL 自带的系统库,不要动它们:information_schema 存「元数据」(所有库和表的描述信息);mysql 存用户与权限;performance_schema 和 sys 是性能监控与诊断用的。
  • 我们自己的业务数据要放在一个独立的库里。这门课只用这一个库,名字叫 hiwen(取自「古典文学网」)。
  • 顺手记一条命名习惯:库名、表名一律全小写 + 下划线(hiwen、user_like),不用中文、不用空格、不用 MySQL 的保留字。这样跨平台(Windows 不区分大小写、Linux 区分)都不会出诡异问题。
动手做(2)创建 hiwen 库注意我们显式指定了字符集,这一步千万别偷懒——理由马上讲。
创建数据库.sqlsql可运行
CREATE DATABASE hiwen
  DEFAULT CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci;
查询结果SQL 执行结果
运行结果: Query OK, 1 row affected (0.01 sec)
避坑:字符集要写 utf8mb4,不要写 utf8这是 MySQL 历史上最坑人的一个命名:MySQL 里的 utf8 是「残缺版」,每个字符最多只用 3 个字节,存不了 emoji,也存不了一部分生僻汉字(比如「𠮷」「𰻝」这类 4 字节字)。utf8mb4 才是真正的完整 UTF-8。
我们这门课的诗文里就有生僻字,一旦用错字符集,插入时会报 ERROR 1366: Incorrect string value,或者更糟——数据被悄悄截断成乱码。认准 utf8mb4。
讲透
  • CHARACTER SET(字符集):决定「用哪种编码存文字」。库级定好后,后面建的表会默认继承它。
  • COLLATE(排序规则):决定「字符串怎么比大小、怎么排序」。utf8mb4_general_ci 结尾的 ci 是 case insensitive(不区分大小写),所以查 WHERE author = 'libai' 也能命中「李白」之外存英文的情况。MySQL 8 的默认其实是 utf8mb4_0900_ai_ci(基于 Unicode 9.0),但本课脚本统一用 utf8mb4_general_ci——各版本表现一致,换机器不会突然变排序结果。
  • 为什么强调「库级就定好」:字符集在库、表、列三级都能单独指定,级别越细优先级越高。如果库级没定、后来又到处补,很容易出现「同一个库里几张表编码不一样」的烂摊子,排查起来极其痛苦。
动手做(3)加上 IF NOT EXISTS把建库语句写进脚本时,一定要加这 5 个单词。
重复执行也不报错.sqlsql可运行
CREATE DATABASE IF NOT EXISTS hiwen
  DEFAULT CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci;
SHOW WARNINGS;
查询结果SQL 执行结果
运行结果: Query OK, 1 row affected, 1 warning (0.01 sec) Level | Code | Message Note | 1007 | Can't create database 'hiwen'; database exists -- 共 1 行
讲透不加 IF NOT EXISTS 时,库已存在会直接报 ERROR 1007 (HY000),脚本就在这里中断了,后面的建表、插数据全都不执行。加上它之后,MySQL 只是给一个 Note 级别的提示(代码 1007)然后跳过,脚本能继续跑完。
这是所有「可重复执行脚本」的基本素养:第一次跑能建,第二次跑不炸。
动手做(4)进入这个库,并确认自己「人在哪儿」建好库不等于进了库——这一步新手最容易忘。
选中数据库.sqlsql可运行
USE hiwen;
SELECT DATABASE();
查询结果SQL 执行结果
运行结果: Database changed DATABASE() hiwen -- 共 1 行
讲透
  • USE hiwen; 的作用是设定「默认库」。设了之后,你可以直接写 SELECT * FROM article,不用写全名。
  • 不设也能查,但每次都得写完全限定名:SELECT * FROM hiwen.article;。跨库查询(比如把 A 库的数据导到 B 库)时这种写法很有用。
  • SELECT DATABASE(); 返回当前默认库;如果还没 USE,它会返回 NULL。养成「动手前先看一眼人在哪儿」的习惯,能省掉大量莫名其妙的报错。
动手做(5)回头确认一下库是怎么建出来的这条语句能原样打印出建库时用的完整定义,是排查字符集问题最快的一招。
回看创建语句.sqlsql可运行
SHOW CREATE DATABASE hiwen;
查询结果SQL 执行结果
运行结果: Database | Create Database hiwen | CREATE DATABASE `hiwen` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ -- 共 1 行
动手做(6)删除数据库 DROP DATABASE先补齐这一条,DDL 的「建 / 用 / 删」才算学全。
删除数据库.sqlsql可运行
DROP DATABASE IF EXISTS hiwen;
查询结果SQL 执行结果
运行结果: Query OK, 0 rows affected (0.02 sec)
避坑:DROP DATABASE 是整门课最危险的一条语句它把这个库、库里所有表、表里所有数据一次性全部删掉,没有回收站、不可撤销、也不会跟你二次确认。
所以:
① 练习时可以随便删(反正有 hiwen.sql 能一键还原);
② 真实项目里执行前必须确认备份存在且可恢复;
③ 也正因如此,我们 hiwen.sql 的第 12 行写着 DROP DATABASE IF EXISTS `hiwen`;——它每次导入都先清空重建,图的是练习方便,千万别拿它去对着存了真实数据的库跑。
另外养成习惯:DROP 前先 SHOW DATABASES; 看一眼,再 SELECT DATABASE(); 确认当前库,别删错。
讲透 · 把这六步串成一条主线
  • 层级关系永远是三层:数据库(database)→ 表(table)→ 行与列(row / column)。所有操作都在这个层级里发生,迷路时就默念这一句。
  • 标准流程:SHOW DATABASES 看现状 → CREATE DATABASE 建库 → USE 进库 → 建表 → 增删改查。这五步会贯穿你今后的每一次数据库操作。
  • 这一节全部属于 DDL:CREATE / USE / DROP / SHOW 都在定义和查看「结构」,没有碰过任何一条数据。下一节开始,你才第一次真正读到数据。
  • 一个重要区别:DROP 删的是「结构」(连库带表带数据一起没),后面第 6 章讲的 DELETE 只删「数据行」、表还在。两者量级完全不同,别混用。

第一个查询:先看一眼数据

SHOW / DESC / SELECT
先讲为什么面对一个陌生的库,老手的动作永远只有三步:先看有哪些表 → 再看这张表长什么样 → 最后取几行真实数据。别急着写复杂 SQL,先把地基看清楚。
动手做(1)先看库里有几张表
看有哪些表.sqlsql可运行
SHOW TABLES;
查询结果SQL 执行结果
运行结果: Tables_in_hiwen article banner category comment favorite user user_like v_article_list -- 共 8 行
讲透
  • 7 张表加 1 个视图(v_article_list)。视图不是表,是「一条被存下来的查询」——第 8 章会专门讲它,现在你只要知道它也能当表来查。
  • 注意表名全是单数:user 不是 users,article 不是 articles。本课所有示例都以此为准,写错表名会直接报 Table 'hiwen.users' doesn't exist。
动手做(2)再看这张表的结构DESC 是 DESCRIBE 的缩写,专门用来看表的列定义。
看表结构.sqlsql可运行
DESC article;
查询结果SQL 执行结果
运行结果: Field | Type | Null | Key | Default | Extra id | int unsigned | NO | PRI | NULL | auto_increment title | varchar(150) | NO | MUL | NULL | author | varchar(50) | YES | | NULL | dynasty | varchar(20) | YES | | NULL | category_id | int unsigned | YES | MUL | NULL | cover | varchar(255) | YES | | '' | summary | varchar(500) | YES | | NULL | content | text | YES | | NULL | views | int unsigned | NO | | 0 | likes | int unsigned | NO | | 0 | is_recommend | tinyint | NO | | 0 | status | tinyint | NO | | 1 | created_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED updated_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP -- 共 14 行
讲透
  • Field / Type:列名和类型。title 最长 150 字符,content 用 TEXT(长文本),views 是 int unsigned(无符号整数,不可能为负)。
  • Null:YES 表示这一列允许存 NULL(空值),NO 表示必须给值。所以插入数据时 title 是必填的,author 可以不填。
  • Key:PRI 是主键;MUL 指这一列是某个非唯一索引的第一列。这里是 title、category_id、is_recommend 三列——因为 article 上建了 FULLTEXT 全文索引(第一列是 title)和两个普通索引。索引是第 7 章的内容,现在知道它存在就行。
  • Default:默认值。views 默认 0,status 默认 1(新作品默认「已发布」)。如果插入时不给值,MySQL 就填默认值。
  • Extra:额外说明。auto_increment 表示 id 会自动编号;DEFAULT_GENERATED 表示默认值是个「表达式」(CURRENT_TIMESTAMP 取当前时间)。
动手做(3)最后把真实数据取出来这就是你人生中第一条有意义的查询。
第一个查询.sqlsql可运行
SELECT title FROM article LIMIT 3;
查询结果SQL 执行结果
运行结果: title 静夜思 春望 念奴娇·赤壁怀古 -- 共 3 行
避坑如果 SHOW TABLES; 报 ERROR 1046 (3D000): No database selected,说明你还没告诉 MySQL 要操作哪个库。先执行 USE hiwen;(看到 Database changed 才算切换成功),再跑后面的语句。这跟你打开 Excel 得先打开某个文件是一个道理。

把 hiwen.sql 导入进去

一条命令,建库建表灌数据
先讲为什么真实项目里,你不可能每次换台机器就手敲几十条建表语句。把「结构 + 初始数据」写成一个 SQL 脚本,谁拿到都能一键还原——这就是数据库的「项目源码」。
我们的 hiwen.sql 就是这样一个脚本:建库 hiwen、建 7 张表、建 1 个视图、灌入分类/作品/书评/收藏/轮播图/点赞的种子数据。整门课的所有示例都跑在它上面。
动手做(1)在系统命令行里导入用 < 把脚本文件「喂」给 mysql 客户端。注意这一句是在系统终端里敲的,不是在 mysql> 提示符里。
导入脚本.shbash可运行
# macOS / Linux(把路径换成你自己的)
mysql -u root -p < ~/Desktop/hiwen.sql

# Windows(PowerShell 里注意路径用反斜杠或正斜杠都行)
mysql -u root -p < D:\hiwen.sql
终端输出命令行执行结果
运行结果: Enter password: -- 没有任何报错输出,就是导入成功;脚本里的 DROP / CREATE / INSERT 已经依次执行完了
动手做(2)已经在 mysql> 里了?用 source如果你人已经在 MySQL 客户端里,就不用退出去,直接 source 文件路径 也能导入。
source导入.sqlsql可运行
-- 注意:source 后面写路径,末尾不要加分号
source /Users/you/Desktop/hiwen.sql

-- 导入完成后切换进去,验证一下
USE hiwen;
SELECT title, author, dynasty FROM article LIMIT 3;
查询结果SQL 执行结果
运行结果: -- source 导入过程中会刷出一大串 Query OK(建库、建表、插数据各打印一行),只要没出现 ERROR 就是成功 Database changed title | author | dynasty 静夜思 | 李白 | 唐 春望 | 杜甫 | 唐 念奴娇·赤壁怀古 | 苏轼 | 宋 -- 共 3 行
讲透
  • 这个脚本可以反复执行。它的开头是 DROP DATABASE IF EXISTS `hiwen`;,意思是「如果已经有 hiwen 就整个删掉重建」。所以练习做乱了、数据改坏了,重新导一次就回到出厂状态——这是它最贴心的设计。
  • 种子数据一共这些:分类 5 条(唐诗/宋词/元曲/散文/小说)、作品 6 篇(静夜思、春望、念奴娇·赤壁怀古、声声慢、天净沙·秋思、陋室铭)、书评 3 条、收藏 3 条、点赞 3 条、轮播图 3 条、用户 2 个。你在后面各章看到的结果,都是从这批数据算出来的,可以自己核对。
  • 脚本里的 user 表没有真实密码:密码列存的是占位符 PUT_HASH_HERE,真正做登录功能时要先用 Python 的 werkzeug.security 生成哈希再更新进去。这是第 10 章的事。
避坑三个导入时的经典翻车:① source 末尾加了分号——MySQL 会把分号当成文件名的一部分,报 Failed to open file '...hiwen.sql;',去掉分号即可。② 中文变问号或乱码——Windows 的 CMD 默认不是 UTF-8,导入时加上 --default-character-set=utf8mb4:mysql -u root -p --default-character-set=utf8mb4 < D:\hiwen.sql。③ 路径含中文或空格——把脚本放到纯英文路径下最稳,比如 D:\hiwen.sql 而不是「我的文档\新建文件夹\hiwen.sql」。
动手练习
1写出两条命令:① 查看 hiwen 库里有哪些表;② 查看 category 表的结构(列名、类型、是否允许 NULL)。
2用一条 SQL 从 article 表取出前 3 篇作品的 id 和 title,然后说说这批数据能不能证明你的 hiwen.sql 已经导入成功了。
3迁移练习:「红影赏析」(电影主题)也要建库了。请完整走一遍本章的流程:先用 DDL 创建 hongying 库(字符集必须选对),进入该库,再建一个 movie 表(至少含 id / title / genre / rating 四列,id 为主键自增),用 DML 插一部电影,用 DQL 把它查出来,最后用一句话说明 DCL 是用来干什么的。加分项:让你这套语句即使重复执行两次也不报错。
参考答案
练习答案.sqlsql可运行
-- 第 1 题
SHOW TABLES; -- 或 SHOW TABLES FROM hiwen;
DESC category; -- 或 SHOW COLUMNS FROM category;

-- 第 2 题
SELECT id, title FROM article LIMIT 3;

-- 第 3 题:红影赏析(hongying 库,结构自拟)
-- ① 建库(加 IF NOT EXISTS,保证重复执行不报错)
CREATE DATABASE IF NOT EXISTS hongying
  DEFAULT CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci;

-- ② 进入这个库
USE hongying;

-- ③ 建表(同样加 IF NOT EXISTS)
CREATE TABLE IF NOT EXISTS movie (
  id         INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '电影ID',
  title      VARCHAR(100) NOT NULL COMMENT '片名',
  genre      VARCHAR(20)      DEFAULT NULL COMMENT '类型',
  rating     DECIMAL(3,1)     DEFAULT NULL COMMENT '评分',
  created_at DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='电影表';

INSERT INTO movie (title, genre, rating) VALUES ('流浪地球', '科幻', 8.4);

SELECT id, title, genre, rating FROM movie;
-- DCL 一句话:用来管理「谁能访问、能做什么」,如 CREATE USER / GRANT / REVOKE(第 10 章细讲)
查询结果SQL 执行结果
运行结果: -- 第 1 题(表清单见本章第 7 节,category 结构如下) Field | Type | Null | Key | Default | Extra id | int unsigned | NO | PRI | NULL | auto_increment name | varchar(30) | NO | UNI | NULL | description | varchar(255) | YES | | NULL | sort | int | NO | | 0 | status | tinyint | NO | | 1 | created_at | datetime | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED -- 共 6 行 -- 第 2 题 id | title 1 | 静夜思 2 | 春望 3 | 念奴娇·赤壁怀古 -- 共 3 行 -- 能取到具体作品,说明建表和灌数据都成功了 -- 第 3 题 -- ① 建库 Query OK, 1 row affected (0.01 sec) -- ② 进库 Database changed -- ③ 建表 Query OK, 0 rows affected (0.03 sec) -- 插入 Query OK, 1 row affected (0.01 sec) -- 查询(在红影的库里执行,评分数据示例) id | title | genre | rating 1 | 流浪地球 | 科幻 | 8.4 -- 共 1 行

第 3 题的关键有两点:① 从建库开始走完整流程——先 CREATE DATABASE 再 USE 再建表,顺序反了就会报 No database selected;② 换的只是库名、表名和字段名,四大分类的分工完全不变——DDL 定结构、DML 改数据、DQL 取数据、DCL 管权限。能把「古典文学」的套路搬到「红影赏析」,说明你真理解了它们的边界。

本章小结

📝 本节自测

做完点「检查本节」看解析与得分;做错可重做。