📖
R‘Notes
  • 关于本仓库/网站
  • Note
    • Golang的知识碎片
      • 关于Golang的一些碎片知识
    • LeetCode
      • LCR 121. 寻找目标值 - 二维数组
      • LCR 125. 图书整理 II
      • LCR 127. 跳跃训练
      • LCR 143. 子结构判断
      • LCR 159. 库存管理 III
      • LCR 161. 连续天数的最高销售额
      • LCR 170. 交易逆序对的总数
      • LCR 174. 寻找二叉搜索树中的目标节点
      • LeetCode--1. 两数之和
      • LeetCode--10. 正则表达式匹配
      • LeetCode--1004. 最大连续1的个数 III
      • LeetCode--101. 对称二叉树
      • LeetCode--102. 二叉树的层序遍历
      • LeetCode--1027. 最长等差数列
      • LeetCode--103. 二叉树的锯齿形层序遍历
      • LeetCode--1035. 不相交的线
      • LeetCode--104. 二叉树的最大深度
      • LeetCode--1044. 最长重复子串
      • LeetCode--105. 从前序与中序遍历序列构造二叉树
      • LeetCode--106. 从中序与后序遍历序列构造二叉树
      • LeetCode--110. 平衡二叉树
      • LeetCode--111. 二叉树的最小深度
      • LeetCode--112. 路径总和
      • LeetCode--113. 路径总和 II
      • LeetCode--1137. 第 N 个泰波那契数
      • LeetCode--114. 二叉树展开为链表
      • LeetCode--1143. 最长公共子序列
      • LeetCode--115. 不同的子序列
      • LeetCode--1191. K 次串联后最大子数组之和
      • LeetCode--120. 三角形最小路径和
      • LeetCode--121. 买卖股票的最佳时机
      • LeetCode--1218. 最长定差子序列
      • LeetCode--122. 买卖股票的最佳时机 II
      • LeetCode--1220. 统计元音字母序列的数目
      • LeetCode--123. 买卖股票的最佳时机 III
      • LeetCode--124. 二叉树中的最大路径和
      • LeetCode--125. 验证回文串
      • LeetCode--128. 最长连续序列
      • LeetCode--1289. 下降路径最小和 II
      • LeetCode--129. 求根节点到叶节点数字之和
      • LeetCode--1301. 最大得分的路径数目
      • LeetCode--1312. 让字符串成为回文串的最少插入次数
      • LeetCode--134. 加油站
      • LeetCode--135. 分发糖果
      • LeetCode--136. 只出现一次的数字
      • LeetCode--138. 随机链表的复制
      • LeetCode--139. 单词拆分
      • LeetCode--14. 最长公共前缀
      • LeetCode--141. 环形链表
      • LeetCode--142. 环形链表 II
      • LeetCode--143. 重排链表
      • LeetCode--144. 二叉树的前序遍历
      • LeetCode--145. 二叉树的后序遍历
      • LeetCode--146. LRU 缓存
      • LeetCode--148. 排序链表
      • LeetCode--15. 三数之和
      • LeetCode--151. 反转字符串中的单词
      • LeetCode--152. 最大乘积子数组【DP】
      • LeetCode--153. 寻找旋转排序数组中的最小值
      • LeetCode--155. 最小栈
      • LeetCode--1584. 连接所有点的最小费用,最小生成树模板题
      • LeetCode--1594. 矩阵的最大非负积
      • LeetCode--16. 最接近的三数之和
      • LeetCode--160. 相交链表
      • LeetCode--162. 寻找峰值
      • LeetCode--165. 比较版本号
      • LeetCode--169. 多数元素
      • LeetCode--174. 地下城游戏
      • LeetCode--179. 最大数
      • LeetCode--1824. 最少侧跳次数
      • LeetCode--188. 买卖股票的最佳时机 IV
      • LeetCode--189. 轮转数组
      • LeetCode--19. 删除链表的倒数第 N 个结点,关于删除链表会遇见的指针问题
      • LeetCode--1964. 找出到每个位置为止最长的有效障碍赛跑路线
      • LeetCode--198. 打家劫舍
      • LeetCode--199. 二叉树的右视图
      • LeetCode--2. 两数相加
      • LeetCode--20. 有效的括号
      • LeetCode--200. 岛屿数量
      • LeetCode--206. 反转链表
      • LeetCode--207. 课程表
      • LeetCode--208. 实现 Trie (前缀树)
      • LeetCode--209. 长度最小的子数组
      • LeetCode--21. 合并两个有序链表,关于链表的复习
      • LeetCode--210. 课程表 II
      • LeetCode--213. 打家劫舍 II
      • LeetCode--2140. 解决智力问题
      • LeetCode--215. 数组中的第K个最大元素
      • LeetCode--22. 括号生成
      • LeetCode--221. 最大正方形
      • LeetCode--2218. 从栈中取出 K 个硬币的最大面值和
      • LeetCode--224. 基本计算器
      • LeetCode--225. 用队列实现栈
      • LeetCode--226. 翻转二叉树
      • LeetCode--2266. 统计打字方案数
      • LeetCode--227. 基本计算器 II
      • LeetCode--23. 合并 K 个升序链表【堆和分治】
      • LeetCode--230. 二叉搜索树中第 K 小的元素
      • LeetCode--2304. 网格中的最小路径代价
      • LeetCode--232. 用栈实现队列
      • LeetCode--2320. 统计放置房子的方式数
      • LeetCode--2321. 拼接数组的最大分数
      • LeetCode--233. 数字 1 的个数
      • LeetCode--234. 回文链表
      • LeetCode--236. 二叉树的最近公共祖先
      • LeetCode--239. 滑动窗口最大值,关于单调队列的复习
      • LeetCode--24. 两两交换链表中的节点
      • LeetCode--240. 搜索二维矩阵 II
      • LeetCode--2435. 矩阵中和能被 K 整除的路径
      • LeetCode--2466. 统计构造好字符串的方案数
      • LeetCode--25. K 个一组翻转链表
      • LeetCode--2533. 好二进制字符串的数量
      • LeetCode--256. 粉刷房子
      • LeetCode--2606. 找到最大开销的子字符串
      • LeetCode--265. 粉刷房子 II
      • LeetCode--2684. 矩阵中移动的最大次数
      • LeetCode--279. 完全平方数【动态规划】
      • LeetCode--283. 移动零
      • LeetCode--287. 寻找重复数
      • LeetCode--295. 数据流的中位数
      • LeetCode--297. 二叉树的序列化与反序列化
      • LeetCode--3. 无重复字符的最长子串
      • LeetCode--300. 最长递增子序列【DP+二分】
      • LeetCode--309. 买卖股票的最佳时机含冷冻期
      • LeetCode--31. 下一个排列
      • LeetCode--3186. 施咒的最大总伤害
      • LeetCode--32. 最长有效括号【栈和dp】
      • LeetCode--322. 零钱兑换
      • LeetCode--328. 奇偶链表
      • LeetCode--329. 矩阵中的最长递增路径
      • LeetCode--33. 搜索旋转排序数组【直接二分】
      • LeetCode--337. 打家劫舍 III
      • LeetCode--3393. 统计异或值为给定值的路径数目
      • LeetCode--34. 在排序数组中查找元素的第一个和最后一个位置
      • LeetCode--3418. 机器人可以获得的最大金币数
      • LeetCode--343. 整数拆分
      • LeetCode--347. 前 K 个高频元素
      • LeetCode--347. 前 K 个高频元素Golang中的堆(containerheap)
      • LeetCode--354. 俄罗斯套娃信封问题
      • LeetCode--377. 组合总和 Ⅳ
      • LeetCode--39. 组合总和
      • LeetCode--394. 字符串解码【栈】
      • LeetCode--395. 至少有 K 个重复字符的最长子串
      • LeetCode--4. 寻找两个正序数组的中位数
      • LeetCode--40. 组合总和 II
      • LeetCode--402. 移掉 K 位数字
      • LeetCode--41. 缺失的第一个正数
      • LeetCode--415. 字符串相加
      • LeetCode--416. 分割等和子集_494. 目标和【01背包】
      • LeetCode--42. 接雨水(单调栈和双指针)
      • LeetCode--426. 将二叉搜索树转化为排序的双向链表
      • LeetCode--43. 字符串相乘
      • LeetCode--437. 路径总和 III【前缀和】
      • LeetCode--44. 通配符匹配
      • LeetCode--440. 字典序的第K小数字
      • LeetCode--442. 数组中重复的数据
      • LeetCode--445. 两数相加 II
      • LeetCode--45. 跳跃游戏 II
      • LeetCode--450. 删除二叉搜索树中的节点
      • LeetCode--46. 全排列
      • LeetCode--460. LFU 缓存
      • LeetCode--468. 验证IP地址
      • LeetCode--470. 用 Rand7() 实现 Rand10()
      • LeetCode--474. 一和零
      • LeetCode--48. 旋转图像
      • LeetCode--498. 对角线遍历
      • LeetCode--5. 最长回文子串
      • LeetCode--50. Pow(x, n)
      • LeetCode--509. 斐波那契数
      • LeetCode--516. 最长回文子序列
      • LeetCode--518. 零钱兑换 II
      • LeetCode--529. 扫雷游戏题解C++广搜
      • LeetCode--53. 最大子数组和
      • LeetCode--54. 螺旋矩阵
      • LeetCode--540. 有序数组中的单一元素
      • LeetCode--543. 二叉树的直径
      • LeetCode--55. 跳跃游戏
      • LeetCode--556. 下一个更大元素 III
      • LeetCode--56. 合并区间
      • LeetCode--560. 和为 K 的子数组
      • LeetCode--572. 另一棵树的子树
      • LeetCode--59. 螺旋矩阵 II
      • LeetCode--61. 旋转链表
      • LeetCode--62. 不同路径
      • LeetCode--622. 设计循环队列
      • LeetCode--63. 不同路径 II
      • LeetCode--64. 最小路径和
      • LeetCode--646. 最长数对链
      • LeetCode--662. 二叉树最大宽度
      • LeetCode--673. 最长递增子序列的个数
      • LeetCode--678. 有效的括号字符串
      • LeetCode--679. 24 点游戏
      • LeetCode--69. x 的平方根
      • LeetCode--695. 岛屿的最大面积
      • LeetCode--7. 整数反转
      • LeetCode--70. 爬楼梯
      • LeetCode--704. 二分查找
      • LeetCode--712. 两个字符串的最小ASCII删除和
      • LeetCode--714. 买卖股票的最佳时机含手续费
      • LeetCode--718. 最长重复子数组
      • LeetCode--72. 编辑距离
      • LeetCode--739. 每日温度
      • LeetCode--74. 搜索二维矩阵
      • LeetCode--740. 删除并获得点数
      • LeetCode--746. 使用最小花费爬楼梯
      • LeetCode--75. 颜色分类
      • LeetCode--76. 最小覆盖子串
      • LeetCode--77. 组合
      • LeetCode--78. 子集
      • LeetCode--79. 单词搜索
      • LeetCode--790. 多米诺和托米诺平铺
      • LeetCode--8. 字符串转换整数 (atoi)
      • LeetCode--82. 删除排序链表中的重复元素 II
      • LeetCode--83. 删除排序链表中的重复元素
      • LeetCode--84. 柱状图中最大的矩形【单调栈】
      • LeetCode--85. 最大矩形
      • LeetCode--87. 扰乱字符串
      • LeetCode--88. 合并两个有序数组
      • LeetCode--887. 鸡蛋掉落
      • LeetCode--91. 解码方法
      • LeetCode--912. 排序数组
      • LeetCode--918. 环形子数组的最大和
      • LeetCode--92. 反转链表 II
      • LeetCode--93. 复原 IP 地址
      • LeetCode--931. 下降路径最小和
      • LeetCode--94. 二叉树的中序遍历
      • LeetCode--958. 二叉树的完全性检验
      • LeetCode--97. 交错字符串
      • LeetCode--98. 验证二叉搜索树
      • LeetCode--983. 最低票价
      • LeetCode--LCR 140. 训练计划 II
      • NC--311.圆环回原点
      • NC--36进制加法
      • 补充题1. 排序奇升偶降链表
    • Redis
      • Redis基础部分
      • 在用Docker配置Redis哨兵节点的时候出现的错误及其解决
    • SQL学习记录
      • SQL碎片知识
      • 系统
        • MySQL学习笔记1【DQL和DCL】
        • MySQL学习笔记2【函数/约束/多表查询】
        • MySQL学习笔记3【事务】
        • MySQL学习笔记4【存储引擎和索引】
        • MySQL学习笔记5【SQL优化/视图/存储过程/触发器】
        • MySQL学习笔记6【锁】
        • MySQL学习笔记7【InnoDB】
    • x86汇编
      • 学习汇编随手记
    • 微服务相关
      • Nacos与gRPC
      • 【Golangnacos】nacos配置的增删查改,以及服务注册的golang实例及分析
    • 手搓
      • Whalebox(仿Docker)的爆诞
    • 操作系统
      • MIT6.S081-lab1
      • MIT6.S081-lab2
      • MIT6.S081-lab3
      • MIT6.S081-lab3前置
      • MIT6.S081-lab4
      • MIT6.S081-lab4前置
      • MIT6.S081-lab5
      • MIT6.S081-lab5前置
      • MIT6.S081-lab7
      • MIT6.S081-lab7前置
      • MIT6.S081-lab8
      • MIT6.S081-lab8前置
      • MIT6.S081-lab9
      • MIT6.S081-环境搭建
    • 消息队列MQ
      • Kafka
    • 算法杂谈
      • 关于二分查找时的边界分类问题
    • 计组笔记
      • 计算机组成原理的学习笔记(1)--概述
      • 计算机组成原理的学习笔记(10)--CPU·其二 组合逻辑控制器和微程序
      • 计算机组成原理的学习笔记(11)--CPU·其三 中断和异常多处理器相关概念
      • 计算机组成原理的学习笔记(12)--总线和IO系统
      • 计算机组成原理的学习笔记(2)--数据的表示和运算·其一
      • 计算机组成原理的学习笔记(3)--数据表示与运算·其二 逻辑门和加减乘
      • 计算机组成原理的学习笔记(4)--数据的表示与运算·其三 补码的乘法以及原码补码的除法
      • 计算机组成原理的学习笔记(4)--数据的表示与运算·其三 补码的乘法以及原码补码的除法
      • 计算机组成原理的学习笔记(6)--存储器·其一 SRAMDRAMROM主存储器的初步认识
      • 计算机组成原理的学习笔记(7)--存储器·其二 容量扩展多模块存储系统外存Cache虚拟存储器
      • 计算机组成原理的学习笔记(8)--指令系统·其一 指令的组成以及数据寻址方式RISK和CISK
      • 计算机组成原理的学习笔记(9)--CPU·其一 CPU的基本概念流水线技术数据通路
    • 闲聊
      • 2025-03-23记
      • 大一上总结
由 GitBook 提供支持
在本页
  • SQL优化
  • 1. 插入数据优化
  • 2. 主键优化
  • 3. 排序优化 (ORDER BY)
  • 4. 分组优化 (GROUP BY)
  • 5. 分页优化 (LIMIT)
  • 6. 计数优化 (COUNT)
  • 7. 更新优化 (UPDATE)
  • 视图
  • 1. 语法
  • 2. 检查
  • 3. 更新
  • 存储过程
  • 1. 语法
  • 2. 用户自定义变量
  • 3. 存储过程
  • 触发器
  • 1. 基本语法
  • 2. 作用
  • 3. 注意事项
  1. Note
  2. SQL学习记录
  3. 系统

MySQL学习笔记5【SQL优化/视图/存储过程/触发器】


SQL优化


1. 插入数据优化

普通插入:

  • 采用批量插入:

    • 每次插入不建议超过1000条记录,这样可以减少事务开销,提高性能。

    • 示例:

    INSERT INTO tb_user (name, age) VALUES ('Alice', 25), ('Bob', 30), ...;
  • 手动提交事务:

    • 在插入过程中手动控制事务的开始与提交,以减少自动提交的次数。

    • 示例:

    START TRANSACTION;
    INSERT INTO tb_user (name, age) VALUES ('Alice', 25);
    ... 
    COMMIT;
  • 顺序插入主键:

    • 使用自增主键,避免随机插入造成的页分裂,提升插入速度。

大批量插入:

  • 使用 LOAD DATA INFILE:

    • 当需要插入大量数据时,通过文件导入的方式提升性能。

    • 客户端连接时加上参数 --local-infile:

    mysql --local-infile -u root -p
    • 设置全局参数:

    SET GLOBAL local_infile = 1;
    • 使用示例:

    LOAD DATA LOCAL INFILE '/path/to/file.sql' INTO TABLE tb_user 
    FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';

2. 主键优化

  • 设计原则:

    • 在满足业务需求的情况下,尽量降低主键的长度。

    • 尽量选择顺序插入,使用 AUTO_INCREMENT 自增主键。

    • 避免使用 UUID 或其他自然主键(如身份证号),以降低索引效率。

  • 存储与索引维护:

    • 在 InnoDB 中,数据根据主键顺序组织。

    • 页分裂:页可以为空,也可以填充部分,也可以填充100%,每个页包含了2-N行数据(如果一行数据过大,会行溢出),根据主键排列。

    • 页合并:当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。当页中删除的记录到达 MERGE_THRESHOLD(默认为页的50%,可自定义,可以在建表,创建索引的时候指定),InnoDB会开始寻找最靠近的页(前后)看看是否可以将这两个页合并以优化空间使用。

3. 排序优化 (ORDER BY)

  • 使用索引优化排序:

    • 使用索引按顺序读取数据,避免 Using filesort。

    • 如果排序字段全部为升序或降序,可直接利用索引。

    • 如果有多字段排序(升序与降序),需创建联合索引。

  • 示例:

CREATE INDEX idx_user_age_phone ON tb_user(age ASC, phone DESC);

SELECT id, age, phone 
FROM tb_user 
ORDER BY age ASC, phone DESC;

4. 分组优化 (GROUP BY)

  • 利用索引:

    • 在 GROUP BY 查询中使用合适的索引,提高效率。

    • 确保索引列满足最左前缀法则。

  • 示例:

SELECT profession, COUNT(*) FROM tb_user GROUP BY profession ORDER BY profession;

5. 分页优化 (LIMIT)

  • 优化大数据量分页:

    • 避免高偏移量的 LIMIT 查询,减少不必要的数据排序。

  • 使用覆盖索引加速:

    • 通过主键索引排序查询,可以显著提高性能。

  • 示例:

-- 慢查询示例
SELECT * FROM tb_sku LIMIT 5000000, 10;

-- 优化查询示例
SELECT id FROM tb_sku ORDER BY id LIMIT 5000000, 10;

-- 通过联表查询进行优化
SELECT * 
FROM tb_sku AS s
JOIN (SELECT id FROM tb_sku ORDER BY id LIMIT 5000000, 10) AS a 
ON s.id = a.id;

6. 计数优化 (COUNT)

  • 性能差异:

    • COUNT(*) ≈ COUNT(1) 性能最好,InnoDB 默认的优化机制。

    • 使用 COUNT(主键)、COUNT(字段) 的性能依次降低。

  • 示例:

SELECT COUNT(*) FROM tb_user;                 # 性能最好
SELECT COUNT(1) FROM tb_user; 				  # 和上面差不多
SELECT COUNT(id) FROM tb_user;                # 次优
SELECT COUNT(name) FROM tb_user;              # 低效(可能遍历全表)
  • 建议:

    • 尽量使用 COUNT(*),并考虑使用 Redis 或其他方式缓存计数。

7. 更新优化 (UPDATE)

  • 避免锁升级:

    • 确保更新条件(WHERE之后)的字段上有索引,以避免行锁升级为表锁。

  • 示例:

UPDATE student SET no = '042' WHERE id = 1;      -- 行锁(主键索引)
UPDATE student SET no = '114514' WHERE name = 'test'; -- 表锁(name没有索引,需添加索引以优化)

视图


1. 语法

  • 创建视图

    CREATE [ OR REPLACE ]
    VIEW 视图名称[(列名列表)]
    AS 
    SELECT 语句 [ WITH [ CASCADED | LOCAL ] CHECK OPTION ];
  • 显示视图

    SHOW CREATE VIEW [ 视图名称 ]; #显示创建视图语句
    
    SELECT [查询字段] FROM [ 视图名称 ]  WHERE [.....]; #查看创建的视图中的数据
  • 修改

    #方式一
    CREATE [OR REPLACE] 
    VIEW 视图名称[(列名列表))] 
    AS 
    SELECT 语句[ WITH[ CASCADED | LOCAL ] CHECK OPTION ];
    ---------------------------------------------------------
    #方式二
    ALTER 
    VIEW 视图名称 [(列名列表)] 
    AS 
    SELECT语句 [WITH [CASCADED | LOCAL] CHECK OPTION];
  • 删除

    DROP VIEW [IF EXISTS] 视图名称 [视图名称]

2. 检查

如果对视图进行插入操作,那么数据将会插入原表之中,如果在创建视图时使用了WITH CHECK OPTION字段,那么在进行插入或更新时将会受到创建视图时设置的检查的限制。

两个检查选项:CASCADED 和 LOCAL ,默认值为 CASCADED。

  • CASCADED:会检查本视图以及递归检查本视图创建时所依赖的视图设置的限制。

  • LOCAL:在空的基础上会检查本视图的限制条件,并向上递归检查本视图所依赖的并且设置了检查选项的视图的限制条件

  • 空(即不加检查选项):不会检查本视图的条件,但是会向上检查依赖的并设置了检查选项的视图的限制条件。

3. 更新

要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。如果视图包含以下任何一项,则该视图不可更新

  1. 聚合函数或窗口函数 ( SUM()、MIN()、MAX()、COUNT() 等 )

  2. DISTINCT

  3. GROUP BY

  4. HAVING

  5. UNION 或者UNION ALL

#插入失败的例子
REATE stu_v_count AS SELECT COUNT(*) FROM student;

INSERT INTO stu_v_count VALUES(10);

作用

  • 视图不仅可以简化用户对数据的理解,也可以简化他们的操作。那些被经常使用的查询可以被定义为视图,从而使得用户不必为以后的操作每次指定全部的条件,只需要用户针对于视图进行操作。

  • 安全 数据库可以授权,但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据,能够屏蔽一些比较敏感的信息,比如密码,身份证号。

  • 数据独立,视图可帮助用户屏蔽真实表结构变化带来的影响

  • 总而言之 类似于给表加上了一个外壳,通过这个外壳访问表的时候,只能按照所设计的方式进行访问与更新。


存储过程

简而言之,就是数据库中的函数。


1. 语法

  • 创建

    CREATE PROCEDURE 存储过程名称( [参数] ) 
    
    BEGIN
    	 SQL 语句 
    END;
  • 调用

    CALL [存储过程名称](传入参数);
  • 删除

    DROP PROCEDURE [ IFEXISTS ] [存储过程名称];

    tips: 在命令行中,执行创建存储过程的SQL时,需要通过关键字delimiter来指定SQL语句的结束符。默认是以分号作为结束符。delimiter $$,则$$符作为结束符。

2. 用户自定义变量

  • 定义方法:

    SET @自定义变量 := ?;  # := 和 = 都可以
    
    SELECT @自定义变量 := ?;
    
    SELECT 字段 INTO @自定义变量 FROM ....; #将查询结果传递给自定义变量
  • 在函数中的应用示例:

    CREATE PROCEDURE getcount()
    
    BEGIN
        DECLARE cnt INT DEFAULT 0; #变量声明
        SELECT COUNT(*) INTO cnt FROM goods; #给变量赋值
        SELECT cnt; #输出结果
    END;
    
    CALL getcount();

3. 存储过程

3.1 IF语句示例:

CREATE PROCEDURE score()
BEGIN
    DECLARE cnt INT DEFAULT 58;
    DECLARE res VARCHAR(6);
    IF cnt >= 80 THEN		#条件之后接THEN
        SET res := '优秀';
    ELSEIF cnt >= 60 THEN	#注意这里写为ELSEIF 没有空格
        SET res := '及格';
    ELSE					#ELSE 表示最后一个分支
        SET res := '重开算了';
    END IF; #END IF;表示IF语句的结束

    SELECT res;
END;

3.2 传参示例:

CREATE PROCEDURE p1(IN cnt INT, OUT res VARCHAR(10)) #'IN'表示传入参数,'OUT'表示输出
BEGIN												#,'INOUT'表示传入也传出。相当于传入了指针
    IF cnt > 80 THEN
        SET res := '优秀';
    ELSEIF cnt > 60 THEN
        SET res := '及格';
    ELSE
        SET res := '重开算了';
    END IF;
END;

CALL p1(99, @result);
SELECT @result;

3.3 CASE语句示例:

CREATE PROCEDURE p4(IN month INT)
BEGIN
    DECLARE res VARCHAR(25);
    CASE
        WHEN month >= 1 AND month <= 3 THEN
            SET res := '第一季度';
        WHEN month >= 4 AND month <= 6 THEN
            SET res := '第二季度';
        WHEN month >= 7 AND month <= 9 THEN
            SET res := '第三季度';
        WHEN month >= 10 AND month <= 12 THEN
            SET res := '第四季度';
        ELSE
            SET res := '非法参数';
    END CASE;
    SELECT res;
END;

CALL p4(6);

3.4 WHILE循环语句示例:

CREATE PROCEDURE wh(IN n INT)
BEGIN
    WHILE n > 0 DO	#满足条件,则干DO后面的事,END WHILE;表示于一次循环结束.
        SET n = n - 1;
        END WHILE;
    SELECT n;
END;

CALL wh(5);

3.5 REPEAT语句示例(相当于do while)

CREATE PROCEDURE rep(IN n INT)
BEGIN
    DECLARE res INT DEFAULT 0;
    REPEAT
            SET res = res + n;
            SET n = n - 1;
        UNTIL n <= 0
    END REPEAT;
    SELECT res;
END;

CALL rep(5);

3.6 LOOP语句示例(相当于无限循环但是带有continue和break的while语句)

CREATE PROCEDURE l2(IN n INT)
BEGIN
    DECLARE res INT DEFAULT 0;
    sum:LOOP		#sum是给这个循环的一个标签
        IF n <= 0 THEN
            LEAVE sum;  #ITERATE sum 则表示continue,继续该循环,LEAVE sum表示跳出该循环
        END IF;

        SET res = res + n;
        SET n = n - 1;
    END LOOP sum; 	#sum表示sum这个标签的循环语句结束
    SELECT res;
END;

CALL l2(15);

3.7 CURSOR游标示例:

CREATE PROCEDURE p15(IN n DECIMAL(10,2))
BEGIN
    DECLARE gname VARCHAR(255);
    DECLARE gprice DECIMAL(10,2);

    DECLARE cursor_goods CURSOR FOR SELECT price, goods_name FROM goods WHERE price < n; #声明游标
    DECLARE exit HANDLER FOR NOT FOUND CLOSE cursor_goods;	#创建一个退出条件并设置退出时执行的语句(关闭游标)

    DROP TABLE IF EXISTS p12_test;
    CREATE TABLE p12_test(
        id INT PRIMARY KEY AUTO_INCREMENT,
        price DECIMAL(10,2),
        goods_name VARCHAR(255)
    );

    OPEN cursor_goods;#打开游标后循环遍历所有的数据
    WHILE TRUE DO
        FETCH cursor_goods INTO gprice, gname;
        INSERT INTO p12_test(price, goods_name) VALUES(gprice, gname);
        END WHILE;
END;

CALL p15(51.15);

3.8 条件处理程序

  • 在 MySQL 存储过程中,条件处理程序用于处理运行时可能遇到的特定条件,如警告、未找到结果或其他 SQL 错误。根据不同的条件,可以选择继续执行程序、终止当前程序或执行其他清理操作。

  • 语法

```sql
DECLARE handler_action HANDLER FOR condition_value
    [statement]
```
  • handler_action:可以是 CONTINUE 或 EXIT。

    • CONTINUE:在遇到指定条件时,继续执行后续程序。

    • EXIT:在遇到指定条件时,终止当前程序的执行。

  • condition_value:指定的 SQL 条件,例如:

    • SQLSTATE 值,例如 02000(表示没有数据行被返回)。

    • SQLWARNING:所有以 01 开头的 SQLSTATE 代码的简写。

    • NOT FOUND:所有以 02 开头的 SQLSTATE 代码的简写。

    • SQLEXCEPTION:捕获所有未被 SQLWARNING 或 NOT FOUND 捕获的 SQLSTATE 代码。

  • 执行示例可以看游标的示例语句

3.9 有返回值的函数

CREATE FUNCTION ad(n INT)
RETURNS INT DETERMINISTIC	#定义返回值类型
BEGIN
    DECLARE res INT DEFAULT 0;

    WHILE n >= 0 DO
        SET res = res + n;
        SET n = n - 1;
    END WHILE;

    RETURN res;
END;

SELECT ad(15);

触发器


1. 基本语法

CREATE TRIGGER trigger_name
[ BEFORE | AFTER ] [ INSERT | UPDATE | DELETE ]
ON table_name
FOR EACH ROW
BEGIN
    -- 触发器逻辑
END;

2. 作用

触发器(Trigger)用于在对表进行插入(INSERT)、更新(UPDATE)或删除(DELETE)操作时,自动执行某一特定操作。触发器可以帮助我们维持数据完整性、自动记录审计日志、实现复杂的业务逻辑等。

3. 注意事项

  • 触发器会在每一行影响的情况下执行,因此在高并发或大批量数据处理时会对性能有影响。

  • 触发器不能被直接调用,并且不能修改调用触发器的表。

  • 在设计触发器时,要注意避免在触发器内进行无限递归调用。


上一页MySQL学习笔记4【存储引擎和索引】下一页MySQL学习笔记6【锁】

最后更新于1天前