mysql之游标,存储过程

本文详细介绍了SQL存储过程的创建、执行、检查及删除流程,通过具体示例展示了如何利用存储过程处理复杂的业务逻辑,如计算订单总额并考虑是否加入营业税。此外,还深入解析了游标的使用,包括创建、打开、关闭及数据访问,通过实例演示了如何利用游标遍历订单数据并调用存储过程进行处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、存储过程
存储过程是什么,简单来讲,就像Java中的方法(函数),不过它是SQL世界中的方法。

大部分时候,我们所使用都是单条SQL,用来针对一个或多表连接。但是也有情况,是据判断先对表A执行操作,变动后再结合表B进行操作。即SQL的执行可能需要考虑包含业务规则在内的智能处理。封装操作的好处就不过多说明,无非是简化,复用,降低耦合等,同时,它还具有更高的性能。

考虑这种业务情况,现在你需要获得订单总额,但同时需要增加营业税,且只针对某些顾客,那么你需要:
获得基本的订单总额
将营业税有条件地添加到合计中
返回合计

1.1 基本语句
先看基本的语句,然后再看示例,就豁然开朗了:

 --创建存储过程 

CREATE PROCEDURE <存储过程的名称>(<变量的类型定义>)

BEGIN

  <执行操作>

END;

--执行存储过程

CALL <存储过程的名称>(<@变量名>);

--删除存储过程

DROP PROCEDURE <存储过程的名称>;


1.2 创建
然后,根据刚才我们说到的返回包含营业税的订单总额,创建如下存储过程:

-- Name: ordertotal

-- Parameters: onumber = order number

--             taxable = 0 if not taxable, 1 if taxable

--             ototal  = order total variable

CREATE PROCEDURE ordertotal(

  IN  onumber INT,

  IN  taxable BOOLEAN,

  OUT ototal DECIMAL(8, 2)

) COMMENT 'Obtain order total, optionally adding tax'

BEGIN

  --Declare variable for total

  DECLARE total DECIMAL(8, 2);

  --Declare tax percentage

  DECLARE taxrate INT DEFAULT 6;

  

  --GET the order total

  SELECT Sum(item_price*quantity)

  FROM orderitems

  WHERE order_num = onumber

  INTO total;

  --Is this taxable

  IF taxable THEN

    SELECT total+(total/100*taxrate) INTO total;

  END IF;

  SELECT total INTO ototal;

END;

看起来这么长好像挺唬人,其实很清楚:

 

CREATE PROCEDURE ordertotal(

  IN  onumber INT,

  IN  taxable BOOLEAN,

  OUT ototal DECIMAL(8, 2)

) COMMENT 'Obtain order total, optionally adding tax'

使用CREATE PROCEDURE关键词创建了名为ordertotal的存储过程
该存储过程定义了三个变量,IN表示要求输入的参数,OUT表示输出的结果。INT、BOOLEAN等表示变量的数据类型
COMMENT非必需,如果有,那么在SHOW PROCEDURE STATUS的结果时会显示(简单说,类似于方法的说明)

BEGIN

  ...

END;

BEGIN和END用来界定存储过程操作执行的语句

  --Declare variable for total

  DECLARE total DECIMAL(8, 2);

  --Declare tax percentage

  DECLARE taxrate INT DEFAULT 6;


  --GET the order total

  SELECT Sum(item_price*quantity)

  FROM orderitems

  WHERE order_num = onumber

  INTO total;
DECLARE用来定义存储过程中的局部变量
INTO表示赋值到变量

--Is this taxable

  IF taxable THEN

    SELECT total+(total/100*taxrate) INTO total;

  END IF;

IF <boolean> THEN <do something> END IF 为条件执行语句,记得END IF结尾

假如用Java来写的话,大概是这么个意思:

 

public void ordertotal(int onumber, boolean taxable, double ototal) {

    double total;

    int taxrate = 6;

    

    total = getOrderTotal(onumber);

    if (taxable) {

        total += total / (100 * taxrate);

    }

    ototal = total;

}

1.3 执行
在1.2我们定义了存储过程ordertotal(),则执行方式为:

 

--不含营业税

CALL ordertotal(20005, 0, @total);

SELECT @total

+----------+
|  @total  |
+----------+
|  149.87  |
+----------+

--包含营业税

CALL ordertotal(20005, 1, @total);

SELECT @total

+-----------------+
|      @total     |
+-----------------+
|  158.862200000  |
+-----------------+

定义时我们说过,IN表示定义输入,OUT表示定义输出,所以这里的三个变量中,前两者由调用者传入,而第三个变量,则作为返回结果的变量。
(调用存储过程时,用于临时存储返回数据的变量必须以@开头)

1.4 检查
用来显示“创建某个存储过程的CREATE语句”,使用SHOW CREATE PROCEDURE语句:

 
SHOW CREATE PROCEDURE ordertotal;

1.5 删除

 
DROP PROCEDURE ordertotal;
注意,检查和删除存储过程,都不用加后面的(),只需要给出存储过程的名称即可。


2、游标
在检索出来的行中,前进或者后退一行或多行,就需要用到所谓的“游标”。游标不是某个SELECT语句,但是它是被该语句检索出来的结果集,另外,MySQL游标只能用于存储过程(和函数)。

2.1 创建游标
使用DECLARE和CURSOR关键字:

 

CREATE PROCEDURE processorders()

BEGIN

  DECLARE ordernumbers CURSOR

  FOR

  SELECT order_num FROM orders;

END;

2.2 打开和关闭游标
因为游标局限于存储过程,所以如果存储过程处理完成后,游标就会消失。所以往往在存储过程中要关键字OPEN进行打开。另,游标相关的SELECT查询语句,在定义时是不执行的,在OPEN时才执行查询,存储检索出的数据以供浏览和滚动。在游标使用完成后,使用CLOSE进行关闭:

 

CREATE PROCEDURE processorders()

BEGIN

  DECLARE ordernumbers CURSOR

  FOR

  SELECT order_num FROM orders;

  OPEN ordernumbers;

  CLOSE ordernumbers;

END;

2.3 使用游标数据
打开游标之后,我们就可以使用关键字FETCH访问数据了,FETCH是从第一行开始,获取当前行的数据,每次执行后会移动内部行指针,再次调用FETCH则会检索到下一行(不会重复读取同一行):

 

CREATE PROCEDURE processorders()

BEGIN

  --Declare

  DECLARE o INT;

  DECLARE ordernumbers CURSOR

  FOR

  SELECT order_num FROM orders;

  --Open

  OPEN ordernumbers;

  --Get

  FETCH ordernumbers INTO o;  

  --Close

  CLOSE ordernumbers;
END;

看一个复杂些的例子:

 

CREATE PROCEDURE processorders()

BEGIN

  --Declare local variables

  DELCARE done BOOLEAN DEFAULT 0;

  DECLARE o    INT;

  DECLARE t    DECIMAL(8,2);

  --Declare cursor

  DECLARE ordernumbers CURSOR

  FOR

  SELECT order_num FROM orders;

 

  --Declare continue handler

  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

  --Create a table to store the results

  CREATE TABLE IF NOT EXISTS ordertotals(order_num INT, total DECIMAL(8,2));  

  --Open the cursor

  OPEN ordernumbers;

  --Loop through all rows

  REPEAT

    FETCH ordernumbers INTO o;

    CALL ordertotal(o, 1, t);

    INSERT INTO ordertotals(order_num, total) VALUES(o, t);

  UNTIL done END REPEAT;

  --Close the cursor

  CLOSE ordernumbers;

END;
以上存储过程,游标不断读取订单号,并以此为参调用另一个存储过程,将最终的值填入到表ordertotals中
CONTINUE HANDLER 是在条件出现时执行的代码,SQLSTATE '02000' 表没有找到更多的行(MySQL错误代码)


 

SELECT * FROM ordertotals;

+---------+---------+
|  20005  |  158.86 |
|  20006  |   58.30 |
|  20007  | 1060.00 |
|  20008  |  132.50 |
|  20009  |   40.78 |
+---------+---------+

 

原地址:https://www.cnblogs.com/deng-cc/p/7986087.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值