独立站建设哪家好网页搜索快捷键是什么
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-ELSEIF CONDITION THENstatements;
ELSEIF another_condition THENstatements;
ELSEstatements;
END IF;-- CASE 语句 CASE-WHEN
CASE varialeWHEN 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 DOstatements; END WHILE;
-
loop
loop_label:loop ...IF condition THENLEAVE 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异常 BEGINROLLBACK; -- 回滚事务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)
)
BEGINDECLARE user_exists INT DEFAULT 0;-- 检查用户名是否存在SELECT COUNT(*) INTO user_existsFROM usersWHERE username = p_username;IF user_exists > 0 THENSET p_result = 'Username already exists';ELSEINSERT 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:LOOPFETCH cur INTO user_id,user_name;IF done THENLEVEL 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
BEGININSERT 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
BEGINIF NEW.salary < 3000 THENSIGNAL 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
BEGINUPDATE usersSET 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权限
- 测试:确保触发器和主操作在事务中协同工作