MySQL 技术笔记
我们平时用的APP(微信、淘宝)、网站,背后的数据(好友列表、订单记录)都存在类似MySQL的数据库里。它就像一个“智能管家”,帮你管理所有数据,你只需要用SQL指令“指挥”它,不用自己管数据存在电脑的哪个角落。把 MySQL 想象成「电脑里的智能文件柜」—— 数据库是「整个文件柜」,表是「文件柜里的每一本Excel表」,数据是「Excel表里的每一行内容」,SQL语句是「你给文件柜的操作指令」(比如找文件、放文件、改文件)。MySQL 是开源的「关系型数据库管理系统」,本质是「帮你高效存、取、改、删结构化数据」,解决“数据太多存不下、找不着、改易错”的问题。
一、基础概念
1. 数据库与关系型数据库
- 数据库(DB):长期存储在计算机内、有组织、可共享的数据集合。
- 关系型数据库(RDBMS):基于二维表结构存储数据,用 SQL(结构化查询语言)操作,核心特性是ACID(原子性、一致性、隔离性、持久性)。
- 常见代表:MySQL、Oracle、PostgreSQL、SQL Server。
- 核心比喻:
- 数据库 = 图书馆的 “藏书楼”
- 关系型数据库 = 把书按 “分类、作者、书名” 等表格形式整理的藏书楼(Excel 就是最直观的关系型数据库雏形)
- 本质:用 “二维表格” 存数据,表格之间可以通过 “关联字段”(比如 “用户 ID”)建立关系。
2. MySQL 的特点与应用场景
- 特点:开源免费、跨平台(Windows/Linux/macOS)、性能优异、社区活跃、InnoDB 引擎支持高并发。
- 应用场景:Web 应用(电商、社交)、企业级系统、轻量级数据分析、嵌入式系统。
- 特点:
- 开源免费(像 Linux 一样)、性能强、社区活跃
- 轻量级,适合从小网站到大型系统
- 应用场景:
- 网站后台(电商、社交、博客)、企业管理系统、数据分析平台
3. MySQL 的版本与分支
- 官方版本:MySQL 5.7(稳定)、MySQL 8.0(主流,新特性丰富)。
- 分支:
- MariaDB:MySQL 创始人创建,完全兼容 MySQL,性能优化更激进。
- Percona Server:专注性能与高可用,适合企业级场景。
二、安装与配置
1. 不同操作系统下的安装方法
- Windows:下载 MySQL Installer,图形化安装(推荐 “Developer Default”)。
- Linux(CentOS/Ubuntu):
- CentOS:
(或官方 YUM 源)。yum install mysql-server - Ubuntu:
apt-get install mysql-server。
- CentOS:
- macOS:DMG 包安装或 Homebrew:
brew install mysql。
2. 初始化配置与安全设置
- 初始化:Linux 下执行
mysqld --initialize(临时密码在日志中)。 - 启动服务:
systemctl start mysqld(Linux)或服务面板(Windows)。 - 安全加固:执行
mysql_secure_installation(设置 root 密码、删除匿名用户、禁止 root 远程登录、删除测试库)。
3. 常见安装问题排查
- 端口被占用:检查 3306 端口(
netstat -anp | grep 3306),修改my.cnf的port参数。 - 忘记 root 密码:停止服务→
mysqld --skip-grant-tables启动→连接后修改密码:sql
UPDATE mysql.user SET authentication_string=PASSWORD('新密码') WHERE User='root';
4.命令行连接MySQL(打开文件柜的钥匙)
连接MySQL,就是用“账号密码”验证身份,获得操作“文件柜”的权限,常用命令如下(复制就能用):
基础连接(最常用,输入命令后回车,再输密码即可)
mysql -u root -p
指定主机和端口(比如远程连接别人的“文件柜”)
mysql -h 127.0.0.1 -P 3306 -u root -p
新手易误解点:① 输入密码时,屏幕不会显示任何字符(不是没输入,是故意隐藏,防止别人看到);② 端口号3306是MySQL的“默认门牌号”,如果修改过,必须写修改后的端口,否则连不上。
三、数据库操作
1. 创建、删除数据库
- 创建:
⚠️ 新手提示:推荐用 utf8mb4(支持 emoji,utf8 是其子集)。CREATE DATABASE 数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 删除:
DROP DATABASE [IF EXISTS] 数据库名; - 查看 / 切换:
SHOW DATABASES;→USE 数据库名;
2. 字符集与排序规则
- 字符集:定义数据编码(如
utf8mb4、latin1)。决定数据库能存哪些文字(比如utf8mb4支持 emoji,像 “📚”) - 排序规则:定义数据比较规则(如
utf8mb4_unicode_ci不区分大小写,utf8mb4_bin区分大小写)。决定文字怎么排序
- 别用旧的
utf8(最多存 3 字节,emoji 会报错),统一用utf8mb4
3. 数据库备份与恢复
- 逻辑备份(mysqldump):
- 备份:
mysqldump -u root -p 数据库名 > 备份文件.sql - 恢复:
mysql -u root -p 数据库名 < 备份文件.sql(先创建空库)。
- 备份:
- 物理备份:直接复制
/var/lib/mysql数据目录(适合大库,需停服务)。
四、表与数据类型
1. 表的创建、修改与删除
- 创建表:
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, age INT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - 修改表:
- 添加列:
ALTER TABLE 表名 ADD COLUMN 列名 数据类型; - 修改列:
ALTER TABLE 表名 MODIFY COLUMN 列名 新数据类型; - 删除列:
ALTER TABLE 表名 DROP COLUMN 列名;
- 添加列:
- 删除表:
DROP TABLE [IF EXISTS] 表名; - 查看结构:
DESC 表名;/SHOW CREATE TABLE 表名;
2. 常见数据类型
建表时,每个表头(字段)都要指定“数据类型”,类比成“Excel表头的格式”——比如“年龄”表头只能填数字,“姓名”表头只能填文字,否则会乱套。数据类型是「约束数据格式」,确保数据统一,同时节省存储空间(比如存年龄用1个字节就够,不用浪费更多空间)。
| 分类 | 具体类型 | 详细说明 | 通俗比喻 | 核心适用场景 |
|---|---|---|---|---|
| 整数 | TINYINT | 1 字节,小范围整数 | - | 状态标识、短枚举值 |
| 整数 | INT | 4 字节,最常用整数 | 书的数量 | 年龄、ID、常规数量统计 |
| 整数 | BIGINT | 8 字节,超大范围整数 | - | 超大 ID、海量数据计数 |
| 字符串 | VARCHAR(n) | 可变长度字符串,n 为最大长度 | 书名 | 姓名、标题、地址、用户名 |
| 字符串 | TEXT | 不限定长度的长文本 | 书的简介 | 文章内容、详细备注、大段文字 |
| 日期 | DATE | 仅日期,格式 YYYY-MM-DD |
出版日期 | 生日、订单日期、纯日期记录 |
| 日期 | DATETIME | 日期 + 时间,YYYY-MM-DD HH:MM:SS,最常用 |
带时间的出版记录 | 订单创建时间、日志时间、操作时间 |
| 小数 | DECIMAL(m,d) | 精确小数,m 总位数、d 小数位(例:DECIMAL (10,2)) | 商品价格 | 金额、薪资、高精度价格 / 数值 |
新手易错点:
VARCHAR(n)里的n是 “字符数” 不是 “字节数”(比如VARCHAR(10)能存 10 个汉字)- 金额别用
FLOAT/DOUBLE(会有精度丢失),必须用DECIMAL
具体介绍
2.1. 数值类型(只能存数字,对应Excel的“数字格式”)
|
类型 |
通俗说明 |
类比 |
适用场景 |
新手避坑 |
|---|---|---|---|---|
|
INT |
普通整数,范围-21亿~21亿,占4个字节 |
Excel里的“常规数字”(不存小数) |
年龄、数量、普通ID(比如学生ID) |
别用INT存超大数字(比如订单号超过21亿),会存不下,改用BIGINT |
|
BIGINT |
大整数,范围极大,占8个字节 |
Excel里的“长数字” |
订单号、用户ID(数据量大时) |
不用盲目用BIGINT,存小数字用INT更省空间 |
|
DECIMAL(M,D) |
精确小数,M=总位数,D=小数位数(比如DECIMAL(10,2)就是最多10位,2位小数) |
Excel里的“货币格式”“保留2位小数” |
金额、价格(比如39.99元、100.00元) |
别用INT存金额(会丢小数),别用FLOAT/DOUBLE(有精度误差,比如0.1+0.2≠0.3) |
2.2. 字符串类型(存文字/符号,对应Excel的“文本格式”)
|
类型 |
通俗说明 |
类比 |
适用场景 |
新手避坑 |
|---|---|---|---|---|
|
VARCHAR(n) |
变长字符串,n是最大长度,存多少内容占多少空间(比如存“张三”占2个字符,存“李四”也占2个) |
Excel里的“可变长度文本”(写多少算多少) |
姓名、地址、手机号(长度不固定) |
n别设太大(比如VARCHAR(1000)存姓名),浪费空间;也别设太小(比如VARCHAR(2)存“张伟”,会存不下) |
|
CHAR(n) |
定长字符串,n是固定长度,不管存多少内容,都占n个空间(比如CHAR(2)存“张”,也占2个字符,多余的补空格) |
Excel里的“固定长度文本”(必须填够长度,不够补空格) |
性别(男/女,固定1个字符)、状态(0/1,固定1个字符) |
别用CHAR存长度不固定的内容(比如地址),会浪费大量空间 |
|
TEXT |
长文本,最多存65535个字符(大概几万字) |
Excel里的“备注栏”(存很长的文字) |
文章内容、备注、详细描述 |
别用TEXT存短内容(比如姓名),查询速度比VARCHAR慢 |
2.3. 日期时间类型(存日期/时间,对应Excel的“日期时间格式”)
|
类型 |
格式 |
通俗说明 |
适用场景 |
|---|---|---|---|
|
DATE |
YYYY-MM-DD |
只存日期,不存时间(比如2026-02-15) |
生日、注册日期(只需要知道哪一天) |
|
DATETIME |
YYYY-MM-DD HH:MM:SS |
存日期+时间(比如2026-02-15 14:30:00),不会自动更新 |
订单创建时间、用户登录时间(需要精确到分秒,且固定不变) |
|
TIMESTAMP |
YYYY-MM-DD HH:MM:SS |
存日期+时间,会自动更新(比如修改数据时,自动改成当前时间),占空间比DATETIME小 |
数据最后修改时间(不需要手动改,自动记录) |
3. 约束
约束核心本质是「给表的字段加“限制条件”」,保证数据准确、不混乱——类比成Excel表的“数据验证”(比如年龄只能填1-100,姓名不能空)。约束是“建表时/修改表时”加的,不是给数据加的;加了约束后,不符合规则的数据,无法插入/修改。
|
约束 |
关键字 |
通俗类比 |
核心作用(本质) |
新手避坑 |
|---|---|---|---|---|
|
主键 |
PRIMARY KEY |
Excel表的“身份证号”列 |
唯一标识每一行数据(非空且唯一),一张表只能有1个主键 |
主键不能重复、不能空;常用INT+自增(AUTO_INCREMENT)当主键 |
|
自增 |
AUTO_INCREMENT |
Excel表的“自动编号”(1、2、3...) |
主键自动增长,不用手动输入(插入数据时,主键填NULL即可) |
自增只能用于“数值类型的主键”(比如INT、BIGINT),不能用于VARCHAR |
|
非空 |
NOT NULL |
Excel表的“必填项” |
字段值不能为空(必须填内容) |
别给“可选字段”加非空约束(比如学生的“备注”,可能没人填),否则会插入失败 |
|
唯一 |
UNIQUE |
Excel表的“手机号”列(不能有重复) |
字段值必须唯一(不能重复),但可以空 |
唯一≠非空(比如手机号可以空,但如果填了,就不能和别人重复) |
|
默认 |
DEFAULT |
Excel表的“默认值”(比如性别默认填“男”) |
字段未赋值时,自动使用默认值 |
默认值要和字段类型匹配(比如性别是CHAR(1),默认值不能是“男性”,太长) |
|
外键 |
FOREIGN KEY |
两个Excel表的“关联列”(比如学生表的“班级ID”和班级表的“班级ID”) |
关联两个表,保证数据一致性(比如不能给学生填一个不存在的班级ID) |
新手初期可先不深入,重点掌握前5个;外键会影响删除/修改,容易出错 |
五、SQL 基本语法
SQL是和MySQL沟通的“语言”,所有操作都靠它,按功能分4类,类比成“对文件柜的4种操作”,一看就懂:
|
分类 |
全称 |
核心类比 |
作用(本质) |
常用关键字 |
|---|---|---|---|---|
|
DDL |
数据定义语言 |
给文件柜“搭架子” |
定义数据库、表的结构(比如新建文件柜、新建Excel表、修改Excel表头) |
CREATE(新建)、ALTER(修改)、DROP(删除) |
|
DML |
数据操作语言 |
给Excel表“填/改/删内容” |
操作表中的具体数据(新增一行内容、修改某行、删除某行) |
INSERT(新增)、UPDATE(修改)、DELETE(删除) |
|
DQL |
数据查询语言 |
从Excel表里“找内容” |
查询表中的数据(最常用,比如找所有18岁的学生、找张三的手机号) |
SELECT(查询) |
|
DCL |
数据控制语言 |
给别人“开文件柜权限” |
控制用户的操作权限(比如允许某人看表、禁止某人改数据) |
GRANT(授权)、REVOKE(回收权限) |
新手易误解点:分不清DDL和DML——DDL改“架子”(比如给Excel表加个表头),DML改“内容”(比如给Excel表填一行数据);DDL操作后,表结构会变,DML操作后,表结构不变,只变内容。
1. DML(数据操作语言)
SELECT(查询)
比喻:从书架上 “找书”
-- 基础查询
SELECT username, age FROM users WHERE age >= 18 ORDER BY age DESC LIMIT 0, 10;
-- 聚合函数
SELECT COUNT(*) AS 总人数, AVG(age) AS 平均年龄 FROM users;
-- 连接查询
SELECT u.username, o.order_id FROM users u INNER JOIN orders o ON u.id = o.user_id;
代码示例:
SELECT * FROM books WHERE author = '金庸'; -- 查金庸的所有书
SELECT title, price FROM books ORDER BY price DESC LIMIT 10; -- 查最贵的 10 本书
INSERT(插入)
比喻:往书架上 “放书”
代码:
INSERT INTO books (title, author, price)
VALUES ('射雕英雄传', '金庸', 59.9);
UPDATE(更新)
比喻:把书的 “价格标签” 改了
代码:
UPDATE books SET price = 49.9 WHERE id = 1;
新手易错点:UPDATE 必须加 WHERE,否则会把全表都改了!
DELETE(删除)
比喻:把书从书架上 “拿走”
代码:
DELETE FROM books WHERE id = 1;
新手易错点:DELETE 必须加 WHERE,否则会把全表数据都删了!
2. DDL(数据定义语言)
DDL核心:操作“结构”,不碰“内容”——比如新建文件柜(数据库)、新建Excel表(表)、修改Excel表头(字段)、删除文件柜/表。DDL操作不可逆(比如删除表,表和里面的所有数据都会消失,无法恢复),操作前一定要确认!
- 创建 / 修改 / 删除数据库、表(见前文)。
- 创建索引:
CREATE INDEX idx_username ON users (username); - 前面 “数据库操作” 和 “表操作” 里的
CREATE、ALTER、DROP都是 DDL
1. 数据库操作(管理“文件柜”)
-- 1. 新建数据库(文件柜):IF NOT EXISTS 表示“如果没有这个文件柜,再新建”,避免报错 CREATE DATABASE IF NOT EXISTS mydb;
-- 2. 使用数据库(打开文件柜,后续所有操作都针对这个文件柜) USE mydb;
-- 3. 删除数据库(删除整个文件柜,里面的所有表和数据都会消失,慎用!) DROP DATABASE IF EXISTS mydb;
2. 表操作(管理“Excel表”)
(1)创建表(新建Excel表,指定表头和规则)
类比:新建一张Excel表,先写好表头(比如id、姓名、年龄),再规定每个表头的规则(比如姓名不能为空、年龄只能是数字)。
-- 示例:创建“学生表”(student),包含5个表头(字段) CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT,
-- 主键(身份证号),自增(自动编号,不用手动填) name VARCHAR(20) NOT NULL,
-- 姓名,非空(必须填,不能空着) age INT,
-- 年龄,可空(可以不填) gender CHAR(1) DEFAULT '男',
-- 性别,默认值(不填的话,自动填“男”) phone VARCHAR(11) UNIQUE,
-- 手机号,唯一(不能有两个一样的手机号) create_time DATETIME -- 创建时间 );
(2)修改表(修改Excel表的表头)
-- 1. 给表加一个表头(字段):给学生表加“地址”字段 ALTER TABLE student ADD address VARCHAR(50);
-- 2. 修改表头规则(字段类型/约束):把“年龄”改成更小的类型(TINYINT,占1个字节) ALTER TABLE student MODIFY age TINYINT;
-- 3. 删除表头(字段):删除“地址”字段 ALTER TABLE student DROP COLUMN address;
-- 4. 修改表名(Excel表重命名):把student改成stu ALTER TABLE student RENAME TO stu;
(3)删除表(删除Excel表)
-- 删除学生表,IF EXISTS 避免“表不存在”报错(删除后,表中所有数据都消失) DROP TABLE IF EXISTS student;
3. DCL(数据控制语言)
比喻:给不同的人 “发借书证”,有的只能看书,有的能买书
- 授权:
-
GRANT SELECT, INSERT ON mydb.* TO 'user'@'localhost' IDENTIFIED BY '密码'; FLUSH PRIVILEGES; - 撤销:
-
REVOKE INSERT ON mydb.* FROM 'user'@'localhost'; - 代码示例:
CREATE USER 'zhangsan'@'localhost' IDENTIFIED BY '123456'; -- 创建用户 GRANT SELECT, INSERT ON my_library.* TO 'zhangsan'@'localhost'; -- 给用户授权 REVOKE INSERT ON my_library.* FROM 'zhangsan'@'localhost'; -- 收回权限
4.DML 操作:(数据增删改)
DML核心操作“数据内容”,不碰“表结构”——类比成给Excel表填一行内容、改一行内容、删一行内容,表的表头不变。修改/删除数据时,务必加WHERE条件,否则会操作全表数据!
1. 插入数据(INSERT,给Excel表填内容)
-- 1. 插入单条数据(指定字段,推荐!不容易出错) INSERT INTO student (name, age, phone) VALUES ('张三', 18, '13800138000');
-- 2. 插入单条数据(所有字段,自增主键填NULL,会自动编号) INSERT INTO student VALUES (NULL, '李四', 20, '女', '13900139000', NOW()); -- NOW() 是MySQL自带函数,自动获取当前日期时间
-- 3. 批量插入(一次填多行,比单条插入高效) INSERT INTO student (name, age) VALUES ('王五', 19), ('赵六', 21);
新手易误解点:① 插入的数据类型要和字段类型匹配(比如给age填“十八”,会报错,因为age是INT类型);② 非空字段必须填(比如name加了NOT NULL,插入时不填name,会报错)。
2. 修改数据(UPDATE,改Excel表的内容)
-- 1. 修改单条数据(务必加WHERE!只改“张三”的年龄) UPDATE student SET age = 22 WHERE name = '张三';
-- 2. 修改多个字段(改“张三”的年龄和性别) UPDATE student SET age = 23, gender = '女' WHERE id = 1;
-- ❌ 错误示例(没有WHERE,会修改表中所有学生的年龄!) UPDATE student SET age = 22;
新手易误解点:① 没有WHERE条件,会修改全表数据(比如上面的错误示例,所有学生年龄都会变成22);② 可以同时修改多个字段,用逗号分隔。
3. 删除数据(DELETE,删Excel表的内容)
-- 1. 删除单条数据(务必加WHERE!只删id=1的学生) DELETE FROM student WHERE id = 1;
-- 2. 删除所有数据(慎用!删完表结构还在,数据全没,可回滚) DELETE FROM student;
-- 3. 清空表(TRUNCATE,比DELETE快,删完重置自增ID,不可回滚) TRUNCATE TABLE student;
核心区别(新手必记):DELETE 是“逐行删除”(可撤销,比如删错了能恢复),TRUNCATE 是“直接删表重建”(不可撤销,且自增ID会重置为1);两者都不会删除表结构,只删数据。
5.DQL 操作:(数据查询)
DQL核心用SELECT查询数据,本质是「从表中“筛选、提取”符合条件的内容」——类比成Excel的“筛选”“排序”“求和”功能,是MySQL最常用、最重要的操作。查询不会修改任何数据(只是“看”数据),放心大胆练;所有查询语句,核心都是“SELECT 要查的内容 FROM 表名 WHERE 筛选条件”。
1. 基础查询(简单“看”数据)
-- 1. 查询所有字段(* 代表所有表头,简单但效率低,不推荐大量数据使用) SELECT * FROM student;
-- 2. 查询指定字段(推荐!只查需要的内容,效率高) SELECT name, age FROM student;
-- 3. 字段别名(AS 可省略,给表头起个好懂的名字,方便查看) SELECT name AS 姓名, age 年龄 FROM student; -- 查出来的表头是“姓名”“年龄”
-- 4. 去重查询(DISTINCT,去掉重复的内容) SELECT DISTINCT gender FROM student; -- 只查“男”“女”,不会重复显示
2. 条件查询(WHERE,筛选符合条件的内容)
类比:Excel的“筛选”功能,只显示符合条件的行(比如只显示年龄>18的学生)。
-- 1. 比较运算符(=、>、<、>=、<=、!= 或 <>) SELECT * FROM student WHERE age > 18; -- 查所有18岁以上的学生 SELECT * FROM student WHERE gender != '男'; -- 查所有不是男性的学生
-- 2. 逻辑运算符(AND 且、OR 或、NOT 非) SELECT * FROM student WHERE age > 18 AND gender = '女'; -- 18岁以上且是女生 SELECT * FROM student WHERE age < 18 OR age > 20; -- 18岁以下或20岁以上
-- 3. 模糊查询(LIKE,查“相似”的内容,%匹配任意字符,_匹配单个字符) SELECT * FROM student WHERE name LIKE '张%'; -- 姓张的(张一、张三、张三丰都能查到) SELECT * FROM student WHERE name LIKE '张_'; -- 姓张且名字只有2个字(张三、张伟,张小三查不到)
-- 4. 范围查询(BETWEEN...AND 范围内,IN 固定集合) SELECT * FROM student WHERE age BETWEEN 18 AND 20; -- 18≤年龄≤20 SELECT * FROM student WHERE age IN (18, 20, 22); -- 年龄是18、20、22中的一个
-- 5. 空值判断(IS NULL 是空,IS NOT NULL 不是空) SELECT * FROM student WHERE phone IS NULL; -- 查手机号为空的学生 SELECT * FROM student WHERE phone IS NOT NULL; -- 查手机号不为空的学生
新手避坑:判断空值不能用 = NULL 或 != NULL,必须用 IS NULL / IS NOT NULL(因为NULL不是“空字符串”,是“没有值”,无法用等于/不等于判断)。
3. 排序查询(ORDER BY,给查询结果排序)
类比:Excel的“排序”功能,按某一列升序/降序排列(比如按年龄从小到大排)。
-- 1. 按年龄升序(ASC 可省略,默认升序:从小到大) SELECT * FROM student ORDER BY age ASC;
-- 2. 按年龄降序(DESC,从大到小) SELECT * FROM student ORDER BY age DESC;
-- 3. 多字段排序(先按年龄降序,年龄相同再按ID升序) SELECT * FROM student ORDER BY age DESC, id ASC;
4. 聚合函数(统计数据,类比Excel的“求和、平均值、计数”)
核心:对一列数据进行“统计计算”,自动忽略NULL值(比如某行age为空,不会计入统计)。
|
函数 |
通俗作用 |
示例(查学生表) |
|---|---|---|
|
COUNT(字段) |
统计非空记录数(比如统计有多少个学生填了年龄) |
SELECT COUNT(age) FROM student; |
|
COUNT(*) |
统计所有记录数(不管有没有空值,最常用,比如统计学生总数) |
SELECT COUNT(*) FROM student; |
|
SUM(字段) |
求和(比如统计所有学生的年龄总和) |
SELECT SUM(age) FROM student; |
|
AVG(字段) |
求平均值(比如统计学生的平均年龄) |
SELECT AVG(age) FROM student; |
|
MAX(字段) |
求最大值(比如统计最大年龄) |
SELECT MAX(age) FROM student; |
|
MIN(字段) |
求最小值(比如统计最小年龄) |
SELECT MIN(age) FROM student; |
新手易误解点:COUNT(*) 和 COUNT(字段) 的区别——COUNT(*) 统计所有行(包括空值),COUNT(字段) 只统计该字段非空的行(比如age有3行空值,就会少统计3行)。
5. 分组查询(GROUP BY,按“类别”统计)
类比:Excel的“分类汇总”(比如按性别分组,统计男生多少人、女生多少人)。
核心规则(新手必记):分组后,SELECT 后面只能写「分组字段」和「聚合函数」,不能写其他字段;分组前过滤用WHERE,分组后过滤用HAVING。
-- 1. 按性别分组,统计每组人数(最常用) SELECT gender, COUNT(*) FROM student GROUP BY gender;
-- 2. 按性别分组,统计每组平均年龄,且只显示平均年龄>19的组 SELECT gender, AVG(age) avg_age -- avg_age 是别名,方便后续过滤 FROM student GROUP BY gender -- 按性别分组 HAVING avg_age > 19; -- 分组后过滤(只留平均年龄>19的组)
新手避坑:WHERE 和 HAVING 的区别——① WHERE 用在 GROUP BY 前面,过滤“分组前的数据”,不能用聚合函数;② HAVING 用在 GROUP BY 后面,过滤“分组后的数据”,可以用聚合函数。
6. 分页查询(LIMIT,分批查看数据)
类比:Excel的“分页预览”(比如数据太多,一页显示不下,分两页看),常用于APP/网站的“分页”(比如第1页显示10条,第2页显示下10条)。
语法:LIMIT 偏移量, 每页条数(偏移量 = (页码-1)*每页条数,新手直接记这个公式)
-- 1. 查询第1页(每页2条,偏移量=0,(1-1)*2=0) SELECT * FROM student LIMIT 0, 2;
-- 2. 查询第2页(每页2条,偏移量=2,(2-1)*2=2) SELECT * FROM student LIMIT 2, 2;
-- 3. 查询第3页(每页2条,偏移量=4,(3-1)*2=4) SELECT * FROM student LIMIT 4, 2;
6.常用函数(MySQL的“小工具”,简化操作)
类比:Excel的“函数”(比如SUM、ROUND),MySQL也有自带的小工具,帮你快速处理数据,重点记常用的即可。
1. 字符串函数(处理文字)
-- 1. 拼接字符串(CONCAT,比如把“姓名:”和name拼接) SELECT CONCAT('姓名:', name) FROM student;
-- 2. 字符串长度(LENGTH,比如查姓名有几个字) SELECT LENGTH(name) FROM student;
-- 3. 转大写/小写(UPPER大写,LOWER小写) SELECT UPPER(name), LOWER(name) FROM student;
2. 数值函数(处理数字)
-- 1. 四舍五入(ROUND(数字, 保留小数位数)) SELECT ROUND(3.1415, 2); -- 结果:3.14(保留2位小数)
-- 2. 向上取整(CEIL,比如3.1取4) SELECT CEIL(3.1); -- 结果:4
-- 3. 向下取整(FLOOR,比如3.9取3) SELECT FLOOR(3.9); -- 结果:3
3. 日期函数(处理日期时间,最常用)
-- 1. 获取当前日期+时间(NOW(),常用在插入数据时) SELECT NOW(); -- 结果:2026-02-15 14:30:00
-- 2. 获取当前日期(CURDATE()) SELECT CURDATE(); -- 结果:2026-02-15
-- 3. 获取年、月、日 SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW()); -- 结果:2026、2、15
六、索引与优化
1. 索引类型
- B-Tree 索引:InnoDB 默认,适合范围查询、排序(最常用)。就像书的 “目录”,通过目录快速找到页码(最常用的索引)
- 哈希索引:就像“字典的哈希表”,查找速度极快,但不支持范围查询(比如 “查价格在 50-100 之间的书”)
- 全文索引:用于全文搜索(如文章内容)。就像“搜索引擎”,用于快速搜索文章里的关键词(比如搜 “射雕” 能找到《射雕英雄传》)
- 复合索引:多列索引(遵循最左前缀原则,如
(username, age))。
2. 索引创建与管理
CREATE INDEX idx_username_age ON users (username, age); -- 复合索引
SHOW INDEX FROM users; -- 查看索引
DROP INDEX idx_username ON users; -- 删除索引
新手易错点:
- 索引不是越多越好!索引会占用空间,且会减慢
INSERT/UPDATE/DELETE的速度(像给书编目录会花时间) - 只给经常查询的字段建索引(比如 “作者”、“书名”)
3. 查询优化(EXPLAIN)
- 核心工具:
EXPLAIN - 比喻:给查询 “拍 X 光片”,看 MySQL 是怎么执行的
- 代码示例:
EXPLAIN SELECT * FROM books WHERE author = '金庸'; - 重点关注:
- type:
const(主键 / 唯一索引)>ref(普通索引)>ALL(全表扫描,需优化)。 - key:实际使用的索引(NULL 表示未用到)。
- Extra:
Using index(覆盖索引,好);Using filesort(需优化)。
- type:
七、事务与锁机制
1. ACID 特性与隔离级别
-
ACID 特性(事务的 “四大金刚”)
- 原子性(Atomicity):比喻:“转账” 要么全成功(A 扣钱 B 加钱),要么全失败(回到原状)
- 一致性(Consistency):比喻:转账前后,A+B 的总钱数不变
- 隔离性(Isolation):比喻:两个转账操作互不干扰(像在两个独立的房间里操作)
- 持久性(Durability):比喻:转账成功后,数据永久保存(即使断电也不丢)
- 事务控制:
START TRANSACTION; -- 开启事务 UPDATE accounts SET balance=balance-100 WHERE id=1; UPDATE accounts SET balance=balance+100 WHERE id=2; COMMIT; -- 提交(成功)/ ROLLBACK;(回滚,失败) - 隔离级别(从低到高):
- 读未提交 → 读已提交(Oracle 默认)→ 可重复读(MySQL InnoDB 默认) → 串行化。
| 级别 | 问题 | 说明 |
|---|---|---|
| 读未提交 | 脏读(读到未提交的数据) | 几乎不用 |
| 读提交 | 不可重复读 | Oracle 默认 |
| 可重复读 | 幻读(像幻觉一样多了行) | MySQL 默认(InnoDB) |
| 串行化 | 无问题,但性能差 | 像排队一样,一个一个来 |
2. 锁的类型
- 表锁:锁定全表(MyISAM),并发差。就像把整个房间锁了,其他人都进不来(MyISAM 用)
- 行锁:锁定行(InnoDB),并发好。只锁某一本书,其他人可以拿其他书(InnoDB 用)
- 共享锁(S 锁):读锁,
SELECT ... LOCK IN SHARE MODE; - 排他锁(X 锁):写锁,
SELECT ... FOR UPDATE;(UPDATE/DELETE 自动加)。
3. 死锁分析与避免
- 比喻:两个人互相等对方手里的书(A 等 B 的《射雕》,B 等 A 的《神雕》)
- 分析:
SHOW ENGINE INNODB STATUS;(查看死锁日志)。 - 避免:事务小而快、按相同顺序访问行、用索引减少锁范围。
八、存储引擎
1. InnoDB 与 MyISAM 对比
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 事务 | ✅ 支持 | ❌ 不支持 |
| 锁 | 行锁(高并发) | 表锁(并发差) |
| 外键 | ✅ 支持 | ❌ 不支持 |
| 适用场景 | 高并发、电商、金融 | 读多写少、博客、新闻 |
⚠️ 新手提示:默认用 InnoDB(MySQL 5.5 + 默认)。
2. 引擎选择与切换
- 选择原则:
- 需要事务、外键、并发高 → 选 InnoDB(默认)
- 只读、查询快 → 选 MyISAM
- 建表指定:
CREATE TABLE 表名 (...) ENGINE=MyISAM; - 修改引擎:
ALTER TABLE 表名 ENGINE=InnoDB;(大表需谨慎)。
九、高级功能
1. 视图与存储过程
视图:虚拟表,简化查询:
比喻:“窗户”,透过窗户只能看到你想看的部分数据(虚拟表,不存实际数据)
CREATE VIEW v_users_adult AS SELECT username, age FROM users WHERE age >= 18;
SELECT * FROM v_users_adult;
存储过程:预编译 SQL,复用:
比喻:“预存的菜谱”,把一系列 SQL 语句存起来,调用时直接执行
DELIMITER //
CREATE PROCEDURE get_user_by_age(IN p_age INT)
BEGIN
SELECT * FROM users WHERE age = p_age;
END //
DELIMITER ;
CALL get_user_by_age(20);
2. 触发器与事件调度
- 触发器:表事件自动执行(慎用,影响性能)。就像“自动报警器”,当你插入 / 更新 / 删除数据时,自动执行一段 SQL
- 事件调度:定时任务(类似 cron):
CREATE EVENT delete_old_logs ON SCHEDULE EVERY 1 DAY DO DELETE FROM log WHERE create_time < DATE_SUB(NOW(), INTERVAL 7 DAY);
3. 分区表与分库分表
- 分区表:大表拆小表(按日期 / 范围),对用户透明。
- 分库分表:数据量亿级时用(如 ShardingSphere、MyCat)。
十、性能调优
1. 服务器参数优化(my.cnf)
innodb_buffer_pool_size:缓冲池大小(物理内存的 50%-75%)。innodb_flush_log_at_trx_commit:1(安全)/ 0(性能)/ 2(折中)。max_connections:最大连接数(500-1000)。
2. 慢查询日志分析
- 开启(my.cnf):
slow_query_log = ON long_query_time = 2 - 分析:
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log(取前 10 慢 SQL)。
3. 连接池与缓存
- 应用层用连接池(Druid、HikariCP)。
- 热点数据用 Redis/Memcached 缓存,减少 MySQL 压力。
十一、安全与权限
1. 用户管理与权限分配
- 创建用户:
CREATE USER 'admin'@'%' IDENTIFIED BY '强密码'; - 最小权限原则:只给需要的权限(如
GRANT SELECT ON mydb.* TO 'user'@'localhost';)。
2. 数据加密与 SQL 注入防范
- 密码加密:应用层用 bcrypt/Argon2(不要用 MySQL 的
PASSWORD())。 - SQL 注入:用预编译语句(如 MyBatis 的
#{}, 不要拼接 SQL)。就像防止 “坏人” 在借书证上写恶意代码(比如' OR '1'='1)- 防范方法:
- 用 “预处理语句”(PreparedStatement),别拼接 SQL
- 代码示例(Java JDBC):
String sql = "SELECT * FROM books WHERE author = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, "金庸"); // 自动转义,防止注入
十二、备份与高可用
1. 备份工具
- mysqldump:逻辑备份(小库)。
- XtraBackup:物理备份(大库,热备)。
2. 主从复制
- 原理:Master 写 Binlog → Slave I/O 线程读入中继日志 → Slave SQL 线程重放。
- 作用:读写分离、数据备份。
3. 集群方案
- MySQL Group Replication(MGR):官方多主集群。
- Galera Cluster:成熟的同步多主集群。
十三、常见问题
- 连接数过多:修改
max_connections,检查连接池释放。 - 大表优化:加索引、分区、分库分表、归档历史数据。
- 数据不一致:检查主从延迟、
innodb_flush_log_at_trx_commit参数。
十四、工具与生态
- 管理工具:MySQL Workbench(官方)、Navicat、DBeaver。
- 监控:Prometheus + Grafana、Percona PMM。
- ORM:MyBatis(国内常用)、Hibernate。
十五、未来趋势
- MySQL 8.0 新特性:窗口函数、CTE、隐藏索引、降序索引、角色。
- 云数据库:AWS RDS、阿里云 RDS(免运维、高可用)。
- 数据库对比:
- PostgreSQL:适合复杂查询、数据分析。
- MongoDB:适合灵活 schema、高并发写(日志、社交)。
新手避坑总结
坑1:修改/删除数据忘加WHERE条件 → 直接修改/删除全表数据,操作前先备份,务必加WHERE!
坑2:判断空值用 = NULL / != NULL → 错误!必须用 IS NULL / IS NOT NULL(NULL不是空字符串)。
坑3:用INT存金额、价格 → 错误!会丢小数,用DECIMAL(M,D)(精确小数)。
坑4:分不清VARCHAR和CHAR → 长度不固定用VARCHAR(省空间),长度固定用CHAR(查得快)。
坑5:分组查询时,SELECT后面写了非分组、非聚合的字段 → 报错!分组后只能查分组字段和聚合函数。
坑6:用WHERE过滤聚合函数结果 → 错误!WHERE不能用聚合函数,用HAVING(分组后过滤)。
坑7:自增主键手动填值 → 没必要!插入时填NULL,MySQL会自动编号,手动填容易重复。
坑8:删除表用DELETE → 删全表数据用DELETE(可回滚),清空表+重置自增用TRUNCATE(不可回滚)。
坑9:查询用SELECT * → 效率低!只查需要的字段(比如SELECT name, age),尤其是数据量大时。
坑10:非空字段插入时不赋值 → 报错!非空约束(NOT NULL)的字段,必须填内容,或设默认值。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)