MySQL存储过程整理

MySQL存储过程

2018-08-15  23:00:06

1、存储过程介绍


(1) 定义:存储过程是存储在数据库目录中的一段声明性SQL语句。 触发器,其他存储过程以及java,python,php等应用程序可以调用存储过程。

递归存储过程:自身的存储过程。大多数数据库管理系统支持递归存储过程。 但是,MySQL不支持它。

(2)优点:

1️⃣通常存储过程有助于提高应用程序的性能。当创建,存储过程被编译之后,就存储在数据库中。 但是,MySQL实现的存储过程略有不同。 MySQL存储过程按需编译。 在编译存储过程之后,MySQL将其放入缓存中。 MySQL为每个连接维护自己的存储过程高速缓存。 如果应用程序在单个连接中多次使用存储过程,则使用编译版本,否则存储过程的工作方式类似于查询。

2️⃣存储过程有助于减少应用程序和数据库服务器之间的流量,因为应用程序不必发送多个冗长的SQL语句,而只能发送存储过程的名称和参数。

3️⃣存储的程序对任何应用程序都是可重用的和透明的。 存储过程将数据库接口暴露给所有应用程序,以便开发人员不必开发存储过程中已支持的功能。

4️⃣存储的程序是安全的。 数据库管理员可以向访问数据库中存储过程的应用程序授予适当的权限,而不向基础数据库表提供任何权限。

(3)缺点:

1️⃣如果使用大量存储过程,那么使用这些存储过程的每个连接的内存使用量将会大大增加。 此外,如果您在存储过程中过度使用大量逻辑操作,则CPU使用率也会增加,因为数据库服务器的设计不当于逻辑运算。

2️⃣存储过程的构造使得开发具有复杂业务逻辑的存储过程变得更加困难。

3️⃣很难调试存储过程。

4️⃣开发和维护存储过程并不容易。

2、存储过程入门


Navicat命令行下创建第一个存储过程HelloProcedure(),也可以直接使用navicat中的图形化界面直接创建,也可以用MySQL Workbench图形化工具创建。

mysql> delimiter //  ---将分隔符;改为//
mysql> drop procedure if exists HelloProcedure;   ---不要括弧-> //
Query OK, 0 rows affected

mysql> create procedure HelloProcedure()
    -> begin
    -> select * from products;
    -> end//
Query OK, 0 rows affected

mysql> delimiter ;  ---将分隔符改回来
mysql> call HelloProcedure();  ---调用存储过程,要带括弧!

 第一个命令是DELIMITER //,它与存储过程语法无关。 DELIMITER语句将标准分隔符 - 分号(;)更改为://。 在这种情况下,分隔符从分号(;)更改为双斜杠//

为什么我们必须更改分隔符? 因为我们想将存储过程作为整体传递给服务器,而不是让mysql工具一次解释每个语句。 在END关键字之后,使用分隔符//来指示存储过程的结束。 最后一个命令(DELIMITER;)将分隔符更改回分号(;)。

3、存储过程变量


声明变量:
declare x int default 0;
declare x, y int default 0;  ---可以同时声明多个变量

分配变量值:
declare total int default 0;
set total = 10;  ---分配给total的值为10

declare total int default 0;
select count(*) into total
from products;   ---将sql语句的查询结果分配给total

变量范围(作用域):
在存储过程中声明一个变量,那么当达到存储过程的END语句时,它将超出范围,因此在其它代码块中无法访问。
以@符号开头的变量是会话变量。直到会话结束前它可用和可访问。

4、存储过程参数


 参数有三种:

  • IN---是默认模式。在存储过程中定义IN参数时,调用程序必须将参数传递给存储过程。 另外,IN参数的值被保护。这意味着即使在存储过程中更改了IN参数的值,在存储过程结束后仍保留其原始值。
mysql> drop procedure if exists GetOfficeByCountry;
Query OK, 0 rows affected

mysql> delimiter //
mysql> create procedure GetOfficeByCountry(in countryName varchar(255))
    -> begin
    -> select *
    -> from offices
    -> where country = countryName;
    -> end //
Query OK, 0 rows affected

mysql> delimiter ;
mysql> call GetOfficeByCountry('USA');
+------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+
| officeCode | city          | phone           | addressLine1         | addressLine2 | state | country | postalCode | territory |
+------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+
| 1          | San Francisco | +1 650 219 4782 | 100 Market Street    | Suite 300    | CA    | USA     | 94080      | NA        |
| 2          | Boston        | +1 215 837 0825 | 1550 Court Place     | Suite 102    | MA    | USA     | 02107      | NA        |
| 3          | NYC           | +1 212 555 3000 | 523 East 53rd Street | apt. 5A      | NY    | USA     | 10022      | NA        |
+------------+---------------+-----------------+----------------------+--------------+-------+---------+------------+-----------+
3 rows in set

Query OK, 0 rows affected

mysql> drop procedure if exists CountOrderByStatus;
Query OK, 0 rows affected
  • OUT---可以在存储过程中更改OUT参数的值,并将其更改后新值传递回调用程序。请注意,存储过程在启动时无法访问OUT参数的初始值。

mysql> drop procedure if exists CountOrderByStatus;
Query OK, 0 rows affected

mysql> delimiter //
mysql> create procedure CountOrderByStatus(in orderStatus varchar(255),out total int)
    -> begin
    -> select count(orderNumber)
    -> into total
    -> from orders
    -> where status = orderStatus;
    -> end //
Query OK, 0 rows affected

mysql> delimiter ;
mysql> call CountOrderByStatus('Shipped',@total);
Query OK, 1 row affected

mysql> select @total;
+--------+
| @total |
+--------+
|    303 |
+--------+
1 row in set
  • INOUT---INOUT参数是INOUT参数的组合。这意味着调用程序可以传递参数,并且存储过程可以修改INOUT参数并将新值传递回调用程序
mysql> drop procedure if exists set_counter;
Query OK, 0 rows affected

mysql> delimiter //
mysql> create procedure set_counter(inout count int(4),in inc int(4))
    -> begin
    -> set count = count + inc;
    -> end //
Query OK, 0 rows affected

mysql> delimiter ;
mysql> set @counter = 1;
Query OK, 0 rows affected

mysql> call set_counter(@counter,1); ---2
Query OK, 0 rows affected

mysql> call set_counter(@counter,1); ---3
Query OK, 0 rows affected

mysql> call set_counter(@counter,5); ---8
Query OK, 0 rows affected

mysql> select @counter;
+----------+
| @counter |
+----------+
|        8 |
+----------+
1 row in set

5、返回多个值的存储过程


DELIMITER $$

CREATE PROCEDURE get_order_by_cust(
 IN cust_no INT,
 OUT shipped INT,
 OUT canceled INT,
 OUT resolved INT,
 OUT disputed INT)
BEGIN
 -- shipped
 SELECT
            count(*) INTO shipped
        FROM
            orders
        WHERE
            customerNumber = cust_no
                AND status = 'Shipped';

 -- canceled
 SELECT
            count(*) INTO canceled
        FROM
            orders
        WHERE
            customerNumber = cust_no
                AND status = 'Canceled';

 -- resolved
 SELECT
            count(*) INTO resolved
        FROM
            orders
        WHERE
            customerNumber = cust_no
                AND status = 'Resolved';

 -- disputed
 SELECT
            count(*) INTO disputed
        FROM
            orders
        WHERE
            customerNumber = cust_no
                AND status = 'Disputed';

END

6、IF语句(if  then  else end if;和 if then elseif then else end if;)


mysql> delimiter //
mysql> create procedure GetCustomerLevel(in p_cusNum int(11),out p_cusLevel varchar(10))
    -> begin
    -> declare creditlim double;
    -> 
    -> select creditlimit into creditlim
    -> from customers
    -> where customerNumber = p_cusNum;
    -> 
    -> if creditlim > 50000 then 
    ->   set p_cusLevel = 'PLATINUM';
    -> elseif (creditlim <= 50000 and creditlim >= 10000) then
    ->   set p_cusLevel = 'GOLD';
    -> elseif creditlim < 10000 then
    ->   set p_cusLevel = 'SILVER';
    -> end if;
    -> end //
Query OK, 0 rows affected

mysql> call GetCustomerLevel(103,@p_cusLevel);
    -> //
Query OK, 1 row affected

mysql> delimiter ;
mysql> select @p_cusLevel;
+-------------+
| @p_cusLevel |
+-------------+
| GOLD        |
+-------------+
1 row in set

7、CASE语句


 case  when  ...    then  ...

     when  ...    then  ...

     else  ...

 end case;

注意:在select查询语句中,可以直接在end 后面加上字段别名!

 case  when  ...    then  ...

     when  ...    then  ...

     else  ...

 end 字段别名;  (或者end as 字段别名

mysql> delimiter //
mysql> create procedure GetCusShipping(in p_cusNum int(11),out p_shipping varchar(50))
    -> begin
    -> declare cusCountry varchar(50);
    -> 
    -> select country into cusCountry
    -> from customers
    -> where customerNumber = p_cusNum;
    -> 
    -> case cusCountry
    -> when 'USA' then set p_shipping = '2';
    -> when 'Canada' then set p_shipping = '3';
    -> else
    -> set p_shipping = '5';
    -> end case;
    -> end //
Query OK, 0 rows affected

mysql> delimiter ;
mysql> set @p_cusNum = 112;
Query OK, 0 rows affected

mysql> select country into @country
    -> from customers
    -> where customerNumber = @p_cusNum;
Query OK, 1 row affected

mysql> call GetCusShipping(@p_cusNum,@shipping);
Query OK, 1 row affected

mysql> select @p_cusNum as Customer,
    -> @country as Country,
    -> @shipping as Shipping;
+----------+---------+----------+
| Customer | Country | Shipping |
+----------+---------+----------+
|      112 | USA     |     2    |
+----------+---------+----------+
1 row in set
 

注意:可以直接在navicatl里面创建存储过程,创建的时候选择参数类型的时候记得加上具体的范围保存的时候只用写上存储过程的名称,不用带括号

8、IF和CASE语句使用技巧


 IF语句和CASE语句的时候,看个人喜好。

IF判断嵌套少的话,使用IF更方便,但是IF判断嵌套太多的话,建议使用CASE更加简单易读!

9、循环


 while...do...end while;

begin
 
    declare x int;
 
    declare str varchar(255);

 
    set x = 1;
 
    set str = '';

 
    while x <= 5 do
 
    set str = concat(str,x,',');
 
    set x = x + 1;
 
    end while;

 
    select str;
 
end

mysql> call test_mysql_while_loop();
+------------+
| str |
+------------+
| 1,2,3,4,5, |
+------------+
1 row in set


Query OK, 0 rows affected

 

repeat...until...end repeat;

begin
 
    declare x int;
 
    declare str varchar(255);

 
    set x = 1;
 
    set str = '';

 
    repeat
 
    set str = concat(str,x,',');
 
    set x = x + 1;
 
    until x > 5
 
    end repeat;

 
    select str;
 
end


mysql> call test_mysql_repeat_loop();
+------------+
| str |
+------------+
| 1,2,3,4,5, |
+------------+
1 row in set


Query OK, 0 rows affected

 

loop...leave...iterate...;  leave相当于break,iterate相当于continue.

begin
 
    declare x int;
 
    declare str varchar(255);

 
    set x = 1;
 
    set str = '';

 
    loop_label: loop
 
    if x > 10 then
 
        leave loop_label;
 
    end if;

 
    set x = x + 1;

 
    if(x mod 2) then
 
        iterate loop_label;
 
    else
 
        set str = concat(str,x,',');
 
    end if;

 
    end loop;

 
    select str;
 
end

mysql> call test_mysql_loop();
+-------------+
| str |
+-------------+
| 2,4,6,8,10, |
+-------------+
1 row in set


Query OK, 0 rows affected

 

10、游标


要处理存储过程中的结果集,请使用游标。游标允许您迭代查询返回的一组行,并相应地处理每行。

MySQL游标为只读(无法通过光标更新基础表中的数据),不可滚动(只能按照select语句的顺序获取行)和敏感(敏感指向实际数据,不敏感指向数据副本,敏感比不敏感执行的快)。

可以在存储过程存储函数触发器中使用MySQL游标。

 

BEGIN

 DECLARE v_finished INTEGER DEFAULT 0;
 DECLARE v_email varchar(100) DEFAULT "";

 -- 1、declare cursor for employee email
 DEClARE email_cursor CURSOR FOR 
 SELECT email FROM employees;

 -- 2、declare NOT FOUND handler
 DECLARE CONTINUE HANDLER 
 FOR NOT FOUND SET v_finished = 1;

 -- 3、open 
 OPEN email_cursor;

 get_email: LOOP

 -- 4、fetch
 FETCH email_cursor INTO v_email;

 -- 5、not found
 IF v_finished = 1 THEN 
    LEAVE get_email;
 END IF;

 -- 6、build email list
 SET email_list = CONCAT(v_email,";",email_list);

 END LOOP get_email;

 -- 7、close
 CLOSE email_cursor;

END

mysql> set @email_list = "";
Query OK, 0 rows affected

mysql> call build_email_list(@email_list);
Query OK, 0 rows affected

mysql> select @email_list;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @email_list                                                                                                                                                                                                                                                                                                                                                                                                                                         |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mgerard@gmail.com;ykato@gmail.com;mnishi@gmail.com;tking@gmail.com;pmarsh@yiibai.com;afixter@yiibai.com;bjones@gmail.com;lbott@yiibai.com;pcastillo@gmail.com;ghernande@gmail.com;lbondur@yiibai.com;gvanauf@yiibai.com;ftseng@yiibai.com;spatterson@yiibai.com;jfirrelli@yiibai.com;lthompson@yiibai.com;ljennings@yiibai.com;abow@gmail.com;gbondur@gmail.com;wpatterson@yiibai.com;jfirrelli@yiibai.com;mpatterso@yiibai.com;dmurphy@yiibai.com; |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

11、在数据库中列出存储过程


mysql> show procedure status;---列出有权访问的数据库的所有存储过程
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db       | Name                     | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| mydb2    | GetAllByUsername         | PROCEDURE | root@localhost | 2018-08-07 17:06:32 | 2018-08-07 17:06:32 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| mydb2    | GetAllUser               | PROCEDURE | root@localhost | 2018-08-06 16:14:26 | 2018-08-06 16:14:26 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| mydb2    | GetAllUser2              | PROCEDURE | root@localhost | 2018-08-06 16:21:29 | 2018-08-06 16:21:29 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | AddOrderItem             | PROCEDURE | root@localhost | 2018-08-08 11:50:42 | 2018-08-08 11:50:42 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | build_email_list         | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | CountOrderByStatus       | PROCEDURE | root@localhost | 2018-08-07 19:23:47 | 2018-08-07 19:23:47 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | Divide                   | PROCEDURE | root@localhost | 2018-08-08 14:30:07 | 2018-08-08 14:30:07 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCusShipping           | PROCEDURE | root@localhost | 2018-08-16 09:20:51 | 2018-08-16 09:20:51 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | GetCustomerLevel         | PROCEDURE | root@localhost | 2018-08-07 22:41:38 | 2018-08-07 22:41:38 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCustomerLevel2        | PROCEDURE | root@localhost | 2018-08-08 14:57:09 | 2018-08-08 14:57:09 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCustomerShipping      | PROCEDURE | root@localhost | 2018-08-07 22:57:06 | 2018-08-07 22:57:06 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetOfficeByCountry       | PROCEDURE | root@localhost | 2018-08-07 19:02:53 | 2018-08-07 19:02:53 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | get_order_by_cust        | PROCEDURE | root@localhost | 2018-08-07 19:58:27 | 2018-08-07 19:58:27 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | HelloProcedure           | PROCEDURE | root@localhost | 2018-08-15 19:20:34 | 2018-08-15 19:20:34 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | insert_article_tags      | PROCEDURE | root@localhost | 2018-08-08 10:57:53 | 2018-08-08 10:57:53 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | insert_article_tags_exit | PROCEDURE | root@localhost | 2018-08-08 11:12:57 | 2018-08-08 11:12:57 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | set_counter              | PROCEDURE | root@localhost | 2018-08-07 19:31:14 | 2018-08-07 19:31:14 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | test_mysql_loop          | PROCEDURE | root@localhost | 2018-08-16 09:39:36 | 2018-08-16 09:39:36 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | test_mysql_repeat_loop   | PROCEDURE | root@localhost | 2018-08-16 09:38:14 | 2018-08-16 09:38:14 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | test_mysql_while_loop    | PROCEDURE | root@localhost | 2018-08-16 09:33:52 | 2018-08-16 09:33:52 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
20 rows in set

mysql> show procedure status where db = 'yiibaidb';---列出指定数据库的所有存储过程
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db       | Name                     | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| yiibaidb | AddOrderItem             | PROCEDURE | root@localhost | 2018-08-08 11:50:42 | 2018-08-08 11:50:42 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | build_email_list         | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | CountOrderByStatus       | PROCEDURE | root@localhost | 2018-08-07 19:23:47 | 2018-08-07 19:23:47 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | Divide                   | PROCEDURE | root@localhost | 2018-08-08 14:30:07 | 2018-08-08 14:30:07 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCusShipping           | PROCEDURE | root@localhost | 2018-08-16 09:20:51 | 2018-08-16 09:20:51 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | GetCustomerLevel         | PROCEDURE | root@localhost | 2018-08-07 22:41:38 | 2018-08-07 22:41:38 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCustomerLevel2        | PROCEDURE | root@localhost | 2018-08-08 14:57:09 | 2018-08-08 14:57:09 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetCustomerShipping      | PROCEDURE | root@localhost | 2018-08-07 22:57:06 | 2018-08-07 22:57:06 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | GetOfficeByCountry       | PROCEDURE | root@localhost | 2018-08-07 19:02:53 | 2018-08-07 19:02:53 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | get_order_by_cust        | PROCEDURE | root@localhost | 2018-08-07 19:58:27 | 2018-08-07 19:58:27 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | HelloProcedure           | PROCEDURE | root@localhost | 2018-08-15 19:20:34 | 2018-08-15 19:20:34 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | insert_article_tags      | PROCEDURE | root@localhost | 2018-08-08 10:57:53 | 2018-08-08 10:57:53 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | insert_article_tags_exit | PROCEDURE | root@localhost | 2018-08-08 11:12:57 | 2018-08-08 11:12:57 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | set_counter              | PROCEDURE | root@localhost | 2018-08-07 19:31:14 | 2018-08-07 19:31:14 | DEFINER       |         | utf8                 | utf8_general_ci      | utf8_general_ci    |
| yiibaidb | test_mysql_loop          | PROCEDURE | root@localhost | 2018-08-16 09:39:36 | 2018-08-16 09:39:36 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | test_mysql_repeat_loop   | PROCEDURE | root@localhost | 2018-08-16 09:38:14 | 2018-08-16 09:38:14 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
| yiibaidb | test_mysql_while_loop    | PROCEDURE | root@localhost | 2018-08-16 09:33:52 | 2018-08-16 09:33:52 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
+----------+--------------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
17 rows in set

mysql> show procedure status where name like '%product%';
Empty set

mysql> show procedure status where name like '%email%';---列出指定名称的存储过程
+----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db       | Name             | Type      | Definer        | Modified            | Created             | Security_type | Comment | character_set_client | collation_connection | Database Collation |
+----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| yiibaidb | build_email_list | PROCEDURE | root@localhost | 2018-08-16 10:11:45 | 2018-08-16 10:11:45 | DEFINER       |         | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
+----------+------------------+-----------+----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
1 row in set

mysql> show create procedure build_email_list;---列出存储过程的源代码
+------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| Procedure        | sql_mode                                                       | Create Procedure                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | character_set_client | collation_connection | Database Collation |
+------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
| build_email_list | STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | CREATE DEFINER=`root`@`localhost` PROCEDURE `build_email_list`(INOUT email_list varchar(4000))
BEGIN

 DECLARE v_finished INTEGER DEFAULT 0;
 DECLARE v_email varchar(100) DEFAULT "";

 -- 1、declare cursor for employee email
 DEClARE email_cursor CURSOR FOR
 SELECT email FROM employees;

 -- 2、declare NOT FOUND handler
 DECLARE CONTINUE HANDLER
 FOR NOT FOUND SET v_finished = 1;

 -- 3、open
 OPEN email_cursor;

 get_email: LOOP

 -- 4、fetch
 FETCH email_cursor INTO v_email;

 -- 5、not found
 IF v_finished = 1 THEN
    LEAVE get_email;
 END IF;

 -- 6、build email list
 SET email_list = CONCAT(v_email,";",email_list);

 END LOOP get_email;

 -- 7、close
 CLOSE email_cursor;

END | utf8mb4              | utf8mb4_general_ci   | utf8_general_ci    |
+------------------+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+--------------------+
1 row in set

12、存储过程中的MySQL错误处理


BEGIN
    #Routine body goes here...
    DECLARE EXIT HANDLER FOR 1062 SELECT 'Duplicate keys error encountered';
    DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT 'SQLException encountered';
    DECLARE EXIT HANDLER FOR SQLSTATE '23000' SELECT 'SQLSTATE 23000';

    INSERT INTO article_tags(article_id,tag_id)
    VALUES(article_id,tag_id);

    SELECT COUNT(*) FROM article_tags;

END

插入重复的值得时候会报错!处理程序优先级:每一个mysql错误都对应一个错误代码(例如1062),所以处理错误优先级是错误越具体,优先级越高

mysql> call insert_article_tags_3(1,3);
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
1 row in set


Query OK, 0 rows affected

 
使用命名错误条件:
也就是给错误代码1051取个好理解的名字,这样发生对应的错误的时候,知道具体是什么错误。
DECLARE table_not_found CONDITION for 1051; DECLARE EXIT HANDLER FOR table_not_found SELECT 'Please create table abc first'; SELECT * FROM abc;

13、使用MySQL SIGNAL/RESIGNAL语句引发错误条件


DELIMITER $$

CREATE PROCEDURE AddOrderItem(in orderNo int,
 in productCode varchar(45),
 in qty int,in price double, in lineNo int )

BEGIN
 DECLARE C INT;

 SELECT COUNT(orderNumber) INTO C
 FROM orders 
 WHERE orderNumber = orderNo;

 -- check if orderNumber exists
 IF(C != 1) THEN 
 SIGNAL SQLSTATE '45000'
 SET MESSAGE_TEXT = 'Order No not found in orders table';
 END IF;
 -- more code below
 -- ...
END $$
DELIMITER ;
DELIMITER $$

CREATE PROCEDURE Divide(IN numerator INT, IN denominator INT, OUT result double)
BEGIN
 DECLARE division_by_zero CONDITION FOR SQLSTATE '22012';

 DECLARE CONTINUE HANDLER FOR division_by_zero 
 RESIGNAL SET MESSAGE_TEXT = 'Division by zero / Denominator cannot be zero';
 -- 
 IF denominator = 0 THEN
 SIGNAL division_by_zero;
 ELSE
 SET result := numerator / denominator;
 END IF;
END $$
DELIMITER ; 

14、存储函数


 存储的函数是返回单个值的特殊类型的存储程序。您使用存储的函数来封装在SQL语句或存储的程序中可重用的常用公式或业务规则。

可以在sql语句中和存储过程中调用存储函数,这样有助于代码的可读性和可维护性。

BEGIN
    DECLARE lvl varchar(10);

    IF p_creditLimit > 50000 THEN
 SET lvl = 'PLATINUM';
    ELSEIF (p_creditLimit <= 50000 AND p_creditLimit >= 10000) THEN
        SET lvl = 'GOLD';
    ELSEIF p_creditLimit < 10000 THEN
        SET lvl = 'SILVER';
    END IF;

 RETURN (lvl);
END

mysql> select customerName,CustomerLevel(creditLimit)
    -> from customers
    -> order by customerName;
+------------------------------------+----------------------------+
| customerName                       | CustomerLevel(creditLimit) |
+------------------------------------+----------------------------+
| Alpha Cognac                       | PLATINUM                   |
| American Souvenirs Inc             | SILVER                     |
| Amica Models & Co.                 | PLATINUM                   |
| ANG Resellers                      | SILVER                     |
| Anna's Decorations, Ltd            | PLATINUM                   |
| Anton Designs, Ltd.                | SILVER                     |
| Asian Shopping Network, Co         | SILVER                     |
| Asian Treasures, Inc.              | SILVER                     |
| Atelier graphique                  | GOLD                       |
| Australian Collectables, Ltd       | PLATINUM                   |
| Australian Collectors, Co.         | PLATINUM                   |
| Australian Gift Network, Co        | PLATINUM                   |
| Auto Associs & Cie.                | PLATINUM                   |
| Auto Canal+ Petit                  | PLATINUM                   |
| Auto-Moto Classics Inc.            | GOLD                       |
| AV Stores, Co.                     | PLATINUM                   |
| Baane Mini Imports                 | PLATINUM                   |
| Bavarian Collectables Imports, Co. | PLATINUM                   |
| BG&E Collectables                  | SILVER                     |
| Blauer See Auto, Co.               | PLATINUM                   |
| Boards & Toys Co.                  | GOLD                       |
| CAF Imports                        | PLATINUM                   |
| Cambridge Collectables Co.         | GOLD                       |
| Canadian Gift Exchange Network     | PLATINUM                   |
| Classic Gift Ideas, Inc            | PLATINUM                   |
| Classic Legends Inc.               | PLATINUM                   |
| Clover Collections, Co.            | PLATINUM                   |
| Collectable Mini Designs Co.       | PLATINUM                   |
| Collectables For Less Inc.         | PLATINUM                   |
| Corporate Gift Ideas Co.           | PLATINUM                   |
| Corrida Auto Replicas, Ltd         | PLATINUM                   |
| Cramer Spezialitten, Ltd           | SILVER                     |
| Cruz & Sons Co.                    | PLATINUM                   |
| Daedalus Designs Imports           | PLATINUM                   |
| Danish Wholesale Imports           | PLATINUM                   |
| Der Hund Imports                   | SILVER                     |
| Diecast Classics Inc.              | PLATINUM                   |
| Diecast Collectables               | PLATINUM                   |
| Double Decker Gift Stores, Ltd     | GOLD                       |
| Down Under Souveniers, Inc         | PLATINUM                   |
| Dragon Souveniers, Ltd.            | PLATINUM                   |
| Enaco Distributors                 | PLATINUM                   |
| Euro+ Shopping Channel             | PLATINUM                   |
| Extreme Desk Decorations, Ltd      | PLATINUM                   |
| Feuer Online Stores, Inc           | SILVER                     |
| Franken Gifts, Co                  | SILVER                     |
| Frau da Collezione                 | GOLD                       |
| FunGiftIdeas.com                   | PLATINUM                   |
| Gift Depot Inc.                    | PLATINUM                   |
| Gift Ideas Corp.                   | GOLD                       |
| Gifts4AllAges.com                  | GOLD                       |
| giftsbymail.co.uk                  | PLATINUM                   |
| GiftsForHim.com                    | PLATINUM                   |
| Handji Gifts& Co                   | PLATINUM                   |
| Havel & Zbyszek Co                 | SILVER                     |
| Heintze Collectables               | PLATINUM                   |
| Herkku Gifts                       | PLATINUM                   |
| Iberia Gift Imports, Corp.         | PLATINUM                   |
| Kelly's Gift Shop                  | PLATINUM                   |
| King Kong Collectables, Co.        | PLATINUM                   |
| Kommission Auto                    | SILVER                     |
| Kremlin Collectables, Co.          | SILVER                     |
| L'ordine Souveniers                | PLATINUM                   |
| La Corne D'abondance, Co.          | PLATINUM                   |
| La Rochelle Gifts                  | PLATINUM                   |
| Land of Toys Inc.                  | PLATINUM                   |
| Lisboa Souveniers, Inc             | SILVER                     |
| Lyon Souveniers                    | PLATINUM                   |
| Marseille Mini Autos               | PLATINUM                   |
| Marta's Replicas Co.               | PLATINUM                   |
| Men 'R' US Retailers, Ltd.         | PLATINUM                   |
| Messner Shopping Network           | SILVER                     |
| Microscale Inc.                    | GOLD                       |
| Mini Auto Werke                    | GOLD                       |
| Mini Caravy                        | PLATINUM                   |
| Mini Classics                      | PLATINUM                   |
| Mini Creations Ltd.                | PLATINUM                   |
| Mini Gifts Distributors Ltd.       | PLATINUM                   |
| Mini Wheels Co.                    | PLATINUM                   |
| Mit Vergngen & Co.                 | SILVER                     |
| Motor Mint Distributors Inc.       | PLATINUM                   |
| Muscle Machine Inc                 | PLATINUM                   |
| Natrlich Autos                     | SILVER                     |
| Norway Gifts By Mail, Co.          | PLATINUM                   |
| Online Diecast Creations Co.       | PLATINUM                   |
| Online Mini Collectables           | PLATINUM                   |
| Osaka Souveniers Co.               | PLATINUM                   |
| Oulu Toy Supplies, Inc.            | PLATINUM                   |
| Petit Auto                         | PLATINUM                   |
| Porto Imports Co.                  | SILVER                     |
| Precious Collectables              | SILVER                     |
| Qubec Home Shopping Network        | GOLD                       |
| Raanan Stores, Inc                 | SILVER                     |
| Reims Collectables                 | PLATINUM                   |
| Rovelli Gifts                      | PLATINUM                   |
| Royal Canadian Collectables, Ltd.  | PLATINUM                   |
| Royale Belge                       | GOLD                       |
| Salzburg Collectables              | PLATINUM                   |
| SAR Distributors, Co               | SILVER                     |
| Saveley & Henriot, Co.             | PLATINUM                   |
| Scandinavian Gift Ideas            | PLATINUM                   |
| Schuyler Imports                   | SILVER                     |
| Signal Collectibles Ltd.           | PLATINUM                   |
| Signal Gift Stores                 | PLATINUM                   |
| Souveniers And Things Co.          | PLATINUM                   |
| Stuttgart Collectable Exchange     | SILVER                     |
| Stylish Desk Decors, Co.           | PLATINUM                   |
| Suominen Souveniers                | PLATINUM                   |
| Super Scale Inc.                   | PLATINUM                   |
| Technics Stores Inc.               | PLATINUM                   |
| Tekni Collectables Inc.            | GOLD                       |
| The Sharp Gifts Warehouse          | PLATINUM                   |
| Tokyo Collectables, Ltd            | PLATINUM                   |
| Toms Spezialitten, Ltd             | PLATINUM                   |
| Toys of Finland, Co.               | PLATINUM                   |
| Toys4GrownUps.com                  | PLATINUM                   |
| UK Collectables, Ltd.              | PLATINUM                   |
| Vida Sport, Ltd                    | PLATINUM                   |
| Vitachrome Inc.                    | PLATINUM                   |
| Volvo Model Replicas, Co           | PLATINUM                   |
| Warburg Exchange                   | SILVER                     |
| West Coast Collectables Co.        | PLATINUM                   |
+------------------------------------+----------------------------+
122 rows in set
原文地址:https://www.cnblogs.com/ahu-lichang/p/9481226.html