MariaDB、MySQL存储过程、游标基础应用举例说明

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: MariaDB、MySQL存储过程、游标基础应用举例说明

MariaDBMySQL存储过程、游标基础应用举例说明


 

测试环境:

MariaDB-10.0.19-centos7-x86_64

 

实践操作:

#创建测试数据库

DROP DATABASE IF EXISTS testdb1;

CREATE DATABASE testdb1;

 

#创建测试表-余额表

DROP TABLE IF EXISTS account;

CREATE TABLE IF NOT EXISTS account

(user_id BIGINT PRIMARY KEY, #用户id

account BIGINT #账户余额

);

 

#创建测试表-创建利润分成表

CREATE TABLE IF NOT EXISTS profit_sharing

(order_id BIGINT PRIMARY KEY, #订单ID

user_id BIGINT,           #用户ID

total_price DECIMAL(9,4), #交易价格

share_price DECIMAL(9,4), #消费返利

FOREIGN KEY(user_id) REFERENCES account(user_id)

);

 

#插入测试数据

INSERT INTO account VALUES(1001, 10000);

INSERT INTO account VALUES(1002, 9000);

 

INSERT INTO profit_sharing VALUES(100001, 1001, 99, 10);

INSERT INTO profit_sharing VALUES(100002, 1002, 90, 5);

 

#场景1:存储过程中的每个查询语句都只返回一条记录

#创建存储过程

DROP PROCEDURE IF EXISTSproc_varify_profit_sharing;  #如果存在proc_varify_profit_sharing则先删除

 

DELIMITER // #使用DELIMITER命令来把语句定界符从;变为// #注意,定界符可以是其它符号,比如$,但是不能为\,因为它是转义字符

#说明,通常情况下,mysql遇到分号;则判断语句结束,并执行该语句,这里DELIMITER //告诉mysql,遇到//则表示语句结束,执行语句

 

CREATE PROCEDURE proc_varify_profit_sharing(

user_id BIGINT,

account_init BIGINT,

order_id BIGINT

)

BEGIN

#声明局部变量

DECLARE account_final BIGINT;       #用于存储最终余额

DECLARE total_price DECIMAL(9, 4);  #用于存储交易总金额

DECLARE share_price DECIMAL(9, 4) DEFAULT 0.00;  #用于存储消费返利金额

 

#说明:BEGIN END;之间定义的变量为局部变量,基础形式:DECLARE变量名数据类型默认值

 

#定义游标

DECLARE cur_get_account_final CURSOR FOR SELECT t1.account FROM account t1 WHERE t1.user_id=user_id;

DECLARE cur_varify_account CURSOR FOR SELECT t2.share_price, t2.total_price FROM profit_sharing t2

WHERE t2.user_id=user_id AND t2.order_id = order_id;

 

#基础语法说明:DECLARE cursor_name CURSOR FOR select_statement;

 

#打开游标

OPEN cur_get_account_final;

OPEN cur_varify_account;

 

#基础语法说明:OPEN cursor_name;

 

#获取数据

FETCH cur_get_account_final INTO account_final;

FETCH cur_varify_account INTO share_price, total_price;

 

#基础语法说明:FETCH cursor_name INTO variable1[, variable2,...]; #读取一行记录(如果有的话)

#并将记录中各项的值赋值给变量variable1variable2,...

#注意,变量个数要和游标指定查询生成记录的记录项的数目要相同,通俗的说,查询生成记录,包含多少列,就指定多少个变量,一一对应

 

#验证金额增减的准确性

SET @tmp = account_final + total_price - share_price;   #使用用户变量@tmp,存放中间计算结果  

SELECT IF(@tmp=account_init, 'right', 'wrong') AS 'result';

 

#说明:用户变量(用户变量也归属局部变量)的定义:@变量名,,

#注意:

#1.mysql中用户变量可不用事前声明,在用的时候直接用“@变量名”使用就可以了,

#2.用户变量跟mysql客户端是绑定的,设置的变量,只对当前用户使用的客户端生效

 

#说明:用SET给变量赋值:SET变量=value;或者SET变量:=value;如上语句所示

小知识:可以用SELECT给变量赋值,类似的有,SELECT变量:=value;SELECT变量:=colunm_name FROM table_name WHERE;

 

注意:使用SELECT时必须用:=

 

#关闭游标

CLOSE cur_get_account_final;

CLOSE cur_varify_account;

#基础语法说明:CLOSE cursor_name;

 

END;

//

 

DELIMITER ; #还原定界符为;

 

#调用存储过程

CALL proc_varify_profit_sharing(1001, 10089, 100001);

 

#调用形式说明:CALL procedure_name()(无参数的话)CALL procedure_name(arg1[, arg2, ...])(带参数)

 

 

# "场景1"不用游标的等价实现

#创建存储过程

DROP PROCEDURE IF EXISTS proc_varify_profit_sharing;

DELIMITER //

CREATE PROCEDURE proc_varify_profit_sharing(

userID BIGINT, #注意,当存储过程参数如果用于存储过程中,表查询语句的WHERE子句,作为筛选条件值时,如果未指定要查询表的表别名,则不能和表的列名相同,参见如下

account_init BIGINT,

orderID BIGINT

)

BEGIN

#定义局部变量

DECLARE account_final BIGINT;       #用于存储最终余额

DECLARE total_price1 DECIMAL(9, 4);  #用于存储交易总金额

DECLARE share_price1 DECIMAL(9, 4);  #用于存储消费返利金额

 

 

#获取数据

SELECT account INTO account_final FROM account WHERE user_id = userID LIMIT 0,1;  # LIMIT 0, 1确保只返回一条记录

#share_price, total_price分别的查询结果分别赋值给局部变量share_price, total_price

SELECT share_price, total_price INTO share_price1, total_price1 FROM profit_sharing

WHERE user_id=userID AND order_id = orderID LIMIT 0,1;

#注意:

#1、未使用游标的情况下,查询语句使用表别名需要添加 AS,如SELECT t1.account INTO account_final FROM account t1;报错,提示t1Undeclared variable ,SELECT t1.account INTO account_final FROM account AS t1则不会报错

#2SELECT column1, ... INTO variable1, ...;如果column1variable1名称不可以相同,否则取不到值,variable1最终的值为NULLMariaDB下测试

 

#验证金额增减的准确性

SET @tmp = account_final + total_price1 - share_price1; #注意:NULL + value1 + ... = NULL

SELECT IF(@tmp=account_init, 'right', 'wrong') AS 'result';

 

END;

//

DELIMITER ;

 

CALL proc_varify_profit_sharing(1001, 10089, 100001);

 

#场景2:返回一个结果集,多条记录(循环读取

#创建存储过程

DROP PROCEDURE IF EXISTS proc_test;

 

DELIMITER //

CREATE PROCEDURE proc_test()

BEGIN

#声明局部变量

DECLARE order_id BIGINT;             #用于存储订单号

DECLARE total_price DECIMAL(9, 4);   #用于存储交易总金额

DECLARE share_price DECIMAL(9, 4) DEFAULT 0.00;  #用于存储消费返利金额

#DECLARE no_more_record INT DEFAULT 0;  #是否还有记录标识

DECLARE no_more_record INT;  #是否还有记录标识

#定义游标

DECLARE cur_get_order_info CURSOR FOR SELECT share_price, total_price FROM profit_sharing;

 

DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_record = 1; #当游标或者SQL选择语句没有返回值时,设置no_more_record=1后继续执行

 

#打开游标

OPEN cur_get_order_info;

 

#读取数据======1

FETCH cur_get_order_info INTO total_price, share_price;

SET no_more_record = 0;

WHILE no_more_record <> 1 DO  #如果存在下一跳记录,则继续读取

   FETCH cur_get_order_info INTO total_price, share_price;

END WHILE;

# ===============2

#注意:如果把行1到行2之间的语句改成如下

#WHILE no_more_record <> 1 DO  #如果存在下一跳记录,则继续读取

#    FETCH cur_get_order_info INTO total_price, share_price;

#END WHILE;

#那么,整个while循环体将执行3(但是表里仅2条记录,为何这样呢?个人想法是这样的:

#第一次循环,no_more_record=0,执行FETCH语句,且游标指针停留在一条记录

#第二次循环,no_more_record=0,执行FETCH语句,且游标指针停留在二条记录

#第三次循环,no_more_record=0,执行FETCH语句,且游标指针移动到下一条,结果无记录,no_more_record=1,结束下次循环

#所以,while循环之前要先执行一次

 

#关闭游标

CLOSE cur_get_order_info;

 

END;

//

 

DELIMITER ;

 

CALL proc_test();

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
4月前
|
关系型数据库 MySQL 分布式数据库
安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景
PolarDB分布式轻量版采用软件输出方式,能够部署在您的自主环境中。PolarDB分布式轻量版保留并承载了云原生数据库PolarDB分布式版技术团队深厚的内核优化成果,在保持高性能的同时,显著降低成本。
547 140
|
2月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
2月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
2月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
3月前
|
存储 关系型数据库 MySQL
MYSQL数据加密压缩函数应用实战指南。
总的来说,加密和压缩是维护MySQL数据库中数据安全性和效率的有效手段。使用时需权衡性能与安全,合理应用加密和压缩函数。在设计数据库架构时要考虑到加密字段的查询性能,因为加密可能使得一些索引失效。压缩数据能有效减少存储空间的占用,但在服务器负载较高时应避免实时压缩和解压,以免影响总体性能。
148 10
|
2月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
|
9月前
|
存储 Java 关系型数据库
java调用mysql存储过程
在 Java 中调用 MySQL 存储过程主要借助 JDBC(Java Database Connectivity)。其核心原理是通过 JDBC 与 MySQL 建立连接,调用存储过程并处理结果。具体步骤包括:加载 JDBC 驱动、建立数据库连接、创建 CallableStatement 对象、设置存储过程参数并执行调用。此过程实现了 Java 程序与 MySQL 数据库的高效交互。
|
存储 关系型数据库 MySQL
MySQL在企业内部应用场景有哪些
【10月更文挑战第17天】MySQL在企业内部应用场景有哪些
515 0
|
8月前
|
存储 关系型数据库 MySQL
【YashanDB知识库】MySQL返回结果集的存储过程的改写方法
本文介绍了将MySQL存储过程改写至YashanDB的解决方案。由于MySQL存储过程可直接返回结果集,而YashanDB需通过返回SYS_REF_CURSOR的函数实现类似功能,因此需要对代码进行转换。示例中展示了如何将MySQL存储过程`proc1`改写为YashanDB函数,并调整JDBC应用代码以适配REF_CURSOR输出参数,从而正确获取查询结果。此方法确保了跨数据库场景下的兼容性与功能性。
|
12月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
309 2

推荐镜像

更多