一、索引基础:MySQL的"查询加速器"
刚开始用MySQL的时候,可能大家都有这样的感受:表数据少的时候,查询速度飞快,但一旦数据量涨到几千、几万条,查询就变得慢吞吞。这时候,索引就该登场了------它就像书籍的目录,能帮MySQL快速定位到目标数据,不用逐行扫描全表,大大提升查询效率。
1. 索引的核心认知
首先要明确:索引不是"万能的",它有优势也有弊端,我们要合理使用,而不是盲目创建。
-
定义:索引是MySQL中一种特殊的数据结构,它关联着表中的一列或多列数据,能快速找到对应的数据行,无需扫描整个表。
-
优势:最核心的作用就是提升查询效率,尤其是在大数据量的表中,效果会非常明显(比如从"扫描10万行"变成"扫描10行")。
-
弊端:索引会占用额外的存储空间,而且每次对表进行插入、修改、删除操作时,MySQL都要同步更新索引,会降低这些操作的效率。所以,不是索引越多越好,按需创建才是关键。
2. 常用索引类型及使用场景
MySQL的索引类型有很多,新手重点掌握以下4种,就能覆盖大部分基础场景:
-
主键索引(PRIMARY KEY):最常用、最特殊的索引,每张表只能有一个主键索引,主键字段的值必须唯一且非空(比如学生表的"学号")。创建表时,只要指定主键,MySQL会自动创建主键索引,无需手动操作。
-
唯一索引(UNIQUE):用于保证字段的值唯一,但允许为空(比如用户表的"手机号""邮箱")。如果插入的数据与已有数据重复,会报错,适合用来避免重复数据。
-
普通索引(INDEX):最基础的索引,没有任何约束,仅用于提升查询效率。适合在查询频率高、但没有主键/唯一约束的字段上创建(比如商品表的"商品名称")。
-
联合索引:由多个字段组合而成的索引(比如"姓名+手机号"),适合多字段联合查询的场景。注意:联合索引遵循"最左前缀原则",查询时要尽量匹配左边的字段,才能触发索引。
3. 索引的基础操作(实操必备)
掌握以下3个核心操作,就能轻松管理索引,新手直接复制语法,替换表名、字段名即可使用:
-
创建索引 :CREATE INDEX索引名 ON 表名(字段名);(普通索引);如果是唯一索引,用 CREATE UNIQUE INDEX 索引名 ON 表名(字段名);
-
删除索引 :DROP INDEX索引名 ON 表名;(注意:主键索引不能用这个语法,要删除主键索引,需先删除主键约束)。
-
查看索引 :SHOW INDEX FROM 表名;(能查看表中所有索引的详细信息,包括索引类型、关联字段等)。
sql
--实操案例:假设我们有一张学生表(student),包含字段:学号(id,主键)、姓名(name)、手机号(phone),实操如下:
--1. 给name字段创建普通索引:
CREATE INDEX idx_student_name ON student(name);
--2. 给phone字段创建唯一索引:
CREATE UNIQUE INDEX idx_student_phone ON student(phone);
--3. 查看student表所有索引:
SHOW INDEX FROM student;
--4. 删除name字段的普通索引:
DROP INDEX idx_student_name ON student;
二、视图:简化查询的"虚拟表"
在实际开发中,我们经常会遇到一些复杂的查询------比如多表连接、聚合查询,每次都要写长长的SQL语句,既麻烦又容易出错。这时候,视图就能帮我们"偷懒",它就像一个"虚拟表",把复杂的查询结果保存起来,后续查询直接调用视图即可,不用重复写复杂SQL。
1. 视图的核心作用
-
简化查询:将复杂的SQL(多表连接、子查询等)封装成视图,后续查询只需执行"SELECT * FROM 视图名",大大减少代码量。
-
隐藏敏感数据:比如员工表中,有"工资""身份证号"等敏感字段,我们可以创建视图,只展示"姓名""部门"等非敏感字段,避免敏感数据泄露。
-
统一查询逻辑:如果多个场景需要用到相同的复杂查询,只需创建一个视图,所有场景统一调用,后续修改查询逻辑时,只需修改视图,无需修改所有相关代码。
2. 视图的基础操作
视图的操作和普通表类似,但要注意:视图是"虚拟表",它本身不存储数据,数据来源于底层的真实表,修改视图的数据,会同步修改底层表的数据(反之亦然)。
-
创建视图:CREATE VIEW 视图名 AS 复杂查询语句;(比如:CREATE VIEW v_student_course AS SELECT 学生.姓名, 课程.课程名 FROM 学生 JOIN 课程 ON 学生.学号=课程.学号;)
-
查询视图:和查询普通表完全一样,SELECT * FROM 视图名; 也可以添加WHERE、ORDER BY等条件。
-
修改视图:ALTER VIEW 视图名 AS 新的查询语句;(当底层表结构变化,或查询逻辑需要调整时使用)。
-
删除视图:DROP VIEW 视图名;(删除视图不会影响底层的真实表数据,只是删除这个"虚拟表"的定义)。
sql
--实操案例:基于student表(学号id、姓名name、班级class)和score表(学号id、课程名course、分数score),实操如下:
--1. 创建视图(查看各学生的姓名、班级和对应课程分数):
CREATE VIEW v_student_score AS SELECT s.name, s.class, sc.course, sc.score FROM student s JOIN score sc ON s.id = sc.id;
--2. 查询视图:
SELECT * FROM v_student_score WHERE score > 80;(查询分数大于80的学生信息)
--3. 修改视图(新增"及格状态"字段):
ALTER VIEW v_student_score AS SELECT s.name, s.class, sc.course, sc.score, IF(sc.score >= 60, '及格', '不及格') AS pass_status FROM student s JOIN score sc ON s.id = sc.id;
--4. 删除视图:
DROP VIEW v_student_score;
3. 视图与表的核心区别
这里用一句话区分:表是真实存储数据的,视图是基于表的查询结果,不存储数据。简单来说,表是"仓库",视图是"仓库的镜子"------镜子能看到仓库里的东西,但本身不存放东西,镜子里的内容会随着仓库的变化而变化。
三、存储过程与函数:封装重复逻辑的"工具"
如果我们需要反复执行一段相同的SQL逻辑(比如批量插入数据、复杂的计算),每次都写一遍代码,不仅繁琐,还容易出错。存储过程和函数就是用来解决这个问题的------它们能将重复的SQL逻辑封装起来,像"函数"一样调用,提升开发效率,还能保证逻辑的一致性。
1. 存储过程基础
存储过程是一组预先编译好的SQL语句的集合,它可以接收参数、执行复杂的逻辑(比如循环、判断),适合处理批量操作、复杂业务逻辑。
-
核心作用:封装重复逻辑,减少代码冗余;提高执行效率(存储过程预先编译,每次调用无需重新编译);增强代码的可维护性(修改逻辑只需修改存储过程,无需修改所有调用处)。
-
基础操作:
-
创建:CREATE PROCEDURE 存储过程名(参数) BEGIN SQL语句集合; END;
-
调用:CALL 存储过程名(参数);(存储过程不能直接用SELECT调用,必须用CALL)
-
删除:DROP PROCEDURE 存储过程名;
-
实操案例:
sql
--创建一个存储过程,批量插入3条学生数据到student表,实操如下:
--1. 创建存储过程:
CREATE PROCEDURE add_student_batch() BEGIN INSERT INTO student(id, name, class) VALUES(101, '张三', '高一(1)班'), (102, '李四', '高一(2)班'), (103, '王五', '高一(1)班'); END;
--2. 调用存储过程:
CALL add_student_batch();
--3. 删除存储过程:
DROP PROCEDURE add_student_batch;
2. 函数基础
函数和存储过程类似,也是封装SQL逻辑,但它有一个核心区别:函数必须有返回值,而存储过程可以没有返回值。函数适合用于数据计算、数据转换等场景(比如计算两个日期的差值、拼接字符串)。
-
基础操作:
-
创建:CREATE FUNCTION 函数名(参数) RETURNS 返回值类型 BEGIN SQL语句; RETURN 返回值; END;
-
调用:SELECT 函数名(参数);(函数可以直接用在SELECT语句中,因为它有返回值)
-
删除:DROP FUNCTION 函数名;
-
实操案例:
sql
--创建一个函数,根据学生分数返回评级(90+优秀、80-89良好、60-79及格、60以下不及格),实操如下:
--1. 创建函数:
CREATE FUNCTION get_score_grade(score INT) RETURNS VARCHAR(20) BEGIN DECLARE grade VARCHAR(20); IF score >= 90 THEN SET grade = '优秀'; ELSEIF score >= 80 THEN SET grade = '良好'; ELSEIF score >= 60 THEN SET grade = '及格'; ELSE SET grade = '不及格'; END IF; RETURN grade; END;
--2. 调用函数:
SELECT name, score, get_score_grade(score) AS grade FROM student s JOIN score sc ON s.id = sc.id;
--3. 删除函数:
DROP FUNCTION get_score_grade;
3. 存储过程与函数的核心区别(新手必区分)
| 对比维度 | 存储过程 | 函数 |
|---|---|---|
| 返回值 | 可以没有返回值,也可以有多个返回值 | 必须有且只有一个返回值 |
| 调用方式 | 用CALL调用,不能用在SELECT中 | 用SELECT调用,可以嵌入在SQL语句中 |
| 适用场景 | 复杂业务逻辑、批量操作(比如批量插入、批量更新) | 数据计算、数据转换(比如日期计算、字符串处理) |
四、常用函数:MySQL的"实用小工具"
在日常查询和数据处理中,我们经常需要对数据进行转换、计算(比如拼接字符串、计算日期差、四舍五入),MySQL内置了很多常用函数,不用我们自己写复杂逻辑,直接调用即可。
1. 字符串函数(最常用)
用于处理字符串类型的数据,比如拼接、截取、转换大小写等,常用的有:
-
CONCAT(字符串1, 字符串2):拼接两个或多个字符串(比如:CONCAT('Hello', 'MySQL') → 'HelloMySQL')。
-
SUBSTR(字符串, 起始位置, 长度):截取字符串(比如:SUBSTR('MySQL学习', 1, 5) → 'MySQL')。
-
TRIM(字符串):去除字符串前后的空格(比如:TRIM(' MySQL ') → 'MySQL')。
-
LOWER(字符串):将字符串转换为小写;UPPER(字符串):将字符串转换为大写。
2. 日期函数(高频使用)
用于处理日期和时间类型的数据,比如获取当前时间、格式化日期、计算日期差等,常用的有:
-
NOW():获取当前的日期和时间(格式:YYYY-MM-DD HH:MM:SS)。
-
CURDATE():获取当前日期(格式:YYYY-MM-DD);CURTIME():获取当前时间(格式:HH:MM:SS)。
-
DATE_FORMAT(日期, 格式):格式化日期(比如:DATE_FORMAT(NOW(), '%Y年%m月%d日') → '2026年04月12日')。
-
DATEDIFF(日期1, 日期2):计算两个日期的差值(返回天数,日期1 - 日期2)。
3. 数值函数(基础必备)
用于处理数值类型的数据,比如四舍五入、取整等,常用的有:
-
ROUND(数值, 小数位数):四舍五入(比如:ROUND(3.1415, 2) → 3.14)。
-
CEIL(数值):向上取整(比如:CEIL(3.1) → 4);FLOOR(数值):向下取整(比如:FLOOR(3.9) → 3)。
-
MOD(数值1, 数值2):取余数(比如:MOD(10, 3) → 1)。
实操案例:
sql
--基于student和score表,直接调用常用函数,查看效果:
--1. 字符串函数:
SELECT CONCAT(name, '-', class) AS 学生信息 FROM student;(拼接姓名和班级)
--2. 日期函数:
SELECT name, score, DATE_FORMAT(NOW(), '%Y年%m月%d日') AS 查询时间 FROM score WHERE score >= 80;(添加查询时间)
--3. 数值函数:
SELECT score, ROUND(score/10, 1) AS 十分制分数, MOD(score, 10) AS 个位数分数 FROM score;
