MySQL 存储过程

本章介绍了什么是存储过程以及为什么要使用存储过程。我们介绍了存储过程的执行和创建的语法以及使用存储过程的一些方法。

目录

存储过程

为什么要使用存储过程

使用存储过程

执行存储过程

创建存储过程

创建代码

说明

执行存储过程

删除存储过程

使用参数

变量

示例一

创建代码

说明

执行存储过程

示例二

创建代码

说明

执行存储过程

建立智能存储过程

场景

创建存储过程

说明

验证存储过程

无税语句

有税语句

说明

检查存储过程

总结


存储过程

目前使用的大多数SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单,经常会有一个完整的操作需要多条语句才能完成。如以下的情况:

1.为了处理订单,需要确保库存中有相应的物品。

2.如果库存有物品,订购后需要减少相应物品库存,并且确保物品不超卖。

3.库存中没有的物品需要订购,这需要与供应商进行某种交互。

4.关于某些物品入库(并且可以立即发货)和某些物品退订,需要通知相应的客户。

执行这个处理需要针对许多表的多条MySQL语句。

此外,需要执行的具体语句及其次序也不是固定的,

它们可能会根据哪些物品在库存中情况而变化。

编写代码:

可以单独编写每条语句,并根据结果有条件地执行另外的语句。

如果需要经常这样处理,就可以创建存储过程来进行处理。

存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批文件,虽然它们的不仅限于批处理。

为什么要使用存储过程

使用存储过程有很多优点和理由:

1.通过把处理封装在容易使用的单元中,简化复杂的操作。

2.由于不需反复建立一系列处理步骤,这保证了数据的完整性,如果所有开发人员和应用程序都使用同一(包括测试)存储过程,则所使用的代码都是相同的。可以防止错误,保证了数据的一致性。

3.简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。通过存储过程限制对基础数据的访问减少了数据讹误的机会,提高了安全性。

4.提高性能。因为使用存储过程比使用单独的SQL语句要快。

5.存在一些只能用在单个请求中的MySQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码

总结:使用存储过程有3个主要的好处,即简单、安全、高性能。

注意:存储过程的编写比基本SQL语句复杂,编写存储过程需要更高的技能,更丰富的经验。

创建存储过程需要足够的安全访问权限。

使用存储过程

使用存储过程需要知道如何执行(运行)它们。存储过程的执行远比其定义更经常遇到,因此,我们将从执行存储过程开始介绍。然后再介绍创建和使用存储过程。

执行存储过程

MySOL称存储过程的执行为调用,因此MySQL执行存储过程的语句为CALL。

CALL接受存储过程的名字以及需要传递给它的任意参数。

示例如下:

sql 复制代码
CALL offerspareprice(@pricelow,@pricehigh,@priceavg);

说明:

执行名为offerspareprice的存储过程,它计算并返回报价产品的最低、最高和平均价格。

存储过程可以显示结果,也可以不显示结果。

创建存储过程

创建一个返回产品平均价格的存储过程示例以作演示。

创建代码

如下:

sql 复制代码
CREATE PROCEDURE offerspareprice()
BEGIN
	SELECT
		Avg(price) AS priceavg
	FROM
		product_offer_spare;
END;
说明

这个存储过程名为offerspareprice, 用CREATE PROCEDURE offerspareprice()语句定义。如果存储过程接受参数,它们将在()中列举出来。此存储过程没有参数,但仍需后跟的()。BEGIN和END语句用来限定存储过程的过程体。过程体本身仅是一个简单的SELECT语句。

在MySQL处理这段代码时,它创建一个新的存储过程offerspareprice。没有返回数据,因为这段代码并未调用存储过程,这里只是创建它。

执行存储过程
sql 复制代码
CALL offerspareprice();

执行结果:

说明:

执行刚创建的存储过程并显示返回的结果。存储过程实际上是一种函数,所以存储过程名后需要有()符号(无参数则为空括号)。

删除存储过程

存储过程在创建之后,被保存在服务器上以供使用,直至被删除。

删除命令从服务器中删除存储过程。删除命令如下:

sql 复制代码
DROP PROCEDURE offerspareprice;

说明:删除刚创建的存储过程offerspareprice。

请注意没有使用后面的(),只给出存储过程名。

使用参数

offerspareprice只是一个简单的存储过程,它简单地显示SELECT语句的结果。

一般存储过程并不显示结果,而是把结果返回你指定的变量。

变量

变量(variable)内存中一个特定的位置,用来临时存储数据。

示例一

以下是offerspareprice的修改版本(需要先删除之前创建存储过程,否则不能创建):

创建代码

如下:

sql 复制代码
CREATE PROCEDURE offerspareprice (
	OUT p1 DECIMAL (8, 2),
	OUT ph DECIMAL (8, 2),
	OUT pa DECIMAL (8, 2)
)
BEGIN
	SELECT Min(price) INTO p1 FROM product_offer_spare;
  SELECT Max(price) INTO ph FROM product_offer_spare;
  SELECT Avg(price) INTO pa FROM product_offer_spare;
END;
说明

此存储过程接受3个参数:pl存储产品最低价格,ph存储产品最高价格,pa存储产品平均价格。每个参数必须具有指定的类型,这里使用十进制值。关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。

MySQL支持IN(传递给存储过程)、0UT(从存储过程传出)和INOUT(对存储过程传入和传出)类型的参数。存储过程的代码位于BEGIN和END语句内。它们是一系列SELECT语句,用来检索值,然后保存到相应的变量(通过指定INTO关键字)。

执行存储过程

调用该存储过程,传入三个参数,执行如下:

sql 复制代码
CALL offerspareprice (@pricelow,@pricehigh,@priceavg);

此存储过程要求3个参数是存储过程将保存结果的3个变量的名字。

在调用时,这条语句并不显示任何数据。它返回可以通过SELECT检索的变量。

检索该变量,如下所示:

sql 复制代码
SELECT @pricehigh, @pricelow, @priceavg;

执行结果:

示例二

这次使用IN和OUT参数。ordertotal接受订单号并返回该订单的合计。

创建代码
sql 复制代码
CREATE PROCEDURE ordertotal (
	IN onumber CHAR(20),
	OUT ototal DECIMAL (8, 2)
)
BEGIN
	SELECT
		Sum(price * num)
	FROM
		product_order_spare
	WHERE
		orderNum = onumber INTO ototal;

END;
说明

onumber定义为IN,需要订单号被传入存储过程,ototal定义为OUT,因为要从存储过程返回合计。SELECT语句使用这两个参数,WHERE子句使用onumber选择数据,INTO使用ototal存储计算出来的合计。

执行存储过程

调用新存储过程,可使用以下语句:

sql 复制代码
CALL ordertotal('20210224140918225910', @tota);

获取订单合计:

sql 复制代码
SELECT @total;

@total已由ordertotal的CALL语句填写,SELECT显示它包含的值。

建立智能存储过程

迄今为止使用的所有存储过程基本上都是封装MySQL简单的SELECT语句。虽然它们全都是有效的存储过程例子,但它们所能完成的工作你直接用这些被封装的语句就能完成。只有在存储过程内包含业务规则和智能处理时,它们的威力才能显示出来。

场景

获取订单合计,但需要对订单合计增加营业税,不过只针对某些客户。那么步骤如下:

1.获取合计

2.把营业税有条件的添加到合计

3.返回合计(带或不带税)

创建存储过程

代码如下:

sql 复制代码
-- 名称: ordertotal
-- 参数:onumber=order number
-- 			 taxable = 0 if not taxable, 1 if taxable
--       ototal = order total variable
CREATE PROCEDURE ordertotal (
	IN onumber CHAR (20),
	IN taxable BOOLEAN,
	OUT ototal DECIMAL (8, 2)
) COMMENT '获取订单总额,可选择加税'
BEGIN
	-- 定义白变量 total
	DECLARE total DECIMAL (8, 2);

-- 定义变量 taxrate
	DECLARE taxrate INT DEFAULT 6;

	-- 获取订单总和
	SELECT
		Sum(price * num)
	FROM
		product_rorder_spare
	WHERE
		order_num = onumber INTO total;

	-- 是否有税
	IF taxable THEN 
		-- 是,则总和增加税
		SELECT total + (tota1 / 100 * taxrate) INTO total;

	END IF;

	-- 最后保存到返回变量中
	SELECT
		total INTO ototal;
END;
说明

这个存储过程有很大的改动。首先增加了注释(前面放置-- )。添加了另外一个参数taxable,它是一个布尔值(如果要增加税则为真,否则为假)。在存储过程体中,用DECLARE语句定义了两个局部变量。DECLARE要求指定变量名和数据类型,它也支持可选的默认值(taxrate的默认被设置为6%)。SELECT语句已经改变,因此其结果存储到tota1(局部变量)而不是ototal。IF语句检查taxable是否为真,如果为真则用另一SELECT语句增加税到局部变量total。

最后用另一SELECT语句将total保存到ototal。

验证存储过程

这显然是一个更高级,功能更强的存储过程。为试验它,请用以下两条语句:

无税语句
sql 复制代码
CALL ordertotal ('20210224140918225910', 0, @ototal);

select @ototal;

运行结果:

有税语句
sql 复制代码
CALL ordertotal ('20210224140918225910', 1, @ototal);

select @ototal;

运行结果:

说明

通过给中间的参数指定0或1,可以有条件的将税加到订单合计上。

检查存储过程

为显示用来创建一个存储过程的CREATE语句,使用SHOWCREATEPROCEDURE语句:

sql 复制代码
SHOW CREATE PROCEDURE ordertotal;

执行结果:

为了获得包括何时、由谁创建等详细信息的存储过程列表,

使用SHOW PROCEDURE STATUS。

执行结果:

上述命令列出所有存储过程列表,限制结果输出可使用:

sql 复制代码
SHOW PROCEDURE STATUS LIKE 'ordertotal';

总结

本章介绍了什么是存储过程以及为什么要使用存储过程。我们介绍了存储过程的执行和创建的语法以及使用存储过程的一些方法。

相关推荐
云和数据.ChenGuang32 分钟前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
woshilys1 小时前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi1 小时前
SQL注入的那些面试题总结
数据库·sql
建投数据2 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi3 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀3 小时前
Redis梳理
数据库·redis·缓存
独行soc3 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天4 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺4 小时前
分布式系统架构:服务容错
数据库·架构
独行soc5 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘