MySQL 由简入深指南

发布于:2025-09-11 ⋅ 阅读:(29) ⋅ 点赞:(0)

作为全球最流行的开源关系型数据库,MySQL 凭借轻量、高效、易扩展的特性,成为后端开发、数据分析等领域的必备工具。本文针对零基础到进阶开发者,从环境搭建到复杂查询,系统梳理 MySQL 核心用法,每个知识点配套实战代码避坑指南,帮你快速上手并解决实际业务问题。建议收藏本文,后续可随时查阅实战细节。

一、入门篇:MySQL 环境搭建与基础连接

1.1 环境搭建(Windows/Linux 通用)

1.1.1 下载与安装
  • 官方地址MySQL Community Server(选择对应系统版本,推荐 8.0+,兼容性与安全性更优)
  • Windows 安装注意事项

安装时选择「Custom」模式,仅勾选「MySQL Server」和「MySQL Workbench」(可视化工具),避免安装冗余组件;

设置 root 密码时需包含大小写字母、数字与特殊符号(如Root@1234),符合 MySQL 8.0 + 的密码强度策略。

  • Linux(CentOS 7)安装命令

# 1. 安装MySQL官方仓库(解决yum源无最新版本问题)

# 1. 安装MySQL官方仓库(解决yum源无最新版本问题)​
wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm​
rpm -ivh mysql80-community-release-el7-3.noarch.rpm​
​
# 2. 安装MySQL服务(自动处理依赖)​
yum install -y mysql-community-server​
​
# 3. 启动服务并设置开机自启​
systemctl start mysqld​
systemctl enable mysqld​
​
# 4. 查看初始密码(首次登录必须使用,后续需修改)​
grep 'temporary password' /var/log/mysqld.log
1.1.2 三种连接方式(适配不同场景)
  1. 命令行连接(服务器端操作首选):
# 本地连接(默认3306端口)​
mysql -u root -p​
​
# 远程连接(需先开启root远程访问权限)​
mysql -h 192.168.1.100 -u root -p -P 3306

🔧 开启远程访问权限(首次登录后执行):


use mysql;

update user set host = '%' where user = 'root';

flush privileges; -- 刷新权限生效(生产环境建议限制IP,而非允许任意IP)
  1. MySQL Workbench 连接(可视化操作,适合新手):

打开软件 → 点击「+」新建连接 → 填写:

    • Connection Name:自定义(如 “本地 MySQL”)
    • Hostname:本地填localhost,远程填服务器 IP
    • Username:root
    • Password:点击「Store in Vault」保存密码

点击「Test Connection」,提示 “Success” 后点击「OK」完成创建。

  1. Python 连接(开发项目必备):

先安装依赖库:pip install pymysql

import pymysql
from pymysql import OperationalError

def connect_mysql():
    try:
        # 建立数据库连接(charset必须为utf8mb4,支持中文与表情)
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='Root@1234',
            database='test_db',  # 需提前创建,否则报错
            port=3306,
            charset='utf8mb4',
            cursorclass=pymysql.cursors.DictCursor  # 游标返回字典(可读性更高)
        )
        print("MySQL连接成功!")
        return conn
    except OperationalError as e:
        print(f"连接失败:{e}")  # 捕获密码错误、数据库不存在等常见问题
        return None

# 调用连接函数并关闭资源
conn = connect_mysql()
if conn:
    conn.close()

二、基础篇:数据库与表的核心操作(DDL/DML)

2.1 数据库操作(DDL)

-- 1. 查看所有数据库

show databases;

-- 2. 创建数据库(指定字符集,避免中文乱码)

create database if not exists test_db

character set utf8mb4

collate utf8mb4_general_ci; -- 排序规则,通用选择utf8mb4_general_ci

-- 3. 切换到目标数据库

use test_db;

-- 4. 查看当前所在数据库

select database();

-- 5. 删除数据库(谨慎!不可逆,建议先备份)

drop database if exists test_db;

2.2 数据表操作(DDL)

以业务常用的「用户表(user)」为例,设计包含id(主键)、username(用户名)、age(年龄)等字段的表结构。

2.2.1 创建表(含约束与最佳实践)
create table if not exists user (

id int primary key auto_increment comment '用户ID(主键,自增)',

username varchar(50) not null unique comment '用户名(非空且唯一,避免重复注册)',

age tinyint check (age > 0 and age < 150) comment '年龄(1-149岁,符合实际场景)',

email varchar(100) unique comment '邮箱(唯一,用于登录与通知)',

create_time datetime default current_timestamp comment '创建时间(默认当前时间)'

) engine=InnoDB default charset=utf8mb4 comment '用户表';

✨ 关键参数解析:

  • engine=InnoDB:默认存储引擎,支持事务、外键与行级锁,适合业务表;
  • auto_increment:主键自增,避免手动赋值导致重复;
  • comment:字段与表的注释,便于团队协作(生产环境必须添加)。
2.2.2 表结构修改与管理
-- 1. 查看当前数据库所有表
show tables;

-- 2. 查看表结构(简洁版/详细版)
desc user;  -- 简洁版(字段名、类型、约束)
show create table user;  -- 详细版(含索引、注释)

-- 3. 添加字段(新增「phone」手机号字段)
alter table user
add column phone char(11) unique comment '手机号'
after email;  -- after指定位置,默认加在最后

-- 4. 修改字段(将「age」从tinyint改为int)
alter table user
modify column age int comment '年龄(修改后支持更大范围)';

-- 5. 删除字段(谨慎!数据不可逆)
alter table user drop column phone;

-- 6. 删除表(彻底删除表结构与数据,生产环境禁止随意执行)
drop table if exists user;

2.3 数据操纵(DML:增删改)

2.3.1 插入数据(INSERT)
-- 1. 插入单条数据(指定字段,推荐!避免字段顺序变化导致错误)

insert into user (username, age, email)

values ('zhangsan', 25, 'zhangsan@xxx.com');

-- 2. 批量插入(减少IO操作,效率比单条插入高10倍以上)

insert into user (username, age, email)

values

('lisi', 30, 'lisi@xxx.com'),

('wangwu', 28, 'wangwu@xxx.com'),

('zhaoliu', 35, 'zhaoliu@xxx.com');

-- 3. 插入后获取自增ID(适用于插入后需用ID做后续操作,如关联订单)

select last_insert_id();
2.3.2 更新数据(UPDATE)
-- 1. 单条件更新(修改指定用户的年龄)
update user set age = 31 where username = 'lisi';

-- 2. 多条件更新(精准定位,避免误改数据)
update user
set email = 'wangwu_new@xxx.com'
where id = 3 and email = 'wangwu@xxx.com';

-- 3. 批量更新(用case when,减少SQL请求次数)
update user
set age = case username
    when 'zhangsan' then 26  -- 张三年龄改为26
    when 'lisi' then 32      -- 李四年龄改为32
    when 'zhaoliu' then 36   -- 赵六年龄改为36
    else age  -- 其他用户保持原年龄(必须加,否则未匹配用户年龄设为NULL)
end
where username in ('zhangsan', 'lisi', 'zhaoliu');

⚠️ 致命误区:UPDATE语句必须加where条件!若省略,会修改表中所有数据,生产环境需严格审核。

2.3.3 删除数据(DELETE/TRUNCATE)
-- 1. 条件删除(DELETE,支持事务回滚,适合删除部分数据)
delete from user where username = 'wangwu';

-- 2. 清空表数据(TRUNCATE,不可回滚,速度比DELETE快)
truncate table user;

特性

DELETE

TRUNCATE

数据恢复

支持事务回滚

不可回滚(直接清空数据页)

自增 ID

不重置(继续从上次自增)

重置为 1

执行速度

慢(逐行删除,写日志)

快(直接删除表数据页)

适用场景

删除部分数据

清空全表

三、进阶篇:复杂查询与索引优化(上)

3.1 基础查询(DQL)

-- 1. 查询指定字段(避免用*,减少网络传输与内存占用)
select id, username, age from user;

-- 2. 字段别名(AS可省略,提升结果可读性)
select
    id as '用户ID',
    username '用户名',  -- 省略AS
    age '年龄'
from user;

-- 3. 条件查询(where + 逻辑运算符)
-- 示例:查询25-35岁、用户名含「zhang」且邮箱非空的用户
select * from user
where age between 25 and 35
  and username like '%zhang%'
  and email is not null;

-- 4. 去重查询(distinct,统计不重复的年龄)
select distinct age from user;

-- 5. 排序(order by,asc升序/desc降序,默认asc)
-- 示例:按年龄降序,年龄相同按创建时间升序
select * from user order by age desc, create_time asc;

-- 6. 分页查询(limit,避免一次性查大量数据导致内存溢出)
-- 语法:limit 起始索引, 每页条数(起始索引 = (页码-1)* 每页条数)
-- 示例:查询第2页数据,每页2条(页码=2,每页条数=2)
select * from user limit 2, 2;

3.2 复杂查询(多表关联 / 聚合函数)

3.2.1 准备关联表数据

假设新增「订单表(order)」,与用户表通过user_id关联:

create table if not exists `order` (  -- order是关键字,需用反引号包裹
    order_id int primary key auto_increment comment '订单ID',
    user_id int not null comment '关联用户ID',
    order_amount decimal(10,2) not null comment '订单金额',
    order_time datetime default current_timestamp comment '下单时间',
    -- 外键约束(保证数据一致性,删除用户时自动删除关联订单)
    foreign key (user_id) references user(id) on delete cascade
) engine=InnoDB default charset=utf8mb4 comment '订单表';

-- 插入测试数据
insert into `order` (user_id, order_amount)
values (1, 99.9), (1, 199.5), (2, 299.0), (3, 499.9);
3.2.2 常用 JOIN 场景示例
  1. 左连接(LEFT JOIN):查询所有用户,包括无订单的用户(如统计用户下单率)
select
    u.username '用户名',
    count(o.order_id) '订单数',  -- 无订单为0
    ifnull(sum(o.order_amount), 0) '总消费'  -- 无订单时总消费为0,避免NULL
from user u
left join `order` o on u.id = o.user_id  -- 关联条件:用户ID=订单用户ID
group by u.id  -- 按用户分组,必须包含非聚合字段的主键
order by 订单数 desc;
  1. 内连接(INNER JOIN):只查询有订单的用户(如筛选付费用户)
select
    u.username '用户名',
    o.order_id '订单ID',
    o.order_amount '订单金额'
from user u
inner join `order` o on u.id = o.user_id
where o.order_amount > 100  -- 筛选金额>100的订单
order by o.order_time desc;
3.2.3 聚合函数(COUNT/SUM/AVG 等)
-- 1. 统计用户总数(count(*)包含NULL,推荐使用)
select count(*) as '总用户数' from user;

-- 2. 统计订单总金额、平均金额、最大金额
select
    sum(order_amount) '总销售额',
    avg(order_amount) '平均订单金额',
    max(order_amount) '最大订单金额'
from `order`;

-- 3. 按条件分组统计(group by + having)
-- 示例:统计订单数>=2的用户
select
    u.username '用户名',
    count(o.order_id) '订单数'
from user u
left join `order` o on u.id = o.user_id
group by u.id
having 订单数 >= 2;  -- having筛选分组后的结果,where筛选分组前的行

3.3 索引优化(提升查询速度的核心)​

3.3.1 索引的作用与类型​
索引类型 特点 适用场景
主键索引 默认自动创建(primary key),唯一非空 主键查询(如where id=1
唯一索引 unique约束自动创建,确保字段唯一 唯一字段查询(如usernameemail
普通索引 手动创建,无约束,仅加速查询 高频非唯一字段查询(如agecreate_time
复合索引 基于多个字段创建(如username+create_time 多条件联合查询(如where username='zhangsan' and create_time>'2024-01-01'
全文索引 针对文本字段的模糊查询优化 替代like '%关键词%'(如邮箱、文章内容查询)
3.3.2 索引创建与删除(实战代码)
-- 1. 创建普通索引(针对age字段,高频用于年龄筛选)
create index idx_user_age on user(age);

-- 2. 创建复合索引(针对username+create_time,适配“按用户名查询并按时间排序”场景)
create index idx_user_name_time on user(username, create_time);

-- 3. 创建全文索引(针对email字段,支持模糊查询邮箱关键词)
create fulltext index idx_user_email_ft on user(email);

-- 4. 查看表中所有索引(验证索引是否创建成功)
show index from user;

-- 5. 删除索引(索引过多会影响插入/更新性能,需定期清理无用索引)
drop index idx_user_age on user;
3.3.3 索引失效的 8 种常见场景(避坑指南)
使用函数或运算操作索引字段:​
select * from user where age + 1 = 26;(失效,应改为age = 25);​


字符串不加引号:​
select * from user where username = 123;(失效,username 是字符串类型,需加引号'123');​


模糊查询以 % 开头:​
select * from user where username like '%zhang';(失效,改为zhang%可命中索引);​


违背最左前缀原则:​
复合索引(username, create_time),查询条件where create_time = '2024-01-01'(失效,需包含左前缀 username);​


使用 or 连接非索引字段:​
select * from user where age = 25 or phone = '13800138000';(phone 无索引,导致 age 索引失效);​


order by 使用非索引字段:​
select * from user where age = 25 order by email;(email 无索引,导致排序时全表扫描);​
数据量过小:​
表数据 < 1000 行时,MySQL 会选择全表扫描(索引开销大于查询收益);​


索引字段为 NULL:​
select * from user where email is null;(索引不存储 NULL 值,导致失效,建议字段设为not null default '')。


网站公告

今日签到

点亮在社区的每一天
去签到