Mysql存储过程与游标

创建存储过程
CREATE PROCEDURE productpricing()
BEGIN
   ...

END

如果在命令行客户端执行,需要先更改语句分割符,DELIMITER // (除\外,任何字符都可以用做语句分割符), 存储过程以END//结束,完成后再设置回来DELIMITER ;


调用存储过程
CALL productpricing();
查看存储过程创建语句
SHOW CREATE PROCEDURE productpricing;
查看数据库的所有存储过程
SHOW PROCEDURE STATUS;
删除存储过程

DROP PROCEDURE productpricing IF EXISTS;//存在时删除


使用参数,IN:输入  OUT:输出    INOUT:输入输出,对于参数的类型,表中使用的都可以,记录集不允许,不能通过一个参数返回多个行和列。所有Mysql局部变量需要使用@开头。如下:

DROP PROCEDURE productpricing IF EXISTS;//存在时删除
CREATE PROCEDURE productpricing(
   OUT pl DECIMAL(8,2), OUT ph DECIMAL(8,2), OUT pa DECIMAL(8,2)
)
BEGIN
   SELECT MIN(prod_price) INTO pl FROM products;
   SELECT MAX(prod_price) INTO ph FROM products;
   SELECT AVG(prod_price) INTO pa FROM products; 
END;
调用CALL productpricing(@pricelow, @pricehigh, @priceaverage);
查看结果:
mysql> SELECT @pricelow, @pricehigh, @priceaverage;
+-----------+------------+---------------+
| @pricelow | @pricehigh | @priceaverage |
+-----------+------------+---------------+
|      2.50 |      55.00 |         16.13 |
+-----------+------------+---------------+

再如以下例子:

ordertotal1:对某些合计增加营业稅,只有部分,需要1获得合计2把营业税有条件的添加到合计3返回合计(带或不带稅)
--Name: ordertotal1
--Params: onumber = order number
--        taxable = 0 if not taxable, 1 if taxable
--        ototal = order total variable
CREATE PROCEDURE ordertotal1(
   IN onumber INT,
   IN taxable BOOLEAN,
   OUT ototal DECIMAL(8,2)
) COMMENT 'Obtain order total, optionally add tax'
BEGIN
   DECLARE total DECIMAL(8,2);
   DECLARE taxrate INT DEFAULT 6;
   
   SELECT Sum(item_price*quantity) FROM orderitems WHERE order_num = onumber INTO total;
   
   IF taxable THEN
      SELECT total + (total/100*taxrate) INTO total;
   END IF;
   
   SELECT total INTO ototal;
END;
调用:
mysql> CALL ordertotal1(20005, 0, @total);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT @total;
+--------+
| @total |
+--------+
| 149.87 |
+--------+


mysql> CALL ordertotal1(20005, 1, @total);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> SELECT @total;
+--------+
| @total |
+--------+
| 158.86 |
+--------+
COMMIT值注释,不是必需的,在SHOW PROCEDURE STATUS显示


游标:

       游标是一个存储在MySQL服务器上的数据库查询,不是一条select语句,而是被该语句检索出来的结果集。在存储了游标之后,应用程序可以根据需要滚动或浏览其中的数据。Mysql中只能用于存储过程。

        使用游标的几个步骤:

        1 使用游标前,必须声明(定义)它,这个过程没有检索数据,只是定义要使用的select语句

        2 如果要使用,必须打开游标。打开时将实际数据检索出来

        3 对于填有数据的游标,根据需要检索出各行

        4 在结束游标使用时,必须关闭游标。

        游标只定义一次,但可以多次打开和关闭使用游标。 但如果关闭后没有重新打开则不能使用。如果在存储过程最后没有关闭游标,在到达END时mysql会关闭它。            

使用游标:Mysql只能用于存储过程
声明:DECLARE cname CURSOR FOR SELECT ....
打开游标:OPEN cname
获取数据:FETCH cname INTO c
关闭游标:CLOSE cname

         存储过程中DECLARE语句的声明顺序:局部变量, 游标,句柄,顺序不能错,否则会产生错误消息,以下为一个游标的使用与分析:

--构造一个新表ordertotals,从订单表中选出所有订单号,然后对于每个订单号,
--调用存储过程计算出订单总价,将这些订单号与计算出的总价存入表中
CREATE PROCEDURE processorders()
BEGIN
  --先声明局部变量
  DECLARE done BOOLEAN;   --来表示循环是否完成
  SET done=0;
  DECLARE o INT;
  DECLARE t DECIMAL(8,2);

  --再声明游标表示取出的所有订单号
  DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders;

  --再声明一个句柄进行错误处理,当游标循环到最后没有数据时,
  --设置02000状态码表示没有数据,从而设置done=1,结束循环
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

  --新建一个表用来存储结果
  CREATE TABLE IF NOT EXISTS ordertotals
    (order_num INT, total DECIMAL(8,2)); 

  OPEN ordernumbers;  --打开游标

  REPEAT
    --FETCH获取游标所指数据
    FETCH ordernumbers INTO o;
    
    --调用存储过程计算总价
    CALL ordertotal1(o, 1, t);
    
    --插入新建的表中
    INSERT INTO ordertotals(order_num, total) VALUES(o,t);
  UNTIL done END REPEAT; --结束循环
  CLOSE ordernumbers;  --关闭游标
END;

      注意,在客户端输入时不能有这些注释,而且要改变分隔符。以下为结果:

mysql> CALL processorders;

mysql> SELECT * from ordertotals;
+-----------+---------+
| order_num | total   |
+-----------+---------+
|     20005 |  158.86 |
|     20009 |   40.78 |
|     20006 |   58.30 |
|     20007 | 1060.00 |
|     20008 |  132.50 |
|     20008 |  132.50 |
+-----------+---------+



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值