MySQL存储过程和游标

一、存储过程

什么是存储过程,为什么要使用存储过程以及如何使用存储过程,并且介绍创建和使用存储过程的基本语法。

什么是存储过程:

存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样

实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用

他就行了。

存储过程的好处:

  1. 由于数据库执行动作时,是先编译后执行的。然而存储过程是一个编译过的代码块,所以执行效率要比

    T-SQL语句高。

  2. 一个存储过程在程序在网络中交互时可以替代大堆的T-SQL语句,所以也能降低网络的通信量,提高通信速率。

  3. 通过存储过程能够使没有权限的用户在控制之下间接地存取数据库,从而确保数据的安全

存储过程的基本语法:

--------------------创建存储过程------------------------------------
CREATE PROCEDURE procedure_name( IN|OUT variable data_type)
BENGIN
    sql_statement;
    ......
END;
-- MySQL支持IN(传递给存储过程)、OUT(从存储过程传出)
-- variable 变量
-- data_type 参数的数据类型
-- sql_statement 中 INTO parameter 的把值保存到相应的变量中(通过INTO关键字) 
--------------------执行存储过程------------------------------------
CALL procedure_name(@parameters);
--------------------删除存储过程------------------------------------
DROP PROCEDURE procedure_name;
-- 如果指定的过程不存在,则DROP PROCEDURE将会产生一个错误。
-- 使用DROP PROCEDURE IF EXISTS
--------------------检查存储过程------------------------------------
SHOW CREATE PROCEDURE procedure_name;
-------------------------------------------------------------------
-- 为了获得包括何时、有谁创建等详细信息的存储过程列表,使用
SHOW PROCEDURE STATUS LIKE ' ';
-- LIKE 指定过滤模式
备注:mysql命令行实用程序使用;作为语句分隔符,所以用命令行写存储过程自身内的;字符,会使存储过程的SQL出现句法错误。解决办法是临时更改命令行的语句分隔符,如下所示:
-- 更改MySQL分隔符   除\符号外,任何字符都可以用作语句分隔符。
DELIMITER //    
DELIMITER ;

存储过程示例:

场景:

你需要获得与以前一样的订单合计,但需要对合计增加营业税,不过只针对某些顾客。那么,你需要做下面几件事情:

  • 获得合计;

  • 把营业税有条件地添加到合计;

  • 返回合计(带或不带税)。

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

-- Name: ordertotal
-- Parameters: onumber = order number
            -- taxable = 0 if not taxable, 1 if taxable
            -- ototal  = order total variable
DROP PROCEDURE IF EXISTS ordertotal;
CREATE PROCEDURE ordertotal(
    IN onumber INT,
    IN taxable BOOLEAN,
    OUT ototal DECIMAL(8,2)
) COMMENT 'Obtion ordertotal, optionally adding tax'
BENGIN
    -- 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
        -- Yes, so add taxrate to the total
        SELECT total+(total/100*taxrate) INTO total;
    END IF;
    -- And finally, save to out variable
    SELECT total INTO ototal;
END;

执行存储过程:

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

1580031909831

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

1580031874363

二、游标

什么是游标以及如何使用游标。

什么是游标:

MySQL检索操作返回一组结果集。MySQL使用简单的select语句没有办法得到第一行、下一行或前10行,也不能成批地处理它们。

  • 游标可以从结果集中做到返回单个结果

  • 使用游标可以轻易的取出在检索出来的行中前进或后退一行或多行的结果

  • 游标可以遍历返回的多行结果。

补充:MySQL中游标只适用于存储过程以及函数。

使用游标步骤:

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

  2. 一旦声明后,必须打开游标以供使用。这个过程用前面定义的select语句把数据实际检索出来。

  3. 对于有数据的游标,根据需要取出(检索)各行。

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

在声明游标后,可根据需要频繁地打开和关闭游标。在游标打开后,可根据需要频繁地执行取操作。

语法:

  1. 定义游标

    DECLARE <游标名> CURSOR 
    FOR
    select语句;
  2. 打开游标

    OPEN <游标名>;
  3. 使用游标

    使用游标需要用关键字FETCH来取出数据,然后取出的数据需要有存放的地方,我们需要用declare声明变量存放列的数据其语法格式为:

    DECLARE variable1 数据类型(与列值的数据类型相同);
    FETCH [NEXT|PRIOR|FIRST|LAST] FROM <游标名> INTO [variable1,variable2,…]
  4. 关闭游标

    CLOSE <游标名>;

游标示例:

DROP PROCEDURE IF EXISTS processorders;
CREATE PROCEDURE processorders()
BEGIN
    -- Declare local variables
    DECLARE done BOOLEAN DEFAULT 0;
    DECLARE o INT;
    DECLARE t DECIMAL(8,2);
    -- Declare the 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 result
    CREATE TABLE IF NOT EXISTS ordertotals(
        id INT PRIMARY KEY AUTO_INCREMENT,
        order_num INT NOT NULL,
        total DECIMAL(8,2)
    );
    -- Open the cursor
    OPEN ordertotals;
    -- Loop through all rows
    REPEAT
        -- Get order number
        FETCH ordertotals INTO o;
        -- Get the total for this order
        CALL ordertotal(o, 1, t);
        -- Insert order and total into ordertotals
        INSERT INTO ordertotals(order_num, total) VALUES(o, t);
    -- End of loop
    UNTIL done END REPEAT;
    -- Close the cursor
    CLOSE ordertotals;
END;
CALL ordertotal();
SELECT * FROM ordertotals;

1580038166242

三、MySQL学习脚本:

链接:https://pan.baidu.com/s/1U4HI-AC49ZUb730odAUkjw 提取码:lti7

posted @ 2020-01-26 20:01  NoviceLearning  阅读(945)  评论(0编辑  收藏  举报