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

MySQL性能:存储过程+触发器基础实战攻略

MySQL性能:存储过程+触发器基础实战攻略

一、MySQL中的存储过程

1.基础概念

1.1 什么是存储过程?

  • 定义:存储过程是预编译SQL语句的集合存储在数据库中,通过传递参数执行,可封装复杂业务逻辑,提升执行效率

  • 优势

    • 减少网络交互(单词调用代替多次SQL传输)
    • 编译一次,重复调用无需重新编译
    • 通过权限控制增强数据安全性

1.2基本语法

-- 创建存储过程
DELIMITER $$ 	-- 修改结束符避免冲突
CREATE PROCEDURE procedure_name(参数列表)
BEGIN 
	SQL语句;
END $$
DELIMITER ; 	-- 恢复默认结束符

-- 调整存储过程
CALL procedure_name(参数);

-- 删除存储过程
DROP PROCEDURE IF EXISTS procedure_name;

2.参数与变量

2.1 参数类型

类型说明示例
IN输入参数(类型)IN user_id INT
OUT输出参数OUT total_sales DECMAL
INOUT双向参数(可输入输出)INOUT counter INT

2.2 变量使用

  • 用户变量:以@开头,当前会话有效

    SET @var_name = 100; --赋值
    SELECT @var_name; 	 --查看
    
  • 局部变量:需要DECLARE 声明,仅在BEGIN/END块内有效

3.流程控制

3.1 条件语句(两种)

 -- 基础语法:IF-THEN-ELSE
 IF CONDITION THEN
 	statements;
ELSEIF another_condition THEN
	statements;
ELSE
	statements;
END IF;


-- CASE 语句  CASE-WHEN
CASE variale
	WHEN value1 THEN statements;
	WHEN value1 THEN statements;
	ELSE statements;
END CASE;

3.2 循环语句

循环类型特点示例
WHILE先判断后执行WHILE i < 10 DO ... END WHILE;
LOOP至少执行一次,需配合LEAVE退出loop_label: LOOP ... IF exit_condition THEN LEAVE loop_label; END IF; END LOOP;
REPEAT先执行后判断REPEAT ... UNTIL condition END REPEAT;
  • WHILE

    WHILE I<10 DO
    	statements;
    END WHILE;
    
  • loop

    loop_label:
    	loop ...
    	IF condition THEN
    		LEAVE loop_labe;
    	END IF;
    	END Loop;
    
  • REPEAT

    REPEAT ... 
    UNTIL condition
    END REPEAT
    

4.游标与异常处理

4.1 游标

  • 作用:用于逐行处理查询结果集,适用于复杂数据处理场景

    DECLARE	cur CURSOR FOR SELECT colum FROM table; -- 声明游标
    OPEN cur; -- 打开游标
    FETCH cur INTO @var; -- 获取数据到变量
    CLOSE cur; -- 关闭游标
    DEALLOCATE cur; -- 释放游标
    

4.2 异常处理

  • 作用:通过DECLARE HANDLER 捕获错误,确保事务完整性

    DECLARE EXIT HANDLER FOR SQLEXCEPTION -- 获取SQL异常
    BEGIN
    	ROLLBACK; -- 回滚事务
    	SELECT 'Error occurred, transaction rolled back';
    END;
    
  • DECLAER ...HANDLER:捕获指定条件,并以处理逻辑

    • 条件类型

      • SQLEXCEPTION:SQL错误(如约束冲突)

      • SQLWARING:警告

      • NOT FOUND :无匹配记录(常见于游标)

  • 处理程序类型

    • EXIT HANDLER :执行处理后退出当前代码块
    • CONTINUE HANDLER:执行处理后继续执行后续代码

5.综合案例

5.1 用户注册存储过程

-- 用户从前端输入数据,传输到后端,我只需要进行存储。 相当于MysQL中的输入,输入成功后,我们需要返回结果!
DELIMITER $$

CREATE PROCEDURE RegisterUser(
	IN p_username VARCHAR(50)
    IN P_email VARCHAR(100),
    OUT P_result VARCHAR(100)
)
BEGIN
	DECLARE user_exists INT DEFAULT 0;
	
	-- 检查用户名是否存在
	SELECT COUNT(*) INTO user_exists
	FROM users
	WHERE username = p_username;
	
	IF user_exists > 0 THEN
		SET p_result = 'Username already exists';
	ELSE
		INSERT INTO users(username, email)
		VALUES (p_username,p_email);
		SET p_result = 'Registration successful';
	END IF;
END $$

DECLARE ;

-- 调用示例
CALL RegisterUser('alice','alice@example.com',@result);
SELECT @result; -- 结果
	

5.2使用游标遍历数据

DELIMITER $$

CREATE PROCEDURE ProcessUsers()
BEGIN 
	DECLARE done INT DEFAULT FALSE;
    DECLARE user_id INT;
    DECLARE user_name VARCHAR(50);
    
    -- 声明游标
    DECLARE cur CURSOR FOR SELECT id,name FROM user;
    
    -- 异常处理:未找到数据时退出循环
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = True;
    
    OPEN cur;
    read_loop:LOOP
    	FETCH cur INTO user_id,user_name;
    	IF done THEN
    		LEVEL read_loop;
    	END IF;
    	
    	
    	-- 处理每一行数据(打印)
    	SELECT CONCAT('ID:',user_id, ',name:',user_name);
	END LOOP;
	CLOSE cur;
END $$
DELIMITER ;

-- 调用示例
CALL ProcessUsers()

二、MYSQL中的触发器

1.基础概念

1.1 什么是触发器

触发器(Trigger)是数据库中的一种特殊对象,当指定事件(插入、更新、删除)在表中发生时自动执行一段预定义的SQL代码。

  • 触发时机:BEFORE 操作前 或AFTER 操作后

  • 行级触发:对每一条受影响的数据行触发(MySQL 仅支持行级触发)

  • 核心用途:数据验证、审计跟踪、自动维护衍生数据(统计字段)、强制业务规则

1.2 基本语法

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT |UPDATE |DELETE}
ON table_name FOR EACH ROW
BEGIN
	-- 触发器的逻辑(使用NEW 和 OLD访问数据)
END;

1.3 触发器的逻辑

访问旧数据和新数据

  • OLD: 引用被更新或删除的旧数据(UPDATE/DELETE可用)
  • NEW:引用插入或更新后的新数据(INSERT/UPDATE可用)

2.案例

2.1 审计日志

记录用户表的变更

-- 创建审计表
CREATE TABLE user_audit(
	id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    old_name VARCHAR(50),
    new_name VARCHAR(50),
    change_time TIMESTAMP
);

-- 创建AFTER UPDATE 触发器
DELIMITER $$
CREATE TRIGGER after_user_update
AFTER UPDATE 
ON users FOR EACH ROW
BEGIN
	INSERT INTO user_audit (user_id, old_name, new_name, change_time)
    VALUES (OLD.id, OLD.name, NEW.name, NOW());
END $$
DELIMITER ;

2.2 数据验证与约束

阻止不合法的数据插入(BEFORE INSERT)

DELIMITER $$
CREATE TRIGGER before_employees_insert
BEFORE INSERT
ON emloyees FOR EACH ROW
BEGIN
	IF NEW.salary < 3000 THEN
		SIGNAL SQLSTATE '45000' 
		SET MESSAGE_TEXT = 'Salary cannot be less than 3000'
	END IF;
END $$
DELIMITER ;
  • SIGNAL:MySQL中用于"返回"错误或警告信息的语句。 它允许开发者在存储过程中,函数或触发器中,根据特定的条件生成自定义的错误或警告信息。

  • SQLSTATE: 用于SQL操作状态的标准代码,它用于指示错误的类型或警告的性质

    -- 基础语法:
    SIGNAL SQLSTATE 'sqlstate_value'
    SET MESSAGE_TEXT = 'message' -- 可选 字符串,提供详细的错误信息或警告信息
    SET MSYQL_ERRNO = 'error_code' -- 可选 整数,用于表示MySQL的错误代码
    

2.3 自动维护衍生数据

更新订单总金额同时同步用户消费总额(订单总金额,用户消费总金额

DELIMITER $$
CREATE TRIGGER after_order_update
AFTER UPDATE 
ON order FOR EACH ROW
BEGIN
	UPDATE users
	SET total_spent = total_spent + (NEW.amount - OLD.amount)
	WHERE id = NEW.user_id;
END $$
DELIMITER;

3.触发器的执行顺序与限制

  • 执行顺序:同一表的同一事件触发时,按照触发器创建的是顺序执行
  • 限制
    • 不能再触发器对本表执行INSERT/UPDATE/DELETE
    • 触发器不能调用存储过程或动态SQL
    • 不支持显示事务控制(commit/rollback)

4.触发器的管理命令

4.1查看触发器

-- 查看触发器
SHOW TRIGGER FROM database_name;

-- 或查询information_schema
SELECT * FROM information_schema.triggers
WHERE trigger_schema = 'database_name';

4.2删除触发器

DROP TRIGGER [IF EXISTS] database_name.trigger_name;

5.适用场景

  • 适用
    • 审计日志、数据版本跟踪。
    • 简单字段级校验或自动填充(如更新时间戳)。
    • 维护冗余统计字段(需权衡一致性)。
  • 不适用
    • 复杂业务逻辑(优先用应用层代码)。
    • 高频交易场景(如每秒数千次写入)。
    • 需要跨数据库操作的场景。

6.注意事项

  • 性能影响:高频写操作的表避免复杂触发器逻辑
  • 可维护性:触发器逻辑应简单清洗,比卖你隐藏业务规则
  • 错误处理:触发器中的错误会导致主操作回滚(如SIGNAL)
  • 权限要求:创建触发器需要TRIGGER权限
  • 测试:确保触发器和主操作在事务中协同工作
http://www.dtcms.com/a/106445.html

相关文章:

  • Mysql中,利用窗口函数来优化掉子查询或者group by
  • IPD推进中关键角色与岗位(二)系统工程师SE确保产品开发过程的高效协同,减少项目失败的风险
  • mysql数据库通过命令行导入sql文件
  • Rust 中的高效视频处理:利用硬件加速应对高分辨率视频
  • 【2025】实操成功-使用Python连接谷歌邮箱发送邮件
  • PostgreSQL:高级SQL特性
  • 【接口重复请求】axios通过AbortController解决页面切换过快,接口重复请求问题
  • windosw11中的.msi文件打不开该怎么办?
  • [python] python四大数据结构(列表 元组 集合 字典)剖析
  • firefox 136.0.4版本离线安装MarkDown插件
  • JavaScript重难点突破:期约与异步函数
  • 从实用的角度聊聊Linux下文本编辑器VIM
  • LambdaQueryWrapper解释一下
  • Ubuntu 20.04 中 Git 的安装、配置和基本操作指南
  • Element Plus 主题色定制指南:从原理到实战
  • Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
  • L2-001 紧急救援
  • 编译原理:first集和follow
  • Python数据类型 - 元组(Tuple)
  • 第四章:检索器(Retriever)设计:从向量到图谱
  • Windows 实战-evtx 文件分析--做题笔记
  • Qt中的数据解析--XML与JSON处理全攻略
  • 前端开发时的内存泄漏问题
  • 数据结构第6篇:手撕排序算法(插入、希尔、堆)
  • 【通用级联选择器回显与提交处理工具设计与实现】
  • 中和农信:让金融“活水”精准浇灌乡村沃土
  • RustDesk 开源远程桌面软件 (支持多端) + 中继服务器伺服器搭建 ( docker版本 ) 安装教程
  • windows使用Python调用7-Zip【按大小分组】压缩文件夹中所有文件
  • C# Winform 入门(3)之尺寸同比例缩放
  • 山东大学《多核平台下的并行计算》实验笔记