当前位置: 首页 > news >正文

MySQL进阶基础:索引、视图、存储过程与常用函数

一、索引基础: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表名;(能查看表中所有索引的详细信息,包括索引类型、关联字段等)。

--实操案例:假设我们有一张学生表(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 视图名;(删除视图不会影响底层的真实表数据,只是删除这个“虚拟表”的定义)。

--实操案例:基于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 存储过程名;

实操案例

--创建一个存储过程,批量插入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 函数名;

实操案例

--创建一个函数,根据学生分数返回评级(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)。

实操案例

--基于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;
http://www.cnnetsun.cn/news/1837057.html

相关文章:

  • 《为什么你的AI系统一到现实世界就失效?》——从“数据驱动幻觉”到“空间智能落地”的断层解析
  • SDMatte赋能微信小程序开发:在线证件照制作工具实战
  • SparkFun TB6612 Arduino驱动库深度解析与工程实践
  • 无感FOC驱动新突破:脉冲注入与电感法实现媲美有霍尔的静音启动与力矩保持
  • 终结Agentic RAG乱象!首篇权威SoK论文:从定义、架构到落地的全体系指南
  • 不用装软件!这款MicroPython浏览器 IDE :让你在手机上也能调试树莓派 Pico拐
  • 用STM32和R60ABD1毫米波雷达DIY一个非接触式睡眠监测仪(附完整代码和PCB)
  • 【51单片机】【Proteus仿真】 十字路口交通灯系统:从仿真到代码的实战解析
  • SLAM 技术路线已收敛:这几条才是未来主流!
  • 告别手动标注!用Python脚本把语义分割Mask一键转成Labelme JSON(附完整代码)
  • 基于人工智能技术的FLUX小红书极致真实V2模型解析
  • Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接椿
  • ArcGIS Pro中协同区位熵方法在商业选址分析中的实战应用
  • LDC1612电感数字转换器原理与Arduino工程实践
  • 一次由Linux内核参数somaxconn设置过小导致的连接失败
  • macos简单配置openclaw诼
  • 如何实现一个「实时数据大屏」?(数据推送与可视化)
  • BMP183气压传感器驱动开发与高精度补偿实践
  • 《空间智能体:下一代AI基础设施》——从视觉识别到空间计算的范式跃迁
  • 使用 C# 删除 PDF 中的数字签名苫
  • jm_PCF8574库深度解析:PCF8574准双向I/O的Arduino驱动实践
  • 影刀RPA实战:Chrome多用户环境批量管理与自动化登录
  • 优化递归迷宫寻路算法
  • SAMD平台零拷贝I2S音频驱动:嵌入式实时音频传输实践
  • RP2040驱动BridgeTek EVE显示控制器的技术实现
  • VL6180X_WE中断驱动库:工业级ToF传感器低功耗实时方案
  • Rust的闭包标注实践
  • stock-sdk-mcp 的实践整理逃
  • NewPing超声波测距库:嵌入式实时测距的高性能实现
  • 如何用LinkSwift轻松获取网盘直链:3个实际应用场景详解