上一篇:没有,这里是系列起点 | 本篇:装 MySQL、跑通第一个例子 | 下一篇:《WHERE 到底筛掉了哪些行》
概念
这个系列有 21 篇,从"取数"一直讲到"排错"。它有一个约定:每篇文章自带示例数据。
也就是说,你不需要先准备什么"样板库"、也不用去下载配套数据文件。每篇的"完整案例"开头 都有一段建表 + 插数据的脚本,粘到你的 MySQL 里跑一遍,这一篇剩下所有例子都能直接复制执行。 表名就是普通的 emp、orders、product、customer------和你在教程、面试题里看到的一致, 只是每张表都控制在几十行以内,看得完、记得住。
这一篇只做两件事:把 MySQL 装好,然后跑通第一个 SELECT。剩下的交给后面 20 篇。
主要用法
1. 装 MySQL
三条路,按你的习惯挑一条:
| 方式 | 适合谁 | 我的选择 |
|---|---|---|
| 官方 ZIP 绿色版(Windows) | 想把程序和数据放在非系统盘 | 我现在用的就是这个,装在 D:\tools\mysql |
| 官方安装包(msi) | 想一路下一步、带服务 | 省事,但默认装在 C 盘 |
| Docker 一个容器 | 用完就删,不污染本机 | 临时试特性很方便 |
绿色版的套路是:解压 → 写一份 my.ini(指定端口、数据目录、字符集)→ 初始化数据目录 → 启动 → 设 root 密码。装好之后用下面这句确认它是活的:
sql
SELECT VERSION() AS 版本, @@port AS 端口,
@@character_set_server AS 服务端字符集, @@sql_mode AS 严格模式;
| 版本 | 端口 | 服务端字符集 | 严格模式 |
|---|---|---|---|
| 8.4.11 | 3306 | utf8mb4 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
四样东西一次看全:版本号、端口、字符集、严格模式。最后那个 sql_mode 值得留意------ 它决定了"数据写得不合规"时是报错还是悄悄改掉,后面好几篇的报错都跟它有关。
2. 建一个专门用来练手的库
示例里的建表脚本都带 DROP TABLE IF EXISTS,会重建同名表, 所以给这个系列单独开一个库是省事的做法------想重来时整库删掉重建就行:
sql
CREATE DATABASE IF NOT EXISTS sqlpractice DEFAULT CHARSET utf8mb4;
USE sqlpractice;
名字随便起,sqlpractice、playground 都行。我不建议叫 test、tmp------ 名字越含糊,越容易有人(包括半年后的你)在里面乱改东西。
3. 怎么跑文中的 SQL
三种方式都行:
| 方式 | 说明 |
|---|---|
| 图形化工具 | Navicat、DBeaver、DataGrip、HeidiSQL 都行,SQL 直接粘进查询窗口 |
| 命令行客户端 | mysql -u root -p --default-character-set=utf8mb4,进去再粘 SQL |
| 存成文件跑 | 把例子存成 01.sql,用 mysql -u root -p -e "source D:/path/01.sql" 执行 |
Windows 上有个小坑值得提前知道:PowerShell 不认 < 重定向, 写 mysql ... < 01.sql 会报「< 运算符保留给未来使用」。 要么用客户端自带的 source,要么套一层 cmd /c "mysql ... < 01.sql"。
举例
完整案例(基于本文的示例表)
这一篇只建一张 3 行的小表,用来验证"环境能建表、能插数、能查数":
sql
DROP TABLE IF EXISTS hello;
CREATE TABLE hello (
id INT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
n INT NULL
);
INSERT INTO hello (id, name, n) VALUES (1, '甲', 10), (2, '乙', 20), (3, '丙', NULL);
SELECT id, name, n FROM hello ORDER BY id;
| id | name | n |
|---|---|---|
| 1 | 甲 | 10 |
| 2 | 乙 | 20 |
| 3 | 丙 | NULL |
能出这三行,说明建表、插数、中文、NULL 都没问题。第三行的 n 是 NULL, 后面几篇会反复拿它讲三值逻辑。
顺便看一眼这一系列会用到的表。 每篇只建自己需要的那几张, 规模都不大,全部加起来也就一百多行数据:
| 表 | 大致行数 | 你会用它学什么 |
|---|---|---|
emp |
13 | 筛选、排序、分组、自连接、窗口函数 |
dept |
5 | 内连接 / 左连接、含零统计 |
salgrade |
5 | 非等值连接(区间当连接条件) |
customer |
10 | 左连接、去重、同名数据 |
product |
8 | 函数、JSON 字段、排序分页 |
orders |
12 | 聚合、分组、时间维度、视图 |
order_item |
19 | 多表连接、销售额排行 |
category |
10 | 递归 CTE、自连接 |
review |
14 | 含零统计、五星率 |
sales_daily |
14 | 累计、移动平均、行转列 |
null_demo |
6 | 专门练 NULL 语义 |
app_log / balance_log |
0 起 | 事件与触发器演示(文章里往里写) |
如果你想知道"这个库现在有哪些表、多少行",可以这样查(把库名换成你自己的):
sql
SELECT table_name AS 表名, table_rows AS 估算行数, table_comment AS 说明
FROM information_schema.tables
WHERE table_schema = 'sqlpractice' AND table_type = 'BASE TABLE'
ORDER BY table_name;
| 表名 | 估算行数 | 说明 |
|---|---|---|
| hello | 3 | (这一篇建的小表) |
table_rows 是 InnoDB 的估算值,和 COUNT(*) 可能差几行------这一点第 19 篇会细说。
30 秒小例子(复制即跑)
不建表也能跑,验证一下环境和一个后面的常用写法:
sql
WITH t(n, name) AS (
SELECT 1, '甲' UNION ALL SELECT 2, '乙' UNION ALL SELECT 3, '丙'
)
SELECT n, name, n * 10 AS 十倍
FROM t
ORDER BY n;
| n | name | 十倍 |
|---|---|---|
| 1 | 甲 | 10 |
| 2 | 乙 | 20 |
| 3 | 丙 | 30 |
WITH 名字 AS (...) 叫 CTE,作用是把一段查询起个名字;后面每篇的"30 秒小例子" 基本都是这个套路------自带数据、复制即跑,你可以把它当成"这条语法最小长什么样"的备忘。
最佳实践
- 练习库用独立的名字,别和生产库混在一起。练坏了整库重建,比小心翼翼地练省心得多。
- 建库时明确写
utf8mb4。MySQL 8 默认就是它,但显式写出来能让别人(和半年后的你) 一眼看到,不用怀疑中文和 emoji 会不会出问题。 - 把 SQL 存成文件再跑 ,别在客户端里手敲一堆分号。我现在的习惯是每个练习一个
.sql文件, 出错能重跑,也方便回头看。 - 每篇文章的例子从头往下跑一遍 。文章里的代码块是按顺序互相依赖的: 第一段建表,后面几段都基于它。中间跳着跑,最容易看到"表不存在"。
- 练习环境不要用生产账号,哪怕只是本地库。养成"练习库用练习账号"的习惯。
易错易乱的点
① Windows 的 mysql ... < 文件.sql 在 PowerShell 里不 work
sql
-- 不执行:PowerShell 把 < 当成保留运算符,这样写会报错
-- mysql -u root -p < 01.sql
-- 正确:用客户端自带的 source,或者套一层 cmd
-- mysql -u root -p -e "source D:/path/01.sql"
-- cmd /c "mysql -u root -p < D:\path\01.sql"
② 只跑了建表语句,忘了插数据,然后怀疑自己查错了
建表脚本只负责结构。空表上跑查询会得到 0 行,看起来像"语法写错了",其实是没数据。 文章里的建表块把 INSERT 写在一起,就是为了避免这件事。
③ 严格模式(ONLY_FULL_GROUP_BY + STRICT_TRANS_TABLES)默认是开的
这是好事,它会把不合规的分组和非法数据拦下来。但你要知道它在, 不然会以为"为什么别人那边能跑我这边报错"。用开头那句 SELECT @@sql_mode 查一下就知道。
④ 重启电脑后连不上,不一定是坏了
绿色版不会自动开机启动。要么每次手动跑一下启动脚本,要么把它注册成 Windows 服务。
⑤ 字符集不一致导致中文乱码
客户端和服务端字符集不一致时,中文会显示成 ?? 或乱码。 命令行加 --default-character-set=utf8mb4,图形化工具里去客户端设置里确认一下编码。
练习题
自拟题 A 用一条 SQL 查出:当前 MySQL 的版本、端口、服务端字符集,以及当前用的库和登录用户。 提示:库和用户是函数,不是系统变量。
自拟题 B 统计当前库里各表的名字和列数,按列数从多到少排序,只保留列数超过 3 的表。
参考答案
自拟题 A
sql
SELECT VERSION() AS 版本,
@@port AS 端口,
@@character_set_server AS 服务端字符集,
DATABASE() AS 当前库,
USER() AS 登录用户;
思路:VERSION()、DATABASE()、USER() 是函数,@@xxx 才是系统变量,混用会报语法错。 DATABASE() 在你还没 USE 任何库时返回 NULL,这不是 bug。
自拟题 B
sql
SELECT table_name AS 表名, COUNT(*) AS 列数
FROM information_schema.columns
WHERE table_schema = 'sqlpractice'
GROUP BY table_name
HAVING COUNT(*) > 3
ORDER BY 列数 DESC;
思路:information_schema.columns 里每个列一行,GROUP BY 数一下即可。 把库名换成你自己的;也可以照第 19 篇那样写成 WHERE table_schema = DATABASE(), 这样脚本换库也能用。
配套源码:本文示例数据自带(每段 SQL 可直接复制运行,不依赖任何外部库)
下一篇我们从一个所有人都写过的语句开始:WHERE。它看着简单,但我见过太多人栽在 = NULL 和 NOT IN 上------下一篇把这两个坑当场挖出来。