零基础从入门到精通MySQL(上篇):筑基篇——吃透核心概念与基础操作,打通SQL入门第一关

你是否也有过这样的经历:

想入行后端开发、数据分析、测试运维,却卡在MySQL这道坎,对着满屏的SQL语句无从下手?

背了无数遍CRUD,真到写业务SQL时,要么逻辑混乱写不出来,要么跑起来巨慢被leader吐槽?

面试时被问到MySQL的基础概念就支支吾吾,连char和varchar的核心区别都说不清楚?

别慌,这不是你笨,而是你没有找到一套成体系、从零基础循序渐进的学习路径。

本系列《零基础从入门到精通MySQL》,将分为**上篇(筑基篇)、中篇(进阶篇)、下篇(精通篇)、附加篇(面试八股文全集)**四大模块,从最基础的环境搭建、核心概念,到进阶的索引、事务、锁机制,再到高阶的性能优化、集群架构,最后配套全覆盖的面试八股文,带你一步一个脚印,从SQL小白成长为MySQL实战高手。

本篇作为系列的开篇------筑基篇,我们将彻底抛弃碎片化的知识点,从零开始,帮你打牢MySQL的核心地基。学完本篇,你将能独立完成数据库、表的规范设计与维护,熟练写出90%业务场景下的基础SQL语句,彻底摆脱"只会背命令,不懂为什么"的困境。


系列整体规划(提前锁定学习路径)

  1. 上篇(筑基篇):MySQL核心认知、环境全场景搭建、核心数据模型、基础SQL语法(DDL/DML/DQL基础/DCL)、单表查询全解
  2. 中篇(进阶篇):多表关联查询、子查询、视图、存储过程、函数、触发器、事务核心原理与ACID特性
  3. 下篇(精通篇):索引底层原理与设计规范、锁机制、MVCC多版本并发控制、执行计划解析、SQL性能优化、集群架构、备份与恢复
  4. 附加篇(八股文全集):从基础到高阶全覆盖的MySQL面试题,附标准答案与答题思路,适配校招、社招全场景

第一章 先搞懂:MySQL到底是什么?为什么非学不可?

1.1 MySQL的核心定位

MySQL是一款开源免费的关系型数据库管理系统(RDBMS),由瑞典MySQL AB公司开发,目前隶属于Oracle。所谓关系型数据库,就是用二维表格的形式来组织和存储数据,通过行和列的结构化方式,实现数据的高效管理和关联查询。

为什么说MySQL是入行IT行业的必修课?

  • 市场占有率第一:互联网行业的标配数据库,淘宝、京东、字节、腾讯等大厂的核心业务均基于MySQL构建,校招、社招后端、数分、测试、运维岗位,MySQL是100%的必考内容
  • 开源轻量,生态完善:社区活跃,文档丰富,有大量的配套工具和解决方案,学习成本低,部署维护简单
  • 跨平台兼容:支持Windows、Linux、MacOS全平台,适配Docker、K8s等容器化部署,无论是本地开发还是线上生产都能无缝适配
  • 功能强大,扩展性强:支持千万级数据量的稳定运行,插件式存储引擎架构,支持事务、索引、高可用集群等企业级特性

1.2 MySQL极简核心架构(零基础先建立全局认知)

很多人学MySQL只盯着SQL语句,却不知道自己写的SQL在MySQL里是怎么执行的,导致遇到问题无从排查。这里我们先给MySQL的架构做个极简拆解,先建立整体认知,后续章节会逐步深入:

MySQL的核心架构分为3层,从上到下依次是:

  1. 连接层:负责客户端连接管理、权限验证、安全校验。比如你用Navicat、DBeaver、代码里的JDBC连接数据库,都是这一层在处理,同时会验证你的用户名、密码、主机访问权限。
  2. 服务层:MySQL的核心SQL处理层,你写的所有SQL语句,都是在这里完成解析、优化、执行的。包括SQL解析器、查询优化器、执行器、缓存组件等,核心功能都在这一层实现。
  3. 存储引擎层 :负责数据的实际存储和提取,是MySQL的底层核心。MySQL的特色就是插件式存储引擎,不同的存储引擎有不同的特性,最常用的就是InnoDB(MySQL5.5之后的默认存储引擎,支持事务、行锁、外键)和MyISAM(不支持事务,仅支持表锁,现在基本被淘汰)。

简单来说:你写的SQL语句,先通过连接层验证身份,再到服务层解析优化成执行计划,最后通过存储引擎层去磁盘上读写数据。


第二章 零基础零踩坑:MySQL环境全场景搭建

学MySQL的第一步,就是搭建一套属于自己的学习环境,很多人在这里就因为各种安装报错放弃了。这里我们覆盖Windows、MacOS、Linux、Docker四大场景,一步一步带你完成安装,全程零踩坑。

2.1 版本选择

优先选择MySQL 8.0.x 稳定版,原因如下:

  • MySQL 5.7已经停止官方维护,后续不会有安全更新,企业正在逐步迁移至8.0
  • 8.0版本在性能、安全性、功能上有巨大提升,优化了查询优化器、支持窗口函数、CTE、原子DDL等高级特性
  • 现在企业招聘的核心要求都是熟练使用MySQL8.0,学习8.0可以直接匹配企业需求

2.2 Windows环境安装

  1. 下载安装包:进入MySQL官网,下载MySQL Installer for Windows(社区版),选择完整安装包。
  2. 安装步骤
    • 打开安装包,选择Developer Default(开发者默认配置,包含服务端、客户端、开发工具等),点击下一步
    • 安装依赖:如果提示缺少VC++运行库,点击安装即可,完成后继续下一步
    • 配置类型选择Development Computer(开发机配置,占用资源少,适合学习)
    • 端口默认3306,不要修改,开启TCP/IP协议,点击下一步
    • 身份验证方式,选择Use Strong Password Encryption(强密码加密,8.0默认)
    • 设置root用户密码,务必记住这个密码,后续登录需要使用,建议设置大小写+数字+特殊字符的强密码
    • 配置Windows服务,服务名默认MySQL80,勾选开机自启(可选),点击下一步
    • 后续步骤全部默认,点击执行,等待安装完成即可
  3. 验证安装是否成功
    • 按下Win+R,输入cmd,打开命令提示符
    • 输入命令 mysql -u root -p,回车后输入你设置的root密码
    • 如果出现mysql>提示符,说明安装成功,已经进入MySQL命令行环境

2.3 Linux环境安装(CentOS 8/9为例)

线上生产环境90%都是Linux系统,所以必须掌握Linux下的MySQL安装:

bash 复制代码
# 1. 配置MySQL官方yum源
sudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el8-3.noarch.rpm

# 2. 安装MySQL社区版服务端
sudo yum install -y mysql-community-server

# 3. 启动MySQL服务,并设置开机自启
sudo systemctl start mysqld
sudo systemctl enable mysqld

# 4. 查看服务运行状态,出现active (running)说明启动成功
sudo systemctl status mysqld

# 5. 查看MySQL生成的初始root密码
sudo grep 'temporary password' /var/log/mysqld.log

# 6. 登录MySQL,输入上一步查到的初始密码
mysql -u root -p

# 7. 登录后,修改root用户的密码(必须先修改密码,才能执行其他操作)
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的强密码@123';

# 8. (可选)开启root用户远程访问,允许其他机器连接该数据库
use mysql;
update user set host='%' where user='root';
flush privileges;

2.4 Docker环境安装(推荐,零污染本地环境)

Docker是现在开发人员最常用的环境部署方式,一键启动,不污染本地环境,随时可以重置,非常适合学习使用:

bash 复制代码
# 1. 拉取MySQL 8.0官方镜像
docker pull mysql:8.0

# 2. 一键启动MySQL容器
# 参数说明:
# -d 后台运行
# --name 容器名称,自定义
# -p 端口映射,宿主机3306端口映射到容器3306端口
# -e MYSQL_ROOT_PASSWORD 设置root用户密码,必须设置
# -v 数据卷挂载,把容器内的数据、配置文件挂载到宿主机,避免容器删除后数据丢失
# --restart=always 开机自启
docker run -d \
  --name mysql8 \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=你的强密码@123 \
  -v /mysql/data:/var/lib/mysql \
  -v /mysql/conf:/etc/mysql/conf.d \
  --restart=always \
  mysql:8.0

# 3. 验证容器是否运行成功,出现mysql8容器说明启动成功
docker ps | grep mysql8

# 4. 进入容器,登录MySQL命令行
docker exec -it mysql8 mysql -u root -p

2.5 客户端工具安装

MySQL服务端安装完成后,我们需要客户端工具来连接和操作数据库,这里推荐2款主流工具:

  1. DBeaver:开源免费、跨平台、功能强大,支持所有主流数据库,社区活跃度高,非常适合学习和开发使用,直接官网下载安装即可。
  2. Navicat Premium:界面友好,操作简单,功能全面,是企业最常用的数据库客户端,但是是付费软件,有14天免费试用期。

重要提醒:图形化工具只是辅助,一定要学会用原生命令行操作MySQL,因为线上生产环境绝大多数只有命令行,没有图形化工具。


第三章 筑基核心:彻底搞懂MySQL的核心概念与数据模型

很多人SQL写不好、面试被问懵,根源就是基础概念不清晰。这一章我们把MySQL的核心概念、数据类型、约束讲透,帮你打下最坚实的地基。

3.1 MySQL核心层级概念

我们用大家最熟悉的Excel来做类比,一秒搞懂MySQL的核心层级:

复制代码
MySQL服务实例 → 数据库(Database) → 数据表(Table) → 列(Column/字段) + 行(Row/记录)
  • MySQL服务实例:你安装启动的MySQL服务,一个服务器上可以运行多个实例,一个实例可以创建多个数据库
  • 数据库 :相当于一个文件夹,用来分类管理数据表,比如一个电商系统,会创建user_db(用户数据库)、order_db(订单数据库)、goods_db(商品数据库),实现数据的隔离管理
  • 数据表 :相当于文件夹里的Excel文件,一个数据库里可以有多个表,每个表对应一类业务数据,比如user表存储用户信息,order表存储订单信息
  • 列(字段) :相当于Excel的表头,比如user表里的idusernamephoneage,每个字段都有自己的数据类型和约束,定义了这个字段能存什么数据
  • 行(记录):相当于Excel里的一行数据,也就是一条完整的业务记录,比如一个用户的信息,对应表中的一行数据

3.2 核心数据类型(建表的核心,90%的坑都在这里)

数据类型定义了字段能存储的数据格式、范围、存储空间,是建表的核心,选择合适的数据类型,不仅能保证数据的完整性,还能极大提升数据库的性能。

MySQL的数据类型主要分为三大类:数值类型、字符串类型、日期时间类型,我们只讲最常用、企业开发必用的类型,避开冷门无用的内容。

3.2.1 数值类型

分为整数类型、浮点/定点类型,核心原则:能存下数据的前提下,占用空间越小越好,存储空间越小,查询性能越高。

整数类型
类型 存储空间 有符号范围 无符号范围 核心适用场景
TINYINT 1字节 -128~127 0~255 状态值、性别、年龄、枚举值,比如0-禁用/1-正常
SMALLINT 2字节 -32768~32767 0~65535 小范围数字,比如商品分类ID、地区编码
INT 4字节 -2147483648~2147483647 0~4294967295 绝大多数场景的业务ID、用户ID、订单ID
BIGINT 8字节 -9e18~9e18 0~1.8e19 超大规模主键、分布式雪花ID、大数据量表的主键

高频避坑点

  1. 不要迷信INT(11):MySQL8.0开始,INT后面的数字不代表存储长度,只代表显示宽度,没有任何实际意义,INT(1)INT(11)的存储范围、占用空间完全一样,很多新手误以为INT(11)只能存11位数字,这是完全错误的。
  2. 不要用INT存小数字:比如年龄,最大不会超过150,用TINYINT UNSIGNED完全足够,只占用1字节,用INT会浪费3字节,表数据量越大,浪费越严重,性能差距越明显。
  3. 主键优先用BIGINT:不要用INT当主键,很多公司都踩过数据量超过INT上限(21亿)导致的线上故障,BIGINT的上限几乎不可能达到,只多占用4字节,完全可以忽略。
  4. 无符号类型UNSIGNED:比如年龄、ID,不可能是负数,加上UNSIGNED可以扩大存储范围,避免负数的脏数据。
浮点/定点类型
类型 特点 适用场景
FLOAT/DOUBLE 浮点类型,占用空间小,但是存在精度丢失问题 非精准的数值计算,比如坐标、重量、温度等非财务数据
DECIMAL(M,D) 定点类型,精准存储,M是总位数,D是小数位数,最大M=65,D=30 金额、财务数据、需要精准计算的数值,比如商品价格、订单金额

致命避坑点金额绝对不能用FLOAT/DOUBLE存储! 因为浮点类型的二进制存储特性,会出现0.1 + 0.2 ≠ 0.3的精度问题,会直接导致财务数据错误,造成资金损失,这是生产环境的致命事故。金额必须用DECIMAL类型,比如DECIMAL(10,2),可以存储最大99999999.99的金额,完全满足绝大多数业务需求。

3.2.2 字符串类型

字符串类型是最常用的类型,核心分为定长字符串、变长字符串、大文本类型,这里重点讲面试必问、开发必用的CHARVARCHAR的核心区别。

类型 核心特点 最大长度 适用场景
CHAR(M) 定长字符串,M是字符数,不足M会自动补空格,查询效率极高 255字符 固定长度的内容,比如手机号(11位)、身份证号(18位)、性别编码、固定长度的唯一编码
VARCHAR(M) 变长字符串,M是最大字符数,只占用实际内容的存储空间,额外用1-2字节存储内容长度 65535字节,业务中建议不超过255 长度不固定的内容,比如用户名、地址、商品名称、备注信息
TEXT 大文本类型,分为TINYTEXT/TEXT/MEDIUMTEXT/LONGTEXT 最大64KB(TEXT) 长文本内容,比如文章详情、商品描述、富文本内容、日志信息

CHAR和VARCHAR的核心区别(面试必问,必须吃透)

  1. 存储方式不同CHAR(11)无论你存1个字符还是11个字符,都会固定占用11个字符的存储空间,不足的部分会用空格补齐;而VARCHAR(11)存1个字符,只会占用1+1字节(1字节内容+1字节长度),只占用实际内容的空间。
  2. 查询性能不同:CHAR是定长存储,MySQL可以直接定位到数据的位置,查询效率比VARCHAR高很多;VARCHAR是变长存储,需要先读取长度,再定位数据,查询效率更低。
  3. 适用场景不同 :固定长度的内容,优先用CHAR,比如手机号固定11位,用CHAR(11)VARCHAR(11)性能更好,还能避免长度不一致的脏数据;长度不固定的内容,用VARCHAR,节省存储空间。

高频避坑点

  1. VARCHAR(M)的M是字符数 ,不是字节数!比如VARCHAR(20),可以存20个中文,也可以存20个英文,在utf8mb4字符集下,一个中文占4字节,所以M是字符数,不是字节数,很多新手在这里搞混。
  2. 不要用VARCHAR(255)存所有内容:很多新手建表,所有字段都用VARCHAR(255),这是非常不规范的,合适的类型才是最好的,比如手机号用CHAR(11),性别用CHAR(1)
  3. 非必要不要用TEXT类型:TEXT类型不能设置默认值,查询效率比VARCHAR低很多,还会占用额外的存储空间,短文本优先用VARCHAR,只有超过255字符的长文本才用TEXT。
  4. 不要用字符串存数值/日期:很多新手喜欢用VARCHAR存年龄、日期,这会导致无法使用数值/日期函数,查询时无法命中索引,性能极低,还会出现脏数据,必须用对应的类型存储。
3.2.3 日期时间类型
类型 存储空间 格式 范围 适用场景
DATE 3字节 YYYY-MM-DD 1000-01-01 ~ 9999-12-31 只需要日期,不需要时间,比如生日、入职日期、活动日期
DATETIME 5字节(8.0+) YYYY-MM-DD HH:MM:SS 1000-01-01 ~ 9999-12-31 绝大多数业务场景,创建时间、更新时间、操作时间,推荐优先使用
TIMESTAMP 4字节 YYYY-MM-DD HH:MM:SS 1970-01-01 ~ 2038-01-19 跨时区的业务场景,注意2038年溢出问题

高频避坑点

  1. 优先用DATETIME,不要用TIMESTAMP:TIMESTAMP有2038年上限,到2038年就会溢出,很多老系统都踩过这个坑;MySQL8.0+的DATETIME只占用5字节,和TIMESTAMP的4字节差距极小,但是存储范围大得多,没有溢出风险。
  2. 不要用字符串存日期:很多新手用VARCHAR存日期,导致无法使用MySQL的日期函数,查询时无法命中索引,还会出现格式混乱的脏数据,必须用对应的日期类型。
  3. 自动维护时间:创建时间create_time建议设置默认值DEFAULT CURRENT_TIMESTAMP,更新时间update_time设置DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,MySQL会自动维护这两个时间,不需要代码里处理,减少bug。

3.3 约束:保证数据完整性的核心

约束是定义在字段上的规则,用来限制存储在表中的数据,保证数据的完整性、一致性、有效性,避免脏数据进入数据库。零基础建表最容易忽略约束,导致后期出现大量脏数据,维护成本极高。

MySQL的核心约束有6种,我们逐个讲透用法和最佳实践:

  1. 主键约束 PRIMARY KEY
    • 作用:唯一标识表中的一行数据,主键字段必须非空、唯一,一个表只能有一个主键
    • 最佳实践:优先用BIGINT AUTO_INCREMENT自增主键,不要用业务字段(比如手机号、身份证号)当主键,业务字段可能会变更,会导致严重的业务问题
  2. 非空约束 NOT NULL
    • 作用:限制字段不能为空,必须赋值
    • 最佳实践:除了特殊场景,所有字段都应该设置NOT NULL,并配合DEFAULT设置默认值,因为NULL值会导致查询、索引失效,还会出现很多不可预期的查询结果,是MySQL的高频坑点
  3. 唯一约束 UNIQUE
    • 作用:限制字段的值在表中必须唯一,不能重复,允许有NULL值(但NULL值也只能有一个)
    • 适用场景:用户名、手机号、身份证号、订单编号等不能重复的业务字段
    • 注意:唯一约束会自动创建唯一索引,提升查询效率
  4. 默认约束 DEFAULT
    • 作用:给字段设置默认值,当插入数据没有给该字段赋值时,自动使用默认值
    • 最佳实践:配合NOT NULL使用,避免NULL值,比如性别默认0(未知),状态默认1(正常),创建时间默认当前时间
  5. 检查约束 CHECK
    • 作用:检查字段的值是否符合指定的规则,不符合的话无法插入/更新
    • 注意:MySQL8.0.16版本之后才正式支持CHECK约束,之前的版本虽然语法支持,但是不会生效,8.0+可以放心使用
    • 示例:age TINYINT CHECK (age > 0 AND age < 150),限制年龄必须在0-150之间
  6. 外键约束 FOREIGN KEY
    • 作用:用来关联两个表,保证数据的一致性,比如订单表的user_id关联用户表的id,保证订单对应的用户必须存在
    • 重要提醒 :互联网企业的生产环境中,强烈不建议使用物理外键,而是用逻辑外键(代码里保证数据关联一致性)。原因:物理外键会导致锁冲突、性能下降、表之间耦合度极高,分布式场景下无法使用,批量导入数据时会有各种限制,维护成本极高。

3.4 企业级建表最佳实践(零基础直接套用)

这里给大家一套企业开发中通用的建表规范,零基础可以直接套用,避免踩坑:

  1. 表必须有主键,优先使用BIGINT NOT NULL AUTO_INCREMENT自增主键
  2. 所有字段尽量设置NOT NULL + DEFAULT,避免NULL值
  3. 表必须有create_timeupdate_time两个字段,自动维护时间
  4. 表名、字段名全部使用小写字母+下划线命名,禁止使用大写、中文、关键字,避免Linux下大小写敏感的问题
  5. 所有表、字段必须添加COMMENT注释,说明用途,方便后续维护
  6. 选择合适的数据类型,遵循"最小够用"原则,避免大材小用
  7. 必须指定存储引擎为InnoDB,字符集为utf8mb4,排序规则为utf8mb4_general_ci

第四章 SQL核心语法入门:DDL数据定义语言,学会建库建表

SQL(结构化查询语言)是操作关系型数据库的标准语言,主要分为四大类:

  • DDL(数据定义语言) :用来操作数据库、表、索引等结构,关键字:CREATEALTERDROPTRUNCATE
  • DML(数据操纵语言) :用来操作表中的数据,关键字:INSERTUPDATEDELETE
  • DQL(数据查询语言) :用来查询数据,关键字:SELECT,是SQL中最核心、最常用的部分
  • DCL(数据控制语言) :用来管理用户、权限,关键字:GRANTREVOKECREATE USER

这一章我们先讲DDL语言,先有库和表,才能操作数据。

4.1 数据库的常用操作

sql 复制代码
-- =============================================
-- 1. 创建数据库(核心,必须掌握)
-- 注意:必须指定utf8mb4字符集,不要用utf8,MySQL的utf8是伪utf8,最多存3字节,不支持emoji和生僻字
-- IF NOT EXISTS:如果数据库不存在才创建,避免重复创建报错
-- DEFAULT CHARACTER SET:指定默认字符集
-- DEFAULT COLLATE:指定默认排序规则
-- =============================================
CREATE DATABASE IF NOT EXISTS user_db 
DEFAULT CHARACTER SET utf8mb4 
DEFAULT COLLATE utf8mb4_general_ci;

-- 2. 查看MySQL实例中所有的数据库
SHOW DATABASES;

-- 3. 切换/使用数据库,后续的表操作都会在这个数据库中执行
USE user_db;

-- 4. 查看当前正在使用的数据库
SELECT DATABASE();

-- 5. 修改数据库的字符集(一般不修改,创建时就指定好)
ALTER DATABASE user_db DEFAULT CHARACTER SET utf8mb4;

-- 6. 删除数据库(高危操作!!!生产环境绝对禁止执行)
-- IF EXISTS:如果数据库存在才删除,避免报错
DROP DATABASE IF EXISTS user_db;

4.2 表的常用操作

4.2.1 创建表(核心,企业级规范示例)

我们基于上面的建表最佳实践,创建一个规范的系统用户表,逐行带注释,零基础可以直接套用:

sql 复制代码
-- 创建系统用户表,完全符合企业级开发规范
CREATE TABLE IF NOT EXISTS sys_user (
  id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  username VARCHAR(50) NOT NULL COMMENT '用户名,登录账号',
  password VARCHAR(100) NOT NULL COMMENT '密码,加密存储,禁止明文',
  phone CHAR(11) NOT NULL COMMENT '手机号',
  age TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '年龄',
  gender CHAR(1) NOT NULL DEFAULT '0' COMMENT '性别:0-未知,1-男,2-女',
  email VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
  birthday DATE DEFAULT NULL COMMENT '生日',
  status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:0-禁用,1-正常',
  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  -- 主键约束
  PRIMARY KEY (id),
  -- 唯一约束,保证用户名和手机号不重复
  UNIQUE KEY uk_username (username),
  UNIQUE KEY uk_phone (phone),
  -- 普通索引,提升查询效率,后续进阶篇会详细讲解索引
  KEY idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';
4.2.2 表的查看操作
sql 复制代码
-- 1. 查看当前数据库下的所有表
SHOW TABLES;

-- 2. 查看表的结构,字段名、类型、约束等信息
DESC sys_user;

-- 3. 查看表的完整创建语句,包括注释、索引、字符集、存储引擎等所有信息
SHOW CREATE TABLE sys_user;
4.2.3 表的修改操作(ALTER TABLE)

开发中经常需要修改表结构,比如加字段、改字段、加索引,这里讲最常用的操作:

sql 复制代码
-- 1. 给表添加字段
-- 示例:给sys_user表添加address地址字段,加到email字段后面
-- AFTER:指定字段的位置,不加的话默认加到表的最后
ALTER TABLE sys_user 
ADD COLUMN address VARCHAR(200) NOT NULL DEFAULT '' COMMENT '地址' AFTER email;

-- 2. 修改字段的类型、约束、默认值、注释
-- 示例:修改age字段的默认值为18
ALTER TABLE sys_user 
MODIFY COLUMN age TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄';

-- 3. 修改字段名(尽量不要修改,会影响业务代码)
-- 示例:把gender字段名改成sex
ALTER TABLE sys_user 
CHANGE COLUMN gender sex CHAR(1) NOT NULL DEFAULT '0' COMMENT '性别:0-未知,1-男,2-女';

-- 4. 删除字段(高危操作,生产环境谨慎执行)
ALTER TABLE sys_user DROP COLUMN address;

-- 5. 修改表名(尽量不要修改,影响极大)
ALTER TABLE sys_user RENAME TO sys_user_info;

-- 6. 给表添加索引
-- 示例:给email字段添加唯一索引
ALTER TABLE sys_user ADD UNIQUE KEY uk_email (email);

-- 7. 删除索引
ALTER TABLE sys_user DROP INDEX uk_email;
4.2.4 表的删除/清空操作(高危操作,必须警惕)
sql 复制代码
-- 1. 删除表,表结构和数据全部删除,无法恢复(生产环境绝对禁止执行)
DROP TABLE IF EXISTS sys_user;

-- 2. 清空表数据,保留表结构,自增主键重置,执行速度极快(高危操作!!!)
TRUNCATE TABLE sys_user;

重要提醒TRUNCATE是DDL操作,不是DML操作,不会触发事务,无法回滚,执行后数据直接清空,无法恢复;而DELETE是DML操作,在事务中可以回滚,这是两者的核心区别,面试必问。


第五章 SQL核心语法:DML数据操纵语言,学会增删改数据

DML是用来操作表中数据的语言,核心就是增、删、改,是业务开发中最常用的语法,同时也是生产环境事故最高发的部分,必须吃透,避开高危坑点。

5.1 INSERT 插入数据

sql 复制代码
-- =============================================
-- 1. 插入单行数据(推荐写法)
-- 优点:指定字段,不依赖表的字段顺序,表结构变更不会导致插入报错
-- 注意:字段顺序和VALUES里的值顺序必须一一对应,类型匹配
-- =============================================
INSERT INTO sys_user (username, password, phone, age, gender, email, birthday, status)
VALUES ('zhangsan', 'e10adc3949ba59abbe56e057f20f883e', '13800138000', 25, '1', 'zhangsan@example.com', '2000-01-01', 1);

-- 2. 插入单行数据(不推荐写法)
-- 不指定字段,必须按表的字段顺序赋值,表结构变了就会报错,维护性极差
INSERT INTO sys_user 
VALUES (2, 'lisi', 'e10adc3949ba59abbe56e057f20f883e', '13800138001', 23, '2', 'lisi@example.com', '2001-02-02', 1, NOW(), NOW());

-- =============================================
-- 3. 批量插入数据(强烈推荐,业务开发必用)
-- 优点:一次插入多条数据,性能比多次单行插入高10倍以上,减少数据库IO压力
-- =============================================
INSERT INTO sys_user (username, password, phone, age, gender, email, birthday, status)
VALUES 
('wangwu', 'e10adc3949ba59abbe56e057f20f883e', '13800138002', 28, '1', 'wangwu@example.com', '1997-03-03', 1),
('zhaoliu', 'e10adc3949ba59abbe56e057f20f883e', '13800138003', 22, '2', 'zhaoliu@example.com', '1999-04-04', 1),
('qianqi', 'e10adc3949ba59abbe56e057f20f883e', '13800138004', 30, '1', 'qianqi@example.com', '1995-05-05', 0);

-- =============================================
-- 4. 存在则更新,不存在则插入(业务高频场景)
-- 基于唯一键(主键/唯一约束)实现,避免重复插入数据,比如导入数据、用户注册
-- =============================================
INSERT INTO sys_user (username, password, phone, age, gender)
VALUES ('zhangsan', 'new_password123', '13800138000', 26, '1')
ON DUPLICATE KEY UPDATE 
password = VALUES(password), 
age = VALUES(age),
update_time = CURRENT_TIMESTAMP;

5.2 UPDATE 更新数据(高危操作,必须警惕)

生产环境第一大事故:忘写WHERE条件的UPDATE,导致全表数据被更新! 必须严格遵守"先查后改"的原则,执行UPDATE之前,先执行SELECT确认WHERE条件能查到的行数,避免误操作。

sql 复制代码
-- 1. 更新单行数据(推荐写法,必须加WHERE条件)
UPDATE sys_user 
SET age = 26, email = 'zhangsan_new@example.com' 
WHERE id = 1;

-- 2. 批量更新数据,符合WHERE条件的所有行都会被更新
UPDATE sys_user 
SET status = 0 
WHERE age > 28;

-- 3. 高危操作!!!没有WHERE条件,会更新全表的所有数据,生产环境绝对禁止执行
-- UPDATE sys_user SET status = 0;

-- 避坑技巧:更新前先执行SELECT,确认WHERE条件的结果
-- 比如先执行 SELECT * FROM sys_user WHERE id = 1; 确认数据正确,再执行UPDATE

5.3 DELETE 删除数据(高危操作,必须警惕)

和UPDATE一样,忘写WHERE条件的DELETE,会导致全表数据被删除,是生产环境第二大事故,必须严格遵守"先查后删"的原则。

sql 复制代码
-- 1. 删除单行数据(推荐写法,必须加WHERE条件)
DELETE FROM sys_user 
WHERE id = 5;

-- 2. 批量删除数据,符合WHERE条件的所有行都会被删除
DELETE FROM sys_user 
WHERE status = 0 AND create_time < '2024-01-01';

-- 3. 高危操作!!!没有WHERE条件,会删除全表的所有数据,生产环境绝对禁止执行
-- DELETE FROM sys_user;

-- 避坑技巧:删除前先执行SELECT,确认WHERE条件的结果
-- 比如先执行 SELECT * FROM sys_user WHERE id = 5; 确认数据正确,再执行DELETE

第六章 SQL核心语法:DQL数据查询语言(基础篇),单表查询全解

DQL(数据查询语言)是SQL中最核心、最常用的部分,业务开发中90%的SQL语句都是查询语句,也是面试的重中之重。本篇我们先讲单表查询,多表关联查询放在中篇详细讲解。

6.1 DQL完整语法与执行顺序(核心中的核心,必须吃透)

很多人写SQL逻辑混乱、报错,根源就是不知道SQL的语法顺序和执行顺序,这里先给大家讲透,理解了这个,你就能写出逻辑清晰的SQL。

sql 复制代码
-- =====================
-- 1. 语法顺序(写SQL的时候,必须严格按照这个顺序写,否则会报错)
-- =====================
SELECT 字段列表
FROM 表名
[WHERE 条件过滤]
[GROUP BY 分组字段]
[HAVING 分组后过滤]
[ORDER BY 排序字段 排序规则]
[LIMIT 分页限制];

-- =====================
-- 2. 执行顺序(MySQL实际执行SQL的顺序,非常重要!!!)
-- =====================
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

核心解读

  • MySQL先从FROM指定的表中获取数据,然后用WHERE过滤掉不符合条件的数据
  • 把过滤后的数据用GROUP BY进行分组,然后用HAVING过滤掉不符合条件的分组
  • 然后执行SELECT查询指定的字段,去重、计算等操作
  • 再用ORDER BY对结果进行排序,最后用LIMIT限制返回的行数
  • 这就是为什么WHERE里不能用聚合函数,因为WHERE的执行顺序在SELECT之前,还没计算聚合结果;而HAVINGGROUP BY之后,可以用聚合函数

6.2 基础查询

sql 复制代码
-- =============================================
-- 1. 查询指定字段(强烈推荐,生产环境规范)
-- 只查询业务需要的字段,不要查询多余的字段,提升性能,支持覆盖索引
-- =============================================
SELECT id, username, phone, age, status FROM sys_user;

-- 2. 查询所有字段(绝对禁止在生产环境使用SELECT *)
-- 缺点:查询多余字段,增加网络传输开销,无法使用覆盖索引,表结构变更会导致代码报错
SELECT * FROM sys_user;

-- 3. 给字段起别名,AS可以省略,别名有空格时必须加引号
SELECT 
  id AS '用户ID',
  username '用户名',
  phone '手机号',
  age '年龄'
FROM sys_user;

-- 4. 查询去重的数据,DISTINCT,比如查询所有不重复的年龄
SELECT DISTINCT age FROM sys_user;

-- 5. 字段运算,比如根据年龄计算出生年份
SELECT 
  username,
  age,
  YEAR(NOW()) - age AS '出生年份'
FROM sys_user;

6.3 WHERE 条件过滤查询

WHERE子句用来过滤数据,只返回符合条件的记录,是查询中最常用的子句。

6.3.1 常用条件运算符
  • 比较运算符:=!=/<>><>=<=BETWEEN ... ANDINIS NULLIS NOT NULL
  • 逻辑运算符:ANDORNOT
6.3.2 代码示例
sql 复制代码
-- 1. 等值查询,查询id=1的用户
SELECT id, username, phone FROM sys_user WHERE id = 1;

-- 2. 不等值查询,查询状态不是正常的用户
SELECT id, username, status FROM sys_user WHERE status != 1;
-- 等价于 <>,和!=效果完全一致
SELECT id, username, status FROM sys_user WHERE status <> 1;

-- 3. 范围查询,查询年龄在20到30之间的用户
-- BETWEEN ... AND 是闭区间,包含边界值20和30
SELECT id, username, age FROM sys_user WHERE age BETWEEN 20 AND 30;
-- 等价于
SELECT id, username, age FROM sys_user WHERE age >= 20 AND age <= 30;

-- 4. IN枚举查询,查询年龄是22、25、28的用户
SELECT id, username, age FROM sys_user WHERE age IN (22,25,28);
-- 等价于
SELECT id, username, age FROM sys_user WHERE age =22 OR age=25 OR age=28;

-- 5. NULL值查询,查询邮箱为空的用户
-- 注意:NULL不能用=判断,必须用IS NULL,因为NULL和任何值比较都是NULL,不会返回true
SELECT id, username, email FROM sys_user WHERE email IS NULL;
-- 查询邮箱不为空的用户
SELECT id, username, email FROM sys_user WHERE email IS NOT NULL;

-- 6. 逻辑运算符AND,多个条件必须同时满足
-- 查询年龄大于20、状态正常的女性用户
SELECT id, username, age, gender, status FROM sys_user 
WHERE age > 20 AND gender = '2' AND status = 1;

-- 7. 逻辑运算符OR,多个条件满足一个即可
-- 查询年龄小于20或者大于30的用户
SELECT id, username, age FROM sys_user WHERE age < 20 OR age > 30;

-- 8. 模糊查询LIKE
-- % 匹配任意多个字符(0个或多个),_ 匹配单个字符
-- 查询用户名以zhang开头的用户
SELECT id, username FROM sys_user WHERE username LIKE 'zhang%';
-- 查询用户名包含san的用户
SELECT id, username FROM sys_user WHERE username LIKE '%san%';
-- 查询用户名第二个字符是h的用户
SELECT id, username FROM sys_user WHERE username LIKE '_h%';

高频避坑点

  1. AND的优先级高于OR,多条件混合使用时,必须用括号明确优先级,比如WHERE (a=1 OR b=2) AND c=3,不要写成WHERE a=1 OR b=2 AND c=3,会导致逻辑错误
  2. %开头的模糊查询,会导致索引失效,数据量大的时候查询性能极差,后续进阶篇会详细讲解
  3. 不要在WHERE子句中对字段进行函数运算,比如WHERE YEAR(create_time) = 2024,会导致索引失效,应该写成WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'

6.4 聚合函数查询

聚合函数用来对一组数据进行统计计算,返回一个结果,常用在数据统计、分组查询中。

常用聚合函数:

函数 作用
COUNT() 统计行数
SUM() 计算数值的和
AVG() 计算数值的平均值
MAX() 计算最大值
MIN() 计算最小值

代码示例:

sql 复制代码
-- 1. COUNT() 统计行数,最常用
-- 统计表中的总用户数,推荐写法,COUNT(1)和COUNT(*)效果一致,MySQL8.0做了优化,性能几乎无差别
SELECT COUNT(1) AS '总用户数' FROM sys_user;
-- 统计状态正常的用户数
SELECT COUNT(1) AS '正常用户数' FROM sys_user WHERE status = 1;
-- 统计有邮箱的用户数,COUNT(字段)会忽略NULL值
SELECT COUNT(email) AS '有邮箱的用户数' FROM sys_user;

-- 2. SUM() 求和,统计所有用户的年龄总和
SELECT SUM(age) AS '年龄总和' FROM sys_user;

-- 3. AVG() 求平均值,统计所有用户的平均年龄
SELECT AVG(age) AS '平均年龄' FROM sys_user;

-- 4. MAX() 求最大值,统计最大的年龄
SELECT MAX(age) AS '最大年龄' FROM sys_user;

-- 5. MIN() 求最小值,统计最小的年龄
SELECT MIN(age) AS '最小年龄' FROM sys_user;

-- 6. 组合使用,多个聚合函数一起查询
SELECT 
  COUNT(1) AS '总用户数',
  MAX(age) AS '最大年龄',
  MIN(age) AS '最小年龄',
  AVG(age) AS '平均年龄',
  SUM(age) AS '年龄总和'
FROM sys_user WHERE status = 1;

高频避坑点

  1. 所有聚合函数都会忽略NULL值,比如AVG(age),如果age有NULL值,会忽略这些行,不会计入平均值的计算
  2. 不要用COUNT(可能为NULL的字段)来统计总行数,会导致统计结果错误,应该用COUNT(*)COUNT(1)
  3. 聚合函数不能用在WHERE子句中,因为WHERE的执行顺序在SELECT之前,还没计算聚合结果,会直接报错,必须用HAVING子句

6.5 GROUP BY 分组查询

GROUP BY子句用来把数据按照指定的字段进行分组,配合聚合函数使用,实现分组统计,比如按性别统计用户数,按状态统计订单数。

sql 复制代码
-- 1. 按性别分组,统计不同性别的用户数
SELECT 
  gender AS '性别',
  COUNT(1) AS '用户数'
FROM sys_user
GROUP BY gender;

-- 2. 按状态分组,统计不同状态的用户数、平均年龄
SELECT 
  status AS '状态',
  COUNT(1) AS '用户数',
  AVG(age) AS '平均年龄'
FROM sys_user
GROUP BY status;

-- 3. 多字段分组,先按状态分组,状态相同的再按性别分组
SELECT 
  status AS '状态',
  gender AS '性别',
  COUNT(1) AS '用户数'
FROM sys_user
GROUP BY status, gender;

重要提醒 :MySQL5.7+默认开启ONLY_FULL_GROUP_BY模式,GROUP BY的字段,必须出现在SELECT的字段中(聚合函数除外),否则会直接报错,这是SQL的规范,必须遵守。

6.6 HAVING 分组后过滤

HAVING子句用来对分组后的结果进行过滤,和WHERE的核心区别:

  • WHERE:分组前过滤,对原始数据进行过滤,不能使用聚合函数
  • HAVING:分组后过滤,对分组统计后的结果进行过滤,可以使用聚合函数
sql 复制代码
-- 统计用户数大于2的年龄分组
SELECT 
  age,
  COUNT(1) AS '用户数'
FROM sys_user
GROUP BY age
HAVING COUNT(1) > 2;

-- 错误写法:WHERE中不能使用聚合函数
-- SELECT age, COUNT(1) AS '用户数' FROM sys_user WHERE COUNT(1) >2 GROUP BY age;

-- 组合使用WHERE和HAVING,先过滤,再分组,再过滤
-- 先过滤状态正常的用户,按性别分组,再过滤用户数大于1的分组
SELECT 
  gender,
  COUNT(1) AS '用户数'
FROM sys_user
WHERE status = 1
GROUP BY gender
HAVING COUNT(1) > 1;

6.7 ORDER BY 排序查询

ORDER BY子句用来对查询结果进行排序,ASC为升序(默认),DESC为降序。

sql 复制代码
-- 1. 按年龄升序排序,ASC可以省略,默认升序
SELECT id, username, age FROM sys_user ORDER BY age ASC;
-- 等价于
SELECT id, username, age FROM sys_user ORDER BY age;

-- 2. 按年龄降序排序
SELECT id, username, age FROM sys_user ORDER BY age DESC;

-- 3. 多字段排序,先按年龄降序,年龄相同的按id升序
SELECT id, username, age, create_time FROM sys_user ORDER BY age DESC, id ASC;

-- 4. 配合WHERE使用,先过滤再排序
SELECT id, username, age FROM sys_user WHERE status =1 ORDER BY age DESC;

6.8 LIMIT 分页查询

LIMIT子句用来限制查询结果返回的行数,是业务开发中分页功能的核心实现方式。

语法:LIMIT offset, size,其中offset是偏移量,从0开始,size是每页返回的条数。

sql 复制代码
-- 1. 分页查询,第1页,每页2条数据
SELECT id, username, age FROM sys_user ORDER BY id DESC LIMIT 0, 2;

-- 2. 第2页,每页2条数据
SELECT id, username, age FROM sys_user ORDER BY id DESC LIMIT 2, 2;

-- 3. 简写,只查询前N条数据,LIMIT N 等价于 LIMIT 0,N
SELECT id, username FROM sys_user LIMIT 3;

分页公式 :第page页,每页size条数据,LIMIT (page-1)*size, size

避坑点 :offset越大,分页性能越差,比如LIMIT 100000, 10,需要扫描100010条数据,性能极差,后续精通篇会详细讲解深分页的优化方案。


第七章 SQL基础权限管理:DCL数据控制语言

DCL(数据控制语言)用来管理MySQL的用户、权限,生产环境中,绝对不会用root用户直接操作业务,都是创建专用的业务用户,分配最小权限,保证数据库的安全。

sql 复制代码
-- 1. 创建用户
-- 格式:CREATE USER '用户名'@'访问主机' IDENTIFIED BY '密码';
-- 访问主机:% 表示所有主机都可以访问,localhost 只能本地访问,也可以指定固定IP/IP段
CREATE USER 'app_user'@'%' IDENTIFIED BY 'AppUser@123456';

-- 2. 给用户授权
-- 格式:GRANT 权限列表 ON 数据库.表 TO '用户名'@'访问主机';
-- 给app_user用户授予user_db库下所有表的查询、插入、更新、删除权限(业务常用)
GRANT SELECT, INSERT, UPDATE, DELETE ON user_db.* TO 'app_user'@'%';

-- 给用户授予所有权限(不推荐,生产环境绝对禁止)
-- GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'%';

-- 3. 刷新权限,授权/撤销权限后必须执行,否则不生效
FLUSH PRIVILEGES;

-- 4. 查看用户的权限
SHOW GRANTS FOR 'app_user'@'%';

-- 5. 撤销用户的权限
REVOKE DELETE ON user_db.* FROM 'app_user'@'%';
FLUSH PRIVILEGES;

-- 6. 修改用户密码
ALTER USER 'app_user'@'%' IDENTIFIED BY 'NewAppUser@123456';
FLUSH PRIVILEGES;

-- 7. 删除用户
DROP USER 'app_user'@'%';

生产环境权限最佳实践

  1. 最小权限原则:只给用户需要的权限,不要给ALL PRIVILEGES,业务用户一般只给SELECT、INSERT、UPDATE、DELETE权限
  2. 限制访问主机:不要用%,尽量指定固定的IP段,比如'192.168.1.%',提升安全性
  3. 强密码策略:密码必须包含大小写、数字、特殊字符,长度不低于8位,定期更换
  4. 禁止业务代码用root用户连接数据库,root用户只用于数据库管理
  5. 不同的业务系统,创建不同的用户,只分配对应数据库的权限,实现权限隔离

第八章 零基础必看:本篇最佳实践与避坑指南

8.1 建库建表规范

  1. 数据库必须使用utf8mb4字符集,不要用utf8,避免emoji和生僻字存储报错
  2. 表必须有主键,优先使用BIGINT AUTO_INCREMENT自增主键,不要用业务字段当主键
  3. 所有字段尽量设置NOT NULL + DEFAULT,避免NULL值带来的索引失效、查询异常问题
  4. 表必须有create_timeupdate_time字段,自动维护时间,不需要代码处理
  5. 表名、字段名全部使用小写字母+下划线,禁止使用大写、中文、关键字,避免跨平台大小写问题
  6. 所有表、字段必须添加COMMENT注释,方便后续维护
  7. 遵循"最小够用"原则,选择合适的数据类型,越小的类型,性能越好
  8. 金额必须用DECIMAL类型,绝对不能用FLOAT/DOUBLE,避免精度丢失
  9. 日期必须用DATETIME/DATE类型,不要用字符串存储,避免无法使用日期函数和索引

8.2 SQL编写规范

  1. 绝对禁止使用SELECT *,只查询业务需要的字段
  2. UPDATE、DELETE语句必须加WHERE条件,执行前先SELECT确认,避免全表更新/删除
  3. 避免使用%开头的模糊查询,会导致索引失效
  4. 批量插入优先使用INSERT ... VALUES (...), (...),不要多次单行插入,提升性能
  5. WHERE条件中,不要对字段进行函数运算,会导致索引失效
  6. 多条件查询,AND优先级高于OR,用括号明确优先级,避免逻辑错误
  7. 不要在业务代码中使用DDL语句,比如ALTER、DROP、TRUNCATE

8.3 安全规范

  1. 生产环境禁止用root用户操作业务,创建专用业务用户,遵循最小权限原则
  2. 限制数据库访问IP,不要开放给所有主机
  3. 密码必须强复杂度,定期更换,禁止在代码中硬编码数据库密码
  4. 生产环境禁止执行DROP、TRUNCATE等高危操作,必须有审批流程
  5. 数据库必须定期备份,避免数据丢失

本篇总结与下篇预告

本篇总结

学完本篇,你已经完成了MySQL的筑基,彻底摆脱了SQL小白的身份:

  • 了解了MySQL的核心定位与架构,掌握了全场景的环境搭建
  • 彻底搞懂了MySQL的核心概念、数据类型、约束,掌握了企业级建库建表规范
  • 熟练掌握了DDL数据定义语言,能独立完成库、表的创建、修改、删除
  • 熟练掌握了DML数据操纵语言,能完成数据的增、删、改,避开了高危操作的坑
  • 熟练掌握了DQL单表查询的全语法,理解了SQL的执行顺序,能写出逻辑清晰的查询语句
  • 掌握了DCL权限管理,能创建用户、分配权限,符合生产安全规范

下篇预告

《零基础从入门到精通MySQL(中篇):进阶篇------吃透多表查询、事务与高级特性,搞定复杂业务SQL》

在下篇中,我们将深入讲解:

  • 多表关联查询:INNER JOIN、LEFT JOIN、RIGHT JOIN的用法与核心区别,搞定复杂业务的关联查询
  • 子查询、临时表、公用表表达式CTE的用法与最佳实践
  • 视图、存储过程、自定义函数、触发器的使用与避坑指南
  • 事务的核心原理、ACID特性、隔离级别,彻底搞懂并发数据一致性问题
  • InnoDB存储引擎的核心特性,与MyISAM的核心区别

互动环节

如果你在学习过程中遇到任何问题,或者有想了解的知识点,欢迎在评论区留言,我会一一回复。

如果本篇内容对你有帮助,欢迎点赞、收藏、转发,关注我,后续的中篇、下篇、八股文附加篇会第一时间更新,带你一步步吃透MySQL,从入门到精通!

相关推荐
@土豆2 小时前
Ubuntu 22.04 运行 Filebeat 7.11.2 崩溃问题分析及解决文档
linux·数据库·ubuntu
专注API从业者2 小时前
淘宝商品详情 API 与爬虫技术的边界:合法接入与反爬策略的技术博弈
大数据·数据结构·数据库·爬虫
爱码小白2 小时前
MySQL 单表查询练习题汇总
数据库·python·算法
WangJunXiang62 小时前
第09章:PostgreSQL日常维护
数据库·postgresql
三道渊3 小时前
进程通信与网络协议
开发语言·数据库·php
徒 花3 小时前
数据库知识复习05
android·数据库
流觞 无依3 小时前
DedeCMS plus/download.php SQL注入漏洞修复教程
sql·php
豆沙糕3 小时前
RAG文档切分最佳实践:企业级方案+主流策略+生产落地
数据库·人工智能
不会写DN3 小时前
SQL 多表操作全解
数据库·sql