MySQL 数据库完全入门指南
本文档面向零基础新手,从概念到实操,用大量示例带你掌握 MySQL 的方方面面。
目录
- 什么是 MySQL
- 安装与启动
- 核心概念
- 基本操作:数据库
- 基本操作:表与数据类型
- 增删改查(CRUD)
- 条件与排序
- 约束
- 索引
- 多表与连接
- 聚合与分组
- 子查询
- 视图
- 常用函数
- 用户与权限(入门)
- 备份与恢复
- 常见问题与最佳实践
1. 什么是 MySQL
1.1 数据库是什么?
数据库就是有结构地存放数据的仓库。
可以把它想象成 Excel:有很多“表”,每张表有“列”和“行”,但数据库比 Excel 更强大,能处理海量数据、多人同时访问、保证数据一致性和安全。
1.2 MySQL 是什么?
- MySQL 是一种关系型数据库管理系统(RDBMS)。
- “关系型”指数据以表的形式组织,表与表之间可以通过关系(如主键、外键)关联。
- 使用 SQL(Structured Query Language,结构化查询语言) 来操作数据。
1.3 为什么学 MySQL?
- 开源、免费、使用广泛(很多网站、应用的后端都用它)。
- 语法相对简单,适合入门。
- 学会 MySQL 后,再学其他数据库(如 PostgreSQL、SQL Server)会容易很多。
2. 安装与启动
2.1 安装 MySQL(Windows 示例)
- 打开 MySQL 官网 下载 Windows 安装包。
- 运行安装程序,选择 “Developer Default” 或 “Server only”。
- 设置 root 用户的密码(务必记住)。
- 完成安装。
2.2 启动 MySQL 服务
- Windows:在“服务”里找到 “MySQL80”(或你的版本),设为“自动”并启动。
- 命令行启动(以管理员身份打开 CMD):
net start MySQL80
2.3 登录 MySQL
打开命令行(CMD 或 PowerShell),输入:
mysql -u root -p
按回车后输入你设置的 root 密码,即可进入 MySQL 命令行,看到类似:
mysql>
参数说明:
-u root:使用用户名为root-p:提示输入密码(也可以写成-p你的密码,但不推荐,会暴露密码)
示例:指定主机和端口
mysql -h 127.0.0.1 -P 3306 -u root -p
-h:主机(本机用 127.0.0.1 或 localhost)-P:端口(默认 3306)
3. 核心概念
3.1 层级关系
MySQL 服务器
└── 数据库(Database)
└── 表(Table)
└── 行(Row / 记录)
└── 列(Column / 字段)
- 数据库:相当于一个“项目”或“应用”的数据容器,里面有多张表。
- 表:类似 Excel 的一张表,有表名和列名。
- 行:一条具体的数据记录。
- 列:一个属性/字段,如“姓名”“年龄”。
3.2 举例理解
假设我们做一个“学生管理系统”:
- 数据库:
school - 表:
students(学生表) - 列:学号、姓名、性别、年龄、班级
- 行:每个学生一条记录
| 学号 | 姓名 | 性别 | 年龄 | 班级 |
|---|---|---|---|---|
| 001 | 张三 | 男 | 18 | 高一1班 |
| 002 | 李四 | 女 | 17 | 高一2班 |
4. 基本操作:数据库
4.1 查看已有数据库
SHOW DATABASES;
示例输出可能包含:
information_schema(系统库)mysql(系统库)performance_schema(系统库)sys(系统库)- 以及你自己创建的库
4.2 创建数据库
CREATE DATABASE 数据库名;
示例:
CREATE DATABASE school;
指定字符集(推荐使用 utf8mb4,支持中文和 emoji):
CREATE DATABASE school DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
4.3 使用(选中)某个数据库
后续的建表、查询等操作都会在这个库里进行。
USE school;
提示:Database changed 表示已切换到 school。
4.4 查看当前使用的数据库
SELECT DATABASE();
4.5 删除数据库
注意:删除后数据无法恢复,慎用!
DROP DATABASE 数据库名;
示例:
DROP DATABASE test_db;
5. 基本操作:表与数据类型
5.1 常用数据类型一览
| 类型 | 说明 | 示例 |
|---|---|---|
| INT | 整数 | 年龄、数量 |
| BIGINT | 大整数 | 雪花 ID |
| DECIMAL(M,D) | 精确小数 | 金额 |
| FLOAT/DOUBLE | 浮点数 | 成绩、比例 |
| VARCHAR(n) | 可变长字符串 | 姓名、地址 |
| CHAR(n) | 定长字符串 | 固定长度编码 |
| TEXT | 长文本 | 文章内容 |
| DATE | 日期 | 2025-02-26 |
| TIME | 时间 | 14:30:00 |
| DATETIME | 日期+时间 | 2025-02-26 14:30:00 |
| TIMESTAMP | 时间戳 | 自动记录时间 |
示例:
- 年龄:
INT - 姓名:
VARCHAR(50) - 价格:
DECIMAL(10,2)(共 10 位,小数点后 2 位) - 生日:
DATE - 注册时间:
DATETIME或TIMESTAMP
5.2 创建表
语法:
CREATE TABLE 表名 (
列名1 数据类型 [约束],
列名2 数据类型 [约束],
...
);
示例:学生表
USE school;
CREATE TABLE students (
id INT, -- 学号
name VARCHAR(50), -- 姓名
gender CHAR(1), -- 性别:男/女
age INT, -- 年龄
class_name VARCHAR(20), -- 班级
birth_date DATE -- 生日
);
示例:商品表(带小数和日期时间)
CREATE TABLE products (
id INT,
name VARCHAR(100),
price DECIMAL(10, 2), -- 价格,如 99.99
stock INT, -- 库存
created_at DATETIME -- 创建时间
);
5.3 查看表结构
DESC students;
或:
DESCRIBE students;
会显示每列的名称、类型、是否可空、默认值、键信息等。
5.4 查看当前库下所有表
SHOW TABLES;
5.5 修改表(了解)
添加一列:
ALTER TABLE students ADD COLUMN phone VARCHAR(20);
修改列类型:
ALTER TABLE students MODIFY COLUMN name VARCHAR(100);
删除一列:
ALTER TABLE students DROP COLUMN phone;
重命名表:
RENAME TABLE students TO student_info;
5.6 删除表
DROP TABLE 表名;
示例:
DROP TABLE products;
6. 增删改查(CRUD)
CRUD = Create(增)、Read(查)、Update(改)、Delete(删)。
6.1 插入数据(Create / 增)
语法:
INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);
示例:插入一条学生记录
INSERT INTO students (id, name, gender, age, class_name, birth_date)
VALUES (1, '张三', '男', 18, '高一1班', '2007-05-15');
- 字符串、日期用单引号括起来。
- 数字不需要引号。
- 列的顺序要和值的顺序一致。
一次插入多条:
INSERT INTO students (id, name, gender, age, class_name, birth_date) VALUES
(2, '李四', '女', 17, '高一2班', '2008-03-20'),
(3, '王五', '男', 18, '高一1班', '2007-08-10'),
(4, '赵六', '女', 17, '高一2班', '2008-01-05');
省略列名(不推荐):
若按表定义顺序给全所有列,可省略列名,但可读性差,易错。
INSERT INTO students VALUES (5, '钱七', '男', 18, '高一1班', '2007-11-22');
6.2 查询数据(Read / 查)
查询所有列:
SELECT * FROM students;
* 表示“所有列”。
查询指定列:
SELECT name, age, class_name FROM students;
给列起别名(AS):
SELECT name AS 姓名, age AS 年龄 FROM students;
6.3 更新数据(Update / 改)
语法:
UPDATE 表名 SET 列1=新值1, 列2=新值2 WHERE 条件;
示例:把学号为 1 的学生年龄改为 19
UPDATE students SET age = 19 WHERE id = 1;
示例:把高一1班所有人的年龄都改为 18
UPDATE students SET age = 18 WHERE class_name = '高一1班';
重要: 不加 WHERE 会更新表中所有行,非常危险!例如:
UPDATE students SET age = 18; -- 所有人的年龄都变成 18!
6.4 删除数据(Delete / 删)
语法:
DELETE FROM 表名 WHERE 条件;
示例:删除学号为 5 的学生
DELETE FROM students WHERE id = 5;
示例:删除高一2班的所有学生
DELETE FROM students WHERE class_name = '高一2班';
重要: 不加 WHERE 会删除表中所有数据!
DELETE FROM students; -- 清空整张表!(表结构还在)
7. 条件与排序
7.1 WHERE 条件
比较运算符: =, != 或 <>, >, <, >=, <=
SELECT * FROM students WHERE age >= 18;
SELECT * FROM students WHERE class_name = '高一1班';
SELECT * FROM students WHERE id != 3;
逻辑运算符: AND, OR, NOT
-- 年龄≥18 且 在高一1班
SELECT * FROM students WHERE age >= 18 AND class_name = '高一1班';
-- 姓名为张三 或 姓名为李四
SELECT * FROM students WHERE name = '张三' OR name = '李四';
-- 不在高一2班
SELECT * FROM students WHERE NOT (class_name = '高一2班');
范围: BETWEEN ... AND ...、IN (...)
-- 年龄在 17 到 18 之间(包含 17 和 18)
SELECT * FROM students WHERE age BETWEEN 17 AND 18;
-- 学号在 1, 2, 3 之中
SELECT * FROM students WHERE id IN (1, 2, 3);
空值判断: IS NULL, IS NOT NULL
SELECT * FROM students WHERE phone IS NULL;
SELECT * FROM students WHERE phone IS NOT NULL;
模糊匹配: LIKE
%:任意多个字符(包括 0 个)_:任意一个字符
-- 姓张的学生
SELECT * FROM students WHERE name LIKE '张%';
-- 名字包含「三」
SELECT * FROM students WHERE name LIKE '%三%';
-- 姓名为 3 个字
SELECT * FROM students WHERE name LIKE '___';
7.2 排序 ORDER BY
语法:
SELECT ... FROM 表名 ORDER BY 列名 [ASC|DESC];
ASC:升序(默认)DESC:降序
示例:按年龄升序
SELECT * FROM students ORDER BY age ASC;
示例:按年龄降序,年龄相同按学号升序
SELECT * FROM students ORDER BY age DESC, id ASC;
7.3 限制条数 LIMIT
语法: LIMIT 数量 或 LIMIT 跳过条数, 取几条
-- 只取前 3 条
SELECT * FROM students ORDER BY id LIMIT 3;
-- 跳过前 2 条,取接下来 3 条(常用于分页)
SELECT * FROM students ORDER BY id LIMIT 2, 3;
8. 约束
约束用于保证数据的正确性和完整性。
8.1 主键(PRIMARY KEY)
- 唯一标识一行,不能重复,不能为 NULL。
- 一张表通常有一个主键(可以是单列或组合多列)。
示例:
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
password VARCHAR(100)
);
8.2 自增(AUTO_INCREMENT)
常与主键配合:插入时不写 id,数据库自动从 1 递增。
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(100)
);
INSERT INTO users (username, password) VALUES ('zhangsan', '123456');
INSERT INTO users (username, password) VALUES ('lisi', 'abcdef');
-- id 会自动为 1, 2, ...
8.3 非空(NOT NULL)
该列不能为空。
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL
);
8.4 唯一(UNIQUE)
该列的值不能重复(可以有多个 NULL,视数据库而定)。
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) UNIQUE
);
8.5 默认值(DEFAULT)
插入时不写该列,则使用默认值。
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200),
view_count INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
8.6 外键(FOREIGN KEY)——了解即可
外键表示“这一列引用另一张表的主键”,用来保证引用关系正确。
示例:订单表引用用户表
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
amount DECIMAL(10,2),
FOREIGN KEY (user_id) REFERENCES users(id)
);
8.7 综合示例:带约束的学生表
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
gender CHAR(1) DEFAULT '男',
age INT,
class_name VARCHAR(20),
birth_date DATE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
9. 索引
索引可以加快查询,但会占用空间,并可能减慢写入。适合在经常用来查询、排序、分组的列上建索引。
9.1 创建索引
建表时创建:
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
INDEX idx_username (username),
INDEX idx_email (email)
);
对已有表创建:
CREATE INDEX idx_name ON students (name);
CREATE INDEX idx_class_age ON students (class_name, age);
9.2 查看索引
SHOW INDEX FROM students;
9.3 删除索引
DROP INDEX idx_name ON students;
10. 多表与连接
实际项目中通常有多张表,通过“关系”连在一起查询。
10.1 示例:学生表 + 成绩表
学生表(已有):
id, name, class_name
成绩表 scores:
CREATE TABLE scores (
id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT, -- 对应 students.id
subject VARCHAR(50), -- 科目
score DECIMAL(5,2) -- 分数
);
INSERT INTO scores (student_id, subject, score) VALUES
(1, '语文', 85),
(1, '数学', 92),
(2, '语文', 78),
(2, '数学', 88);
10.2 内连接(INNER JOIN)
只保留两表都匹配上的行。
语法:
SELECT 列...
FROM 表1
INNER JOIN 表2 ON 表1.某列 = 表2.某列
[WHERE ...];
示例:查每个学生的姓名和每科成绩
SELECT s.name, sc.subject, sc.score
FROM students s
INNER JOIN scores sc ON s.id = sc.student_id;
这里用别名 s 和 sc 简化书写。
10.3 左连接(LEFT JOIN)
以左表为准,右表没有匹配时,右表列显示为 NULL。
SELECT s.name, sc.subject, sc.score
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id;
这样没有成绩的学生也会出现,成绩列是 NULL。
10.4 右连接(RIGHT JOIN)
以右表为准,左表没有匹配时,左表列显示为 NULL。实际中多用 LEFT JOIN,右连接可用“左右表互换 + LEFT JOIN”代替。
11. 聚合与分组
11.1 聚合函数
| 函数 | 说明 | 示例 |
|---|---|---|
| COUNT | 计数 | 人数、条数 |
| SUM | 求和 | 总成绩、总金额 |
| AVG | 平均值 | 平均分 |
| MAX | 最大值 | 最高分 |
| MIN | 最小值 | 最低分 |
示例:
-- 学生总人数
SELECT COUNT(*) FROM students;
-- 某表某列非 NULL 的个数
SELECT COUNT(phone) FROM students;
-- 年龄总和、平均年龄、最大最小年龄
SELECT SUM(age), AVG(age), MAX(age), MIN(age) FROM students;
11.2 分组 GROUP BY
按某一列(或几列)分组,再对每组做聚合。
语法:
SELECT 分组列, 聚合函数(...)
FROM 表名
GROUP BY 分组列
[HAVING 条件];
示例:每个班级的人数
SELECT class_name, COUNT(*) AS 人数
FROM students
GROUP BY class_name;
示例:每个班级的平均年龄
SELECT class_name, AVG(age) AS 平均年龄
FROM students
GROUP BY class_name;
11.3 HAVING
WHERE 在分组前过滤行,HAVING 在分组后过滤“组”。
示例:人数大于 2 的班级
SELECT class_name, COUNT(*) AS 人数
FROM students
GROUP BY class_name
HAVING COUNT(*) > 2;
12. 子查询
子查询就是“查询里再套一个查询”,内层查询的结果可以给外层用。
12.1 在 WHERE 里用子查询
示例:查年龄大于平均年龄的学生
SELECT * FROM students
WHERE age > (SELECT AVG(age) FROM students);
示例:查有成绩记录的学生
SELECT * FROM students
WHERE id IN (SELECT student_id FROM scores);
12.2 在 FROM 里用子查询(派生表)
SELECT t.class_name, t.人数
FROM (
SELECT class_name, COUNT(*) AS 人数
FROM students
GROUP BY class_name
) t
WHERE t.人数 >= 1;
13. 视图
视图是一张“虚拟表”,本质是一条保存好的 SELECT。
好处:简化复杂查询、控制可见列,不存数据,数据仍来自基表。
13.1 创建视图
CREATE VIEW v_student_score AS
SELECT s.id, s.name, s.class_name, sc.subject, sc.score
FROM students s
LEFT JOIN scores sc ON s.id = sc.student_id;
13.2 使用视图
像表一样查询:
SELECT * FROM v_student_score WHERE class_name = '高一1班';
13.3 删除视图
DROP VIEW v_student_score;
14. 常用函数
14.1 字符串
SELECT CONCAT('Hello, ', name) FROM students; -- 拼接
SELECT LENGTH(name) FROM students; -- 长度(字节)
SELECT CHAR_LENGTH(name) FROM students; -- 字符数
SELECT UPPER(name), LOWER(name) FROM students; -- 大小写
SELECT TRIM(' abc '); -- 去首尾空格
SELECT SUBSTRING(name, 1, 2) FROM students; -- 截取
14.2 数值
SELECT ROUND(3.14159, 2); -- 四舍五入,保留 2 位 → 3.14
SELECT CEIL(3.2); -- 向上取整 → 4
SELECT FLOOR(3.8); -- 向下取整 → 3
SELECT ABS(-10); -- 绝对值 → 10
14.3 日期时间
SELECT NOW(); -- 当前日期时间
SELECT CURDATE(); -- 当前日期
SELECT CURTIME(); -- 当前时间
SELECT YEAR(birth_date) FROM students;
SELECT MONTH(birth_date), DAY(birth_date) FROM students;
SELECT DATEDIFF(NOW(), birth_date) FROM students; -- 相差天数
15. 用户与权限(入门)
15.1 创建用户
CREATE USER 'xiaoming'@'localhost' IDENTIFIED BY 'password123';
'xiaoming'@'localhost':用户 xiaoming 只能从本机登录。- 若允许从任意主机登录:
'xiaoming'@'%'(生产环境慎用)。
15.2 授权
-- 把 school 库的所有权限给 xiaoming
GRANT ALL PRIVILEGES ON school.* TO 'xiaoming'@'localhost';
-- 只给查询权限
GRANT SELECT ON school.* TO 'xiaoming'@'localhost';
-- 生效
FLUSH PRIVILEGES;
15.3 收回权限
REVOKE ALL PRIVILEGES ON school.* FROM 'xiaoming'@'localhost';
15.4 删除用户
DROP USER 'xiaoming'@'localhost';
16. 备份与恢复
16.1 备份(导出)
在系统命令行(不要先登录 mysql)执行:
mysqldump -u root -p school > school_backup.sql
会提示输入 root 密码,然后当前目录下生成 school_backup.sql,包含建表语句和数据。
备份所有数据库:
mysqldump -u root -p --all-databases > all_backup.sql
16.2 恢复(导入)
先有数据库(若没有:CREATE DATABASE school;),再导入:
mysql -u root -p school < school_backup.sql
17. 常见问题与最佳实践
17.1 常见错误
- 忘记 WHERE:UPDATE/DELETE 时一定要检查是否写了 WHERE,避免误改/误删全表。
- 字符串引号:字符串、日期必须用单引号,数字不要加引号。
- 中文乱码:建库建表时用
utf8mb4,连接时也指定charset=utf8mb4。
17.2 最佳实践(简要)
- 命名:表名、列名用英文或拼音,见名知意;主键常用
id。 - 主键:每张表尽量有主键,常用自增 INT 或 BIGINT。
- 敏感信息:密码等不要明文存储,要加密(如 bcrypt)。
- 索引:常查、常排序的列可建索引,不要无脑给所有列建索引。
- 备份:重要数据定期用
mysqldump备份。 - SQL 注入:应用层不要拼接 SQL,要用预编译(Prepared Statement)传参。
17.3 学习顺序建议
- 库 → 表 → 增删改查 → WHERE、ORDER BY、LIMIT
- 约束(主键、非空、默认、唯一)
- 聚合与 GROUP BY
- 多表 JOIN
- 子查询、视图
- 索引、用户权限、备份恢复
附录:常用命令速查
| 操作 | 命令示例 |
|---|---|
| 登录 | mysql -u root -p |
| 看库 | SHOW DATABASES; |
| 建库 | CREATE DATABASE 库名; |
| 用库 | USE 库名; |
| 看表 | SHOW TABLES; |
| 看表结构 | DESC 表名; |
| 建表 | CREATE TABLE 表名 (列定义...); |
| 插数据 | INSERT INTO 表名 (列...) VALUES (值...); |
| 查数据 | SELECT 列 FROM 表 [WHERE] [ORDER BY] [LIMIT]; |
| 改数据 | UPDATE 表 SET 列=值 WHERE 条件; |
| 删数据 | DELETE FROM 表 WHERE 条件; |
| 退出 | EXIT; 或 QUIT; |
祝你学习顺利!有问题多查文档、多写示例,动手练几遍就会越来越熟。