23.1 存储过程

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

23.2 为什么要使用存储过程

使用存储过程有3个主要的好处,即简单、安全、高性能。显然,它们都很重要。不过,在将SQL代码转换为存储过程前,也必须知道它的一些缺陷。

  • 一般来说,存储过程的编写比基本SQL语句复杂,编写存储过程需要更高的技能,更丰富的经验。
  • 你可能没有创建存储过程的安全访问权限。许多数据库管理员限制存储过程的创建权限,允许用户使用存储过程,但不允许他们创建存储过程。

23.3 使用存储过程

23.3.1 执行存储过程

MySQL称存储过程的执行为调用,因此MySQL执行存储过程的语句为CALL。 CALL接受存储过程的名字以及需要传递给它的任意参数。请看以下例子:

  • 分析:其中,执行名为productpricing的存储过程,它计算并返回产品的最低、最高和平均价格。

23.3.2 创建存储过程

一个返回产品平均价格的存储过程。以下是其代码:

CREATE PROCEDURE productpricing()
BEGIN SELECT Avg(prod_price) AS priceaverage FROM products;
END;
  • 分析:我们稍后介绍第一条和最后一条语句。此存储过程名为productpricing,用CREATE PROCEDURE productpricing()语句定义。如果存储过程接受参数,它们将在()中列举出来。此存储过程没有参数,但后跟的()仍然需要。 BEGIN和END语句用来限定存储过程体,过程体本身仅是一个简单的SELECT语句。

注意:这里会报错,因为默认的MySQL语句分隔符为;
解决办法是临时更改命令行实用程序的语句分隔符,如下所示:

最后,为恢复为原来的语句分隔符,可使用DELIMITER ;

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

mysql> CALL productpricing();
+--------------+
| priceaverage |
+--------------+
|    16.133571 |
+--------------+
  • 分析:CALL productpricing();执行刚创建的存储过程并显示返回的结果。因为存储过程实际上是一种函数,所以存储过程名后需要有()符号(即使不传递参数也需要)。

23.3.3 删除存储过程

为删除刚创建的存储过程,可使用以下语句:

DROP PROCEDURE   productpricing;
  • 分析:这条语句删除刚创建的存储过程。请注意没有使用后面的(),只给出存储过程名。

仅当存在时删除 如果指定的过程不存在,则DROP PROCEDURE将产生一个错误。当过程存在想删除它时(如果过程不存在也不产生错误)可使用DROP PROCEDURE IF EXISTS。

23.3.4 使用参数

productpricing只是一个简单的存储过程,它简单地显示SELECT语句的结果。一般,存储过程并不显示结果,而是把结果返回给你指定的变量。

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

以下是productpricing的修改版本(如果不先删除此存储过程,则不能再次创建它):

CREATE PROCEDURE     productpricing(out pl DECIMAL(8, 2),out ph DECIMAL(8, 2),out pa DECIMAL(8, 2)
)
BEGINSELECT Min(prod_price)INTO plFROM products;SELECT Max(prod_price)INTO phFROM products;SELECT Avg(prod_price)INTO paFROM products;
END;
  • 分析:此存储过程接受3个参数: pl存储产品最低价格, ph存储产品最高价格, pa存储产品平均价格。每个参数必须具有指定的类型,这里使用十进制值。关键字OUT指出相应的参数用来从存储过程传出一个值(返回给调用者)。 MySQL支持IN(传递给存储过程)、 OUT(从存储过程传出,如这里所用)和INOUT(对存储过程传入和传出)类型的参数。存储过程的代码位于BEGIN和END语句内,如前所见,它们是一系列SELECT语句,用来检索值,然后保存到相应的变量(通过指定INTO关键字)

为调用此修改过的存储过程,必须指定3个变量名,如下所示:

CALL productpricing(@pricelow, @pricehigh, @priceaverage);
  • 分析:由于此存储过程要求3个参数,因此必须正好传递3个参数,不多也不少。所以,这条CALL语句给出3个参数。它们是存储过程将保存结果的3个变量的名字。

变量名 所有MySQL变量都必须以@开始。

为了显示检索出的产品平均价格,可如下进行:

SELECT  @priceaverage;


为了获得3个值,可使用以下语句:

SELECT @pricehigh, @pricelow, @priceaverage;


下面是另外一个例子,这次使用IN和OUT参数。 ordertotal接受订单号并返回该订单的合计:

CREATE PROCEDURE ordertotal(IN onumber INT,OUT ototal DECIMAL(8,2)
)
BEGINSELECT Sum(item_price*quantity)FROM orderitemsWHERE order_num = onumberINTO ototal;
END;
  • 分析:onumber定义为IN,因为订单号被传入存储过程。 ototal定义为OUT,因为要从存储过程返回合计。 SELECT语句使用这两个参数, WHERE子句使用onumber选择正确的行, INTO使用ototal存储计算出来的合计。

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

CALL ordertotal(20005, @total);
  • 分析:必须给ordertotal传递两个参数;第一个参数为订单号,第二个参数为包含计算出来的合计的变量名。

为了显示此合计,可如下进行:

SELECT @total;

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

为了得到另一个订单的合计显示,需要再次调用存储过程,然后重新显示变量:

CALL ordertotal(20009, @total);
SELECT @total;

23.3.5 建立智能存储过程

只有在存储过程内包含业务规则和智能处理时,它们的威力才真正显现出来。
考虑这个场景。你需要获得与以前一样的订单合计,但需要对合计增加营业税,不过只针对某些顾客(或许是你所在州中那些顾客)。那么,你需要做下面几件事情:

  • 获得合计(与以前一样);
  • 把营业税有条件地添加到合计;
  • 返回合计(带或不带税)。

存储过程的完整工作如下:

-- Name: ordertotal
-- Parameters: onumber = order number
--             taxable = 0 if not taxable, 1 if taxable
--             ototal = order total variableCREATE PROCEDURE ordertotal(IN onumber INT,IN taxable BOOLEAN,OUT ototal DECIMAL(8,2)
) COMMENT 'Obtain order total, optionally adding tax'
BEGIN-- Declare variable for totalDECLARE total DECIMAL(8,2);-- Declare tax percentageDECLARE taxrate INT DEFAULT 6;-- Get the order total SELECT Sum(item_price*quantity)FROM orderitemsWHERE order_num = onumberINTO total;-- Is this taxable?IF taxable THEN-- Yes, so add taxrate to the total SELECT total+(total/100*taxrate) INTO total;END IF;-- And finally, save to out variableSELECT total INTO ototal;
END;
  • 分析:此存储过程有很大的变动。首先,增加了注释(前面放置–)。在存储过程复杂性增加时,这样做特别重要。添加了另外一个参数taxable,它是一个布尔值(如果要增加税则为真,否则为假)。在存储过程体中,DECLARE语句定义了两个局部变量。 DECLARE要求指定变量名和数据类型,它也支持可选的默认值(这个例子中的taxrate的默认被设置为6%)。 SELECT语句已经改变,因此其结果存储到total(局部变量)而不是ototal。 IF语句检查taxable是否为真,如果为真,则用另一SELECT语句增加营业税到局部变量total。最后,用另一SELECT语句将total(它增加或许不增加营业税)保存到ototal

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

CALL ordertotal(20005, 0, @total);
SELECT @total;

CALL ordertotal(20005, 1, @total);
SELECT @total;

  • 分析:BOOLEAN值指定为1表示真,指定为0表示假(实际上,非零值
    都考虑为真,只有0被视为假)。通过给中间的参数指定0或1,可以有条件地将营业税加到订单合计上。

23.3.6 检查存储过程

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

SHOW CREATE PROCEDURE ordertotal;

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

限制过程状态结果 SHOW PROCEDURE STATUS列出所有存储过程。为限制其输出,可使用LIKE指定一个过滤模式,例如:SHOW PROCEDURE STATUS LIKE ‘ordertotal’;

MySQL必知必会二十三:使用存储过程相关推荐

  1. 【MySQL必知必会(十三)】【创建高级联结】

    上一篇:[MySQL必知必会(十二)][联结表] +++++++++++++开始线++++++++++++++++ 文章目录 一. 使用表别名 二. 使用不同类型的联结 2.1 自联结 2.2 自然联 ...

  2. MYSQL必知必会学习笔记(二)

    MYSQL必知必会四-五章--检索.排序 书中部分代码展示: ##第四第五章 SELECT prod_name FROM products; /*从products表中检索一个叫prod_name的列 ...

  3. 根据SQL必知必会学习SQL(MYSQL)

    很久都没有整理SQL语句了,遇到让写SQL语句的题也很迷茫,所以就重拾一下知识,本文章根据SQL必知必会进行梳理 文章目录 一.检索所有列 1.select 1.1检索单个列 1.2 检索多个列 1. ...

  4. MySQL必知必会笔记(一)基础知识和基本操作

    第一章  了解MySQL     数据库       保存有组织的数据的容器.(通常是一个文件或一组文件) 人们经常使用数据库这个术语代替他们使用的软件.这是不正确的,确切的说,数据库软件应称为DBM ...

  5. MySQL必知必会pdf网盘下载+每章总结

    书籍下载 链接:https://pan.baidu.com/s/18g0XgavniXQzp6RlOxnwnQ 密码:j8pm 目录 书籍下载 MySQL必知必会 第二章 连接mysql 第三章 连接 ...

  6. 《SQL必知必会》第十三课 创建高级联结表 使用不同类型的联结 使用带聚集函数的联结 使用联结时应注意的问题

    第十三课 创建高级联结表 #使用表别名的原因 #不同的联结类型以及每类联结所使用的语法 #如何与联结一起使用聚集函数 #使用联结时的注意问题 一.使用表别名 [1]前面(第七课)介绍使用别名引用被检索 ...

  7. 读书笔记系列1——MySQL必知必会

    读书笔记系列1--MySQL必知必会 文章目录 读书笔记系列1--MySQL必知必会 MySQL官方文档:https://dev.mysql.com/doc/ 第一章 数据库基础 *2021.11.2 ...

  8. 30 分钟读完《MySQL 必知必会》

    第一章 了解 SQL 介绍几个数据库的概念 数据库(database) 通过DBMS创建和操纵的保存有组织的数据的容器(通常是一个文件或一组文件). 数据库软件/数据库管理系统(DBMS)访问数据库, ...

  9. 《MySQL必知必会》学习笔记十(增删改语句使用)------掌握部分

    MySQL必知必会知识预览 第一章--了解SQL 第二章--MySQL简介 第三章--使用MySQL 第四章--检索数据 第五章--排序检索数据 第六章--过滤数据 第七章--数据过滤 第八章--用通 ...

  10. php7.2 开启mcy扩展,phper必知必会(二)

    1.说说你对进程,线程以及协程的理解 进程:是系统进行资源分配和调度的基本单位,是基本操作系统结构的基础.进程是程序基本执行的实体.进程与进程之间是独立的,拥有完全独立的地址空间,进程的切换只发生在内 ...

最新文章

  1. Ubuntu 32下Android NDK+NEON的配置过程及简单使用举例
  2. 用U盘破除XP管理员密码
  3. Net设计模式实例之桥接模式( Bridge Pattern)(2)
  4. React入门---事件与数据的双向绑定-9
  5. SpringCloud分布式事务,版本一:未加事务版本
  6. 画图软件怎么做性能测试,软件性能测试能力提升解决方案.pdf
  7. WPF游戏,使用move游戏开发
  8. 相机标定(4) 矫正畸变 undistort()和initUndistortRectifyMap()
  9. 美国政府发布关键海事行业的网络安全规划
  10. matlab liccode,车牌识别的matlab程序--(详细注释,并有使用注意点)
  11. 笔记本电脑怎么清理灰尘_笔记本电脑卡顿,运行慢,似中病毒,看这里 小白教你轻松搞定...
  12. 数据库的内连接和外连接的区别
  13. python复制上一条语句快捷键_pycharm快捷键及一些常用设置
  14. 赛思互动:管理学最重要的八大定理
  15. 前端js正则表达式2
  16. 元宇宙、区块链和潘家园
  17. 电视剧《勇敢的心》观后感
  18. 微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例
  19. JavaScript面向对象实现-坦克大战(附前端全套学习路线)
  20. Centos下使用C++操作Redis——hiredis

热门文章

  1. Exchange Server 2010邮件撤回条件说明
  2. python、pandas、Excel、Powerbi中对日期的处理方法
  3. Java String 真的是不可变的吗
  4. Vue中的视频播放插件( vue-video-player )
  5. 信用评分卡模型开发中双峰分布原因及解决方案
  6. golang:字符类型(byte和rune)
  7. a16z:元宇宙解锁游戏基础设施中的新机遇
  8. oracle 统计同比 环比,oracle求同比,环比函数(LAG与LEAD)的详解
  9. 2020年第六届美亚杯个人资格赛题目复现
  10. c语言嵌套结构体数组,第22节 C语言结构体之结构体嵌套、结构体指针与结构体数组的代码实现...