1. 首页 > MariaDB教程 > 正文

MariaDB教程FG023-MariaDB存储过程开发与业务逻辑封装实战

内容简介:本文风哥教程参考MariaDB官方文档MariaDB Server、Stored Procedures等章节,详细讲解MariaDB存储过程的开发与业务逻辑封装,包括存储过程的创建、执行、调试和优化。

Part01-基础概念与理论知识

1.1 存储过程基本概念

存储过程是一组预编译的SQL语句,存储在数据库中,可以通过名称调用执行。它可以接收参数,执行复杂的业务逻辑,并返回结果。

1.2 存储过程语法结构

MariaDB存储过程的基本语法结构:

  • CREATE PROCEDURE:创建存储过程
  • 参数类型:IN(输入参数)、OUT(输出参数)、INOUT(输入输出参数)
  • BEGIN…END:存储过程体
  • DECLARE:声明变量
  • IF…THEN…ELSE:条件判断
  • LOOP、WHILE、REPEAT:循环结构
  • CALL:调用存储过程

1.3 存储过程优势与适用场景

  • 优势:
    • 减少网络传输量
    • 提高执行效率
    • 封装业务逻辑
    • 增强安全性
    • 便于维护
  • 适用场景:
    • 复杂的业务逻辑处理
    • 批量数据操作
    • 数据校验与转换
    • 定期执行的任务
更多视频教程www.fgedu.net.cn

Part02-生产环境规划与建议

2.1 存储过程设计原则

风哥提示:良好的存储过程设计可以提高代码可维护性和执行效率。
  • 单一职责:每个存储过程只负责一个功能
  • 参数化设计:使用参数传递,避免硬编码
  • 错误处理:包含异常捕获和处理机制
  • 事务管理:合理使用事务确保数据一致性
  • 命名规范:使用统一的命名标准

2.2 性能优化建议

  • 避免使用游标,尽量使用集合操作
  • 合理使用索引
  • 减少临时表的使用
  • 避免在循环中执行SQL语句
  • 使用预处理语句
  • 定期更新统计信息

2.3 生产环境最佳实践

  • 版本控制:将存储过程代码纳入版本管理
  • 文档化:为存储过程编写详细的文档
  • 测试:在开发环境充分测试
  • 监控:监控存储过程的执行性能
  • 安全:限制存储过程的执行权限
学习交流加群风哥微信: itpux-com

Part03-生产环境项目实施方案

3.1 存储过程创建与管理

更多学习教程公众号风哥教程itpux_com

# 创建存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_get_user(IN user_id INT)
BEGIN
SELECT * FROM fgedu_users WHERE id = user_id;
END //
DELIMITER;
Query OK, 0 rows affected (0.01 sec)
# 查看存储过程
MariaDB [fgedudb]> SHOW CREATE PROCEDURE fgedu_get_user\G
*************************** 1. row ***************************
Procedure: fgedu_get_user
sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`@`fgedu.localhost` PROCEDURE `fgedu_get_user`(IN `user_id` INT)
BEGIN
SELECT * FROM fgedu_users WHERE id = user_id;
END
character_set_client: utf8mb4
collation_connection: utf8mb4_unicode_ci
database_collation: utf8mb4_unicode_ci
# 调用存储过程
MariaDB [fgedudb]> CALL fgedu_get_user(1);
+—-+——+———————+
| id | name | created_at |
+—-+——+———————+
| 1 | user | 2023-01-01 00:00:00 |
+—-+——+———————+
# 修改存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> ALTER PROCEDURE fgedu_get_user(IN user_id INT)
BEGIN
SELECT id, name FROM fgedu_users WHERE id = user_id;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 删除存储过程
MariaDB [fgedudb]> DROP PROCEDURE IF EXISTS fgedu_get_user;
Query OK, 0 rows affected (0.00 sec)

3.2 存储过程参数与返回值

# 创建带输出参数的存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_get_user_count(OUT total_count INT)
BEGIN
SELECT COUNT(*) INTO total_count FROM fgedu_users;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 调用带输出参数的存储过程
MariaDB [fgedudb]> CALL fgedu_get_user_count(@count);
Query OK, 1 row affected (0.00 sec)
MariaDB [fgedudb]> SELECT @count;
+——-+
| @count |
+——-+
| 10 |
+——-+
# 创建带输入输出参数的存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_increment(INOUT value INT)
BEGIN
SET value = value + 1;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 调用带输入输出参数的存储过程
MariaDB [fgedudb]> SET @num = 5;
Query OK, 0 rows affected (0.00 sec)
MariaDB [fgedudb]> CALL fgedu_increment(@num);
Query OK, 0 rows affected (0.00 sec)
MariaDB [fgedudb]> SELECT @num;
+——+
| @num |
+——+
| 6 |
+——+

3.3 错误处理与事务管理

# 创建带错误处理的存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_transaction_demo(IN user_id INT, IN amount DECIMAL(10,2))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT ‘Error occurred, transaction rolled back’ AS message;
END;
START TRANSACTION;
— 扣减账户余额
UPDATE fgedu_accounts SET balance = balance – amount WHERE user_id = user_id;
— 记录交易
INSERT INTO fgedu_transactions (user_id, amount, type) VALUES (user_id, amount, ‘debit’);
COMMIT;
SELECT ‘Transaction completed successfully’ AS message;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 测试存储过程
MariaDB [fgedudb]> CALL fgedu_transaction_demo(1, 100.00);
+———————————-+
| message |
+———————————-+
| Transaction completed successfully |
+———————————-+
# 测试错误处理
MariaDB [fgedudb]> CALL fgedu_transaction_demo(999, 100.00);
+——————————————+
| message |
+——————————————+
| Error occurred, transaction rolled back |
+——————————————+
学习交流加群风哥QQ113257174

Part04-生产案例与实战讲解

4.1 基础存储过程示例

# 示例1:用户注册存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_register_user(
-> IN p_name VARCHAR(50),
-> IN p_email VARCHAR(100),
-> IN p_password VARCHAR(100),
-> OUT p_user_id INT
-> )
BEGIN
INSERT INTO fgedu_users (name, email, password, created_at)
VALUES (p_name, p_email, MD5(p_password), NOW());
SET p_user_id = LAST_INSERT_ID();
— 创建用户账户
INSERT INTO fgedu_accounts (user_id, balance, created_at)
VALUES (p_user_id, 0.00, NOW());
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 调用注册存储过程
MariaDB [fgedudb]> CALL fgedu_register_user(‘John Doe’, ‘john@fgedu.net.cn’, ‘password123’, @user_id);
Query OK, 2 rows affected (0.01 sec)
MariaDB [fgedudb]> SELECT @user_id;
+———+
| @user_id |
+———+
| 11 |
+———+
# 示例2:批量插入数据存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_batch_insert(IN p_count INT)
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= p_count DO
INSERT INTO fgedu_test (name, value)
VALUES (CONCAT(‘test_’, i), i);
SET i = i + 1;
END WHILE;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 调用批量插入存储过程
MariaDB [fgedudb]> CALL fgedu_batch_insert(100);
Query OK, 1 row affected (0.05 sec)
# 验证数据
MariaDB [fgedudb]> SELECT COUNT(*) FROM fgedu_test;
+———-+
| COUNT(*) |
+———-+
| 100 |
+———-+

4.2 业务逻辑封装实战

# 示例:订单处理存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_process_order(
-> IN p_user_id INT,
-> IN p_product_id INT,
-> IN p_quantity INT,
-> OUT p_order_id INT,
-> OUT p_status VARCHAR(20)
-> )
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET p_status = ‘ERROR’;
END;
DECLARE v_product_price DECIMAL(10,2);
DECLARE v_stock INT;
DECLARE v_total_amount DECIMAL(10,2);
START TRANSACTION;
— 检查商品库存
SELECT price, stock INTO v_product_price, v_stock
FROM fgedu_products WHERE id = p_product_id;
IF v_stock < p_quantity THEN
SET p_status = ‘OUT_OF_STOCK’;
ROLLBACK;
RETURN;
END IF;
— 计算总金额
SET v_total_amount = v_product_price * p_quantity;
— 检查用户余额
IF (SELECT balance FROM fgedu_accounts WHERE user_id = p_user_id) < v_total_amount THEN
SET p_status = ‘INSUFFICIENT_BALANCE’;
ROLLBACK;
RETURN;
END IF;
— 扣减库存
UPDATE fgedu_products SET stock = stock – p_quantity WHERE id = p_product_id;
— 扣减用户余额
UPDATE fgedu_accounts SET balance = balance – v_total_amount WHERE user_id = p_user_id;
— 创建订单
INSERT INTO fgedu_orders (user_id, total_amount, status, created_at)
VALUES (p_user_id, v_total_amount, ‘PENDING’, NOW());
SET p_order_id = LAST_INSERT_ID();
— 创建订单明细
INSERT INTO fgedu_order_items (order_id, product_id, quantity, price)
VALUES (p_order_id, p_product_id, p_quantity, v_product_price);
— 记录交易
INSERT INTO fgedu_transactions (user_id, order_id, amount, type, created_at)
VALUES (p_user_id, p_order_id, v_total_amount, ‘PURCHASE’, NOW());
COMMIT;
SET p_status = ‘SUCCESS’;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 调用订单处理存储过程
MariaDB [fgedudb]> CALL fgedu_process_order(1, 1, 2, @order_id, @status);
Query OK, 1 row affected (0.01 sec)
MariaDB [fgedudb]> SELECT @order_id, @status;
+———-+——–+
| @order_id | @status |
+———-+——–+
| 1 | SUCCESS |
+———-+——–+

4.3 存储过程调试与优化

# 启用存储过程调试
MariaDB [fgedudb]> SET GLOBAL log_bin_trust_function_creators = 1;
Query OK, 0 rows affected (0.00 sec)
# 创建调试存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_debug_demo()
BEGIN
DECLARE v_counter INT DEFAULT 0;
DECLARE v_max INT DEFAULT 100000;
DECLARE v_start_time TIMESTAMP;
SET v_start_time = NOW();
WHILE v_counter < v_max DO
INSERT INTO fgedu_debug (value, created_at) VALUES (v_counter, NOW());
SET v_counter = v_counter + 1;
END WHILE;
SELECT TIMESTAMPDIFF(SECOND, v_start_time, NOW()) AS execution_time;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 测试调试存储过程
MariaDB [fgedudb]> CALL fgedu_debug_demo();
+—————-+———–+
| execution_time |
+—————-+———–+
| 15 |
+—————-+———–+
# 优化存储过程 – 使用批量插入
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_optimized_demo()
BEGIN
DECLARE v_counter INT DEFAULT 0;
DECLARE v_max INT DEFAULT 100000;
DECLARE v_start_time TIMESTAMP;
DECLARE v_values TEXT DEFAULT ”;
SET v_start_time = NOW();
WHILE v_counter < v_max DO
SET v_values = CONCAT(v_values, ‘(‘, v_counter, ‘, NOW())’);
IF v_counter < v_max - 1 THEN
SET v_values = CONCAT(v_values, ‘,’);
END IF;
SET v_counter = v_counter + 1;
END WHILE;
SET @sql = CONCAT(‘INSERT INTO fgedu_debug (value, created_at) VALUES ‘, v_values);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SELECT TIMESTAMPDIFF(SECOND, v_start_time, NOW()) AS execution_time;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 测试优化后的存储过程
MariaDB [fgedudb]> CALL fgedu_optimized_demo();
+—————-+———–+
| execution_time |
+—————-+———–+
| 2 |
+—————-+———–+
风哥提示:安全开发是防止SQL注入的第一道防线

Part05-风哥经验总结与分享

5.1 存储过程开发经验

在实际生产环境中,存储过程的开发需要注意以下几点:

  • 合理设计存储过程的结构,避免过于复杂
  • 使用参数化设计,提高代码的可重用性
  • 包含完整的错误处理机制
  • 合理使用事务,确保数据一致性
  • 定期优化存储过程的性能

5.2 常见问题与解决方案

  • 性能问题:
    • 问题:存储过程执行缓慢
    • 解决方案:优化SQL语句、使用索引、减少循环操作
  • 内存问题:
    • 问题:存储过程占用内存过多
    • 解决方案:减少变量使用、优化数据类型、分批处理数据
  • 调试问题:
    • 问题:存储过程调试困难
    • 解决方案:添加日志输出、使用变量跟踪执行过程

5.3 生产故障案例分析

某电商系统在大促销期间出现存储过程执行超时的问题,经过分析发现:

  • 问题原因:
    • 存储过程中使用了大量的循环操作
    • 没有合理使用索引
    • 事务范围过大
  • 解决方案:
    • 将循环操作改为批量操作
    • 为查询条件添加索引
    • 拆分大事务为小事务
    • 优化存储过程的逻辑结构
  • 效果:存储过程执行时间从分钟级降至秒级,系统并发处理能力提升5倍
from MariaDB视频:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息