[数据库]MYSQL之存储过程
一 存储过程的特点
MySQL 5.0 版本开始支持存储过程
1.1 定义
- 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。
- 存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。
- 存储过程在思想上很简单,就是数据库 SQL 语言层面的【代码封装与重用】。
1.2 优点
- 存储过程【可封装】,并【隐藏复杂的商业逻辑】。
- 存储过程【可回传值】,并【可接受参数】。
- 存储过程【无法使用 SELECT 指令来运行】。因为它是子程序,与查看表,数据表或用户定义函数不同。
- 存储过程【可用在数据检验】,【强制实行商业逻辑】等。
- 存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件,虽然它们的作用不仅限于批处理。
1.3 缺点
尽管有这些缺陷,存储过程还是非常有用的,并且应该尽可能地使用。
- 【移植性:差】。往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
- 【编程开发的复杂程度:高】。一般来说,存储过程的编写比基本SQL语句复杂,编写存储过程需要更高的技能,更丰富的经验。
- 用户可能【没有创建存储过程的安全访问权限】。许多数据库管理员限制存储过程的创建权限,允许用户使用存储过程,但不允许他们创建存储过程。
1.4 具体业务场景
迄今为止,使用的大多数SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单,经常会有一个完整的操作需要多条语句才能完成。例如,考虑以下的情形。
- 为了处理订单,需要核对以保证库存中有相应的物品。
- 如果库存有物品,这些物品需要预定以便不将它们再卖给别的人,并且要减少可用的物品数量以反映正确的库存量。
- 库存中没有的物品需要订购,这需要与供应商进行某种交互。
- 关于哪些物品入库(并且可以立即发货)和哪些物品退订,需要通知相应的客户。
1.5 适用场景:简单、安全、高性能
- 1通过把处理封装在容易使用的单元中,【简化复杂的操作】。
- 2由于不要求反复建立一系列处理步骤,这【保证了数据的完整性和一致性】。如果所有开发人员和应用程序都使用同一(试验和测试)存储过程,则所使用的代码都是相同的。这一点的延伸就是【防止错误】。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。
- 3【简化对变动的管理】。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。这一点的延伸就是【安全性】。通过存储过程限制对基础数据的访问减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。
- 4【提高性能】。因为使用存储过程比使用单独的SQL语句要快。
- 5存在一些只能用在单个请求中的MySQL元素和特性,存储过程可以使用它们来【编写功能更强更灵活的代码】。
二 存储过程的使用 -- 创建与调用
2.1 无参数的存储过程
-- DELIMITER $$ # [可选项]声明语句结束符 - 将语句的结束符号从分号;临时改为两个$$(即 可自定义)
DROP PROCEDURE IF EXISTS procedure_view_all_student;
CREATE PROCEDURE procedure_view_all_student() -- 查看所有学生信息
BEGIN -- 1执行段 - 起始
DECLARE varName INT DEFAULT 0; -- 变量 de 声明
SET varName = 100+1; -- 变量 de 赋值(SET =) 1
# 变量(varName)
# 变量的使用: 必须先声明,才能后使用
# 变量的声明格式: DECLARE variable_name datatype(size) [DEFAULT default_value];
SELECT COUNT(*) INTO varName FROM Student; -- 变量 de 赋值(SELECT INTO) 2
SELECT varName AS '总人数'; -- 变量 de 输出
END; -- 2执行段 - 结束
-- END $$
CALL procedure_view_all_student;
2.2 仅含输入参数(IN)的存储过程
DROP PROCEDURE IF EXISTS procedure_view_select_course_of_one_student; -- 查看 指定某一学生的选课信息
CREATE PROCEDURE procedure_view_select_course_of_one_student(IN sno CHAR(9))
BEGIN
SELECT * FROM select_course AS sc WHERE sc.sno = sno;
END;
CALL procedure_view_select_course_of_one_student('201215121');
2.3 仅含输出参数(OUT)的存储过程
DROP PROCEDURE IF EXISTS procedure_view_total_student; -- 查看 总共的学生数目
CREATE PROCEDURE procedure_view_total_student(OUT total INT)
BEGIN
SELECT COUNT(*)
INTO total
FROM select_course AS sc;
END;
CALL procedure_view_total_student(@total_student);
SELECT @total_student AS '学生总人数';
2.4 含又作输出又作输入参数(INOUT)的存储过程
DROP PROCEDURE IF EXISTS procedure_create_huge_test_records_for_student;
CREATE PROCEDURE procedure_create_huge_test_records_for_student(INOUT records_num INT) -- 插入 指定数目的学生信息的测试数据
BEGIN
DECLARE sno CHAR(9);
DECLARE sname VARCHAR(30);
DECLARE ssex VARCHAR(2) DEFAULT '男';
DECLARE sage SMALLINT DEFAULT 29;
DECLARE sdept VARCHAR(50) DEFAULT 'MS';
DECLARE counter INT;
SET counter = records_num;
START TRANSACTION; -- 整个存储过程指定为1个事务
-- ↑ 大量插删数据时,追加事务可避免插删每条数据时频繁的磁盘IO交互,便不再受磁盘IO限制,暂存到了内存缓存区,以此大大提高速度
WHILE counter >= 1 DO
SELECT MID(UUID(), 1, 9) INTO sno; -- 从36位的字符串UUID()中的第1个位置截取9个字符:
SELECT MID(UUID(), 1, 5) INTO sname;
insert into Student (`sno`, `sname`, `ssex`, `sage`, `sdept`) VALUES(sno, sname, ssex, sage, sdept);
SET counter = counter - 1;
END WHILE;
COMMIT; -- 必须主动提交
END;
SET @records_num = 200000; #插入20万条数据 总计 36.296秒(启用了事务 start transaction + sql... + commit)
call procedure_create_huge_test_records_for_student(@records_num);
SELECT * FROM student WHERE student.sno= '1231546-';
2.5 循环存储过程
2.5.1 简单示例
# DEMO - 存储过程 - 循环篇
-- CALL testloop(@out1); SELECT @out1 as out; --out := 11
CREATE PROCEDURE testloop(OUT outvalue INT(11))
BEGIN
DECLARE max_value INT(11) DEFAULT 10;
DECLARE i INT(11); -- 局部变量(i , max_value) 必须先声明,后使用
SET i = 0;
myLoop:LOOP
SET i = i+1;
IF i > max_value THEN
LEAVE myLoop;
END IF;
END LOOP myLoop;
SET outvalue = i;
END
2.5.2 自动插入N条记录
/**
* 自动插入 `Person`表 amount 条记录
* @param in amount : 插入自动测试记录的总数
* @param out result: 执行结果
*/
# 1 [调用存储过程]
-- SET @number = 10; CALL loopInsertRecords(@number, @exe_result); SELECT @exe_result as `执行结果`;
-- `执行结果` := [执行结果]成功10; 失败:0
# 2 [创建 存储过程]
DROP PROCEDURE IF EXISTS `loopInsertRecords`;
CREATE PROCEDURE loopInsertRecords(IN amount INT(10), OUT result VARCHAR(100))
BEGIN
DECLARE i INT(10) DEFAULT 1; -- 局部变量 必须先声明,后使用
DECLARE success INT DEFAULT 0;
DECLARE fail INT DEFAULT amount;
DECLARE hasSqlError INT DEFAULT FALSE; -- 声明1个变量,标识是否有SQL异常
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET hasSqlError=TRUE; -- 在执行过程中出任何SQL异常, 则: 设置hasSqlError为TRUE
myLoop:LOOP
SET i = i+1;
START TRANSACTION; -- transaction start
INSERT INTO `CJ_TEST`.`Person` (
`CSSJY111`,
`CSSJY107`,
`CSSJY106`,
`CSSJY112`,
`CSSJY103`,
`CSSJY113`,
`CSSJY104`,
`CSSJY108`,
`CSSJY102`,
`CSSJY109`,
`CSSJY101`,
`CSSJY110`,
`CSSJY105`
) VALUES (
SUBSTR(REPLACE(UUID(), "-", "@"),1, 3),
1,
2,
DATE_ADD(NOW(), INTERVAL -10 DAY), -- INTERVAL -N DAY: N天前; INTERVAL N DAY: N天后
SUBSTR(REPLACE(UUID(), "-", "@"),1, 10),
"blob-data",
SUBSTR(REPLACE(UUID(), "-", "#"),1, 10),
SUBSTR(REPLACE(UUID(), "-", "$"),1, 10),
SUBSTR(REPLACE(UUID(), "-", "%"),1, 10),
SUBSTR(REPLACE(UUID(), "-", "&"),1, 10),
SUBSTR(REPLACE(UUID(), "-", "*"),1, 10),
DATE_ADD( NOW(), INTERVAL 10 DAY ), -- INTERVAL -N DAY: N天前; INTERVAL N DAY: N天后
( SELECT ROUND( exp(sum(log(RAND())+log(100))) , 0 ) )
);
IF hasSqlError THEN -- 根据hasSqlError判断是否有异常,做回滚和提交操作
ROLLBACK;
ELSE
COMMIT; -- transaction end
SET success = success+1;
END IF;
IF i > amount THEN
LEAVE myLoop;
END IF;
END LOOP myLoop;
SET fail = amount - success;
SET result = CONCAT("[执行结果]成功", success, "; 失败:", fail);
END
三 存储过程的使用 -- 查看与删除
3.1 查看指定表的存储过程
3.1.1 查看 表内的存储过程 【基本信息】
[方式1]
-- 语法格式: SHOW {PROCEDURE | FUNCTION} STATUS [LIKE ‘pattern’]
SHOW PROCEDURE STATUS; -- 存储过程
show create procedure <proc_name>;
SHOW FUNCTION STATUS; -- 函数
SELECT * FROM information_schema.VIEWS -- 视图
SELECT * FROM information_schema.TABLES -- 表
SHOW TRIGGERS [FROM db_name] [LIKE expr] -- 触发器
SELECT * FROM triggers T WHERE trigger_name="mytrigger" \G
[方式2]
select `name` from mysql.proc where db = 'sys' and `type` = 'PROCEDURE' -- 存储过程
-- mysql 5.x - 7.x 默认支持此表;
-- mysql 8.0 默认不支持此表;解决方法:数据层引用的 MySql.Data.dll 这个插件版本过低导致的,可尝试更新官网最新的 MySql.Data.dll (https://www.cnblogs.com/xuling-297769461/p/10570040.html)
3.1.2 查看 表内的存储过程 【详细信息】
SHOW CREATE PROCEDURE indexName;
3.2 删除 存储过程
DROP PROCEDURE IF EXISTS indexName;
4 参考文献
[数据库]MYSQL之存储过程的更多相关文章
- 数据库MySQL之存储过程
存储过程的定义 存储过程是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象.其在思想上与面向对象编程中函数的定义与调用一致,存储过程只是SQL语言维度上的封装与运用. 存储过程的优缺点 优 ...
- 第二百八十三节,MySQL数据库-MySQL存储过程
MySQL数据库-MySQL存储过程 MySQL存储过程,也就是有点像MySQL函数,但是他与MySQL函数是有区别的,后面会讲到函数,所以注意区分 注意:函数与存储过程的区别 存储过程是:CREAT ...
- 数据库MySQL之 视图、触发器、存储过程、函数、事务、数据库锁、数据库备份、事件
数据库MySQL之 视图.触发器.存储过程.函数.事务.数据库锁.数据库备份.事件 浏览目录 视图 触发器 存储过程 函数 事务 数据库锁 数据库备份 事件 一.视图 1.视图概念 视图是一个虚拟表, ...
- python数据库MySQL之视图,触发器,事务,存储过程,函数
一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...
- MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称
MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称 INFORMATION_SCHEMA.TABLES INFORMATION_SCHEMA. ...
- MYSQL中存储过程的创建,调用及语法
MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库 ...
- MYSQL分页存储过程及事务处理
最近给客户做的一小系统是SQLSERVER的数据库,因为特殊原因要切换到MYSQL上去,切换数据库确实让人头疼的,SQLSERVER和MYSQL的存储过程还是有很大差别的,下面是我做切换时转换的MYS ...
- mysql的存储过程
mysql5中开始引入存储过程,存储过程是一组为了完成特定功能的sql语句集,经编译后存储在数据库中. 存储过程的特点(优点): 1:减小网络通信量.调用一个行数不多的存储过程与直接高用SQL语名的网 ...
- mysql查看存储过程
查询数据库中的存储过程 方法一: select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE' 方法 ...
- mysql之存储过程
一.存储过程 迄今为止,使用的大多数 SQL语句都是针对一个或多个表的单条语句.并非所有操作都这么简单,经常会有一个完整的操作需要多条语句才能完成.例如,考虑以下的情形. 1. ...
随机推荐
- 代码随想录算法训练营第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
977.有序数组的平方 :https://leetcode.cn/problems/squares-of-a-sorted-array/ 心得:周末再写... public class Solutio ...
- python实现录屏功能(亲测好用)
更新时间:2020年03月02日 13:59:52 作者:linnahan https://www.jb51.net/article/181757.htm import time,threading ...
- hdu: 改革春风吹满地(叉乘求面积)
Problem Description" 改革春风吹满地,不会AC没关系;实在不行回老家,还有一亩三分地.谢谢!(乐队奏乐)" 话说部分学生心态极好,每天就知道游戏,这次考试如此简 ...
- FlexPaperViewer跨服务器\跨域访问swf不显示问题
做在线预览办公文档时,遇到了使用flexpaper访问文件服务器swf不显示问题. 假想1: swf文件有问题? 实验1: 直接访问swf文件在文件服务器的地址,浏览器可以正常访问,但是放在flexp ...
- HarmonyOS_Text_Image
Text组件 ohos:属性 id="$+id:text_helloworld" #在程序中控制,需要id="$+id:name",转回MainAbilityS ...
- [Vue warn]: Duplicate keys detected: ''. This may cause an update error. found in
原因: 使用element-ui 导致 使用路由模式之后 index 没写 导致 解决办法: 删掉 或者天添加路由
- linux 部署轻量级堡垒机Next Terminal
对比 类似的开源堡垒机有 Teleport,Jumpserver,Next Terminal等等. Teleport 安全性最好,较轻量,但是对被管理资产不透明,纳管前需要双向认证,在资产设备上需额外 ...
- 子接口vlan终结
问题: 在华为的NE40E设备上,配置三层字接口的ip后,接口的physical状态为up, protocol为down,接口还是不可用. 解决方案: 需要在子接口上配置vlan终结,配置如下: 为什 ...
- selenium 模拟鼠标滚轮,滚动到可见的选项
self.wrap_driver.move_to_element(locator=const_xpath.monitor_select) #鼠标移动到某个区域target = self.driver. ...
- IDEA快键键设置为Eclipse快捷键
一.基础修改,参考这个就可以了 https://jingyan.baidu.com/article/6dad5075a5f7b4e122e36e4b.html 二.其他需要手动配置的快捷键修改(主要是 ...