1 创建存储过程和函数

  存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别是:CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句来调用存储过程,只能用输出变量返回值。函数可以从语句外调用(即通过引用函数名),也能返回标量值。存储过程也可以调用其它存储过程。
  说白了,存储过程和函数就是我们一般编程语言的自定义函数。

1.1 创建存储存储过程

  基本语法:

CREATE PROCEDURE sp_name([proc_parameter])
  [characteristics] routine_body

  (1)CREATE PROCEDURE:创建存储过程的关键字
  (2)sp_name:存储过程的名字
  (3)proc_parameter:指定存储过程的参数列表。
IN表示输入参数;OUT表示输出参数;INOUT表示即可以输入也可以输出;param_name表示参数名;type表示参数类型
  (4)characteristics指定存储过程的特性,可以有如下取值:

  • LANGUAGE SQL:说明routine body部分是由SQL语句组成
  • [NOT] DETERMINISTIC:指明存储过程执行的结果是否正确
  • {CONTAINS SQL|NO SQL|READS SQL DATA|MODIFIES SQL DATA}:指明子程序使用SQL语句的限制
  • SQL SECURITY {DEFINER|INVOKER}:指明谁有权限来执行
  • COMMENT ‘string’:注释信息
      示例:
mysql> DELIMITER //
mysql> CREATE PROCEDURE Pro()
    -> BEGIN
    -> SELECT * FROM fruits;
    -> END //
Query OK, 0 rows affected

mysql> CREATE PROCEDURE CountProc(OUT param1 INT)
    -> BEGIN
    -> SELECT COUNT(*) INTO param1 FROM fruits;
    -> END //
Query OK, 0 rows affected

mysql> DELIMITER ;

  “DELIMITER //”表示将结束符设置为//

1.2 变量的使用

  变量可以在子程序中声明并使用,作用范围是咋BEGIN…END程序中。
  (1)定义变量

DECLARE var_name[,varname]...data_type[DEFAULT value];

  例如:

DECLARE myparam INT DEFAULT 100;

  (2)为变量赋值

SET var_name=expr[,var_name = expr]...;

  示例:

DECLARE var1, var2, var3 INT;
SET var1 = 10, var2 = 20;
SET var3 = var1 + var2;

1.3 定义条件和处理程序

  特定条件需要特定处理,这些条件可以联系到错误,以及子程序中的一般流程控制。
  定义条件是事先定义程序执行过程中遇到的问题,处理程序定义了在遇到这些问题时应当采取的处理方式,并且保证存储过程或函数咋iyudao警告或错误时能继续执行。这样可以增强存储程序处理问题的能力,避免程序异常停止运行。
  (1)定义条件

DECLARE condition_name CONDITION FOR[condition_type]
[condition_type]:
  SQLSTATE [VALUE] sqlstate_value|mysql_error_code

  (2)定义处理程序

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement
handler_type:
  CONTINUE|EXIT|UNDO


condition_value:
  SQLSTATE[VALUE]sqlstate_value
|condition_name
|SQLWARNING
|NOT FOUND
|SQLEXCEPTION
|mysql_error_code

①handler_type:错误处理方式,取值:CONTINUE、EXIT和UNDO。
- CONTINUE表示遇到错误不处理,继续执行
- EXIT表示遇到错误马上退出
- UNDO表示遇到错误后撤回之前的操作。
②condition_value:表示错误类型

  (3)示例:

mysql> CREATE TABLE t(s1 int,primary key(s1));
Query OK, 0 rows affected

mysql> DELIMITER //
mysql> CREATE PROCEDURE handlerdemo()
    -> BEGIN
    -> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2=1;
    -> SET @x=1;
    -> INSERT INTO t VALUES(1);
    -> SET @x=2;
    -> INSERT INTO t VALUES(1);
    -> SET @x=3;
    -> END;
    -> //
Query OK, 0 rows affected

mysql> DELIMITER ;
mysql> CALL handlerdemo();
Query OK, 0 rows affected

mysql> SELECT @x;
+----+
| @x |
+----+
|  3 |
+----+
1 row in set

  “@var_name”表示用户变量,使用SET语句赋值,用户变量与连接有关。一个客户端定义的变量不能被其他客户端使用。客户端退出时,变量自动释放。

1.4 光标的使用

  查询语句可能返回多条记录,如果数据量非常大,需要在存储过程和函数中使用光标来逐条读取查询结果集中的记录。应用程序可以根据需要滚动或浏览其中的数据。
  光标必须在声明处理程序之前被声明,并且变量和条件还必须在声明光标或处理程序之前被声明。
  (1)声明光标

DECLARE cursor_name CURSOR FOR selec_statement

例如:

DECLARE cursor_fruits CURSOR FOR SELECT f_name,f_price FROM fruits;

  (2)打开光标

OPEN cursor_name{光标名称}

例如:

OPEN cursor_fruits;

  (3)使用光标

FETCH cursor_name INTO var_name[,var_name]...{参数名称}

例如:

FETCH cursor_fruits INTO fruits_name,fruits_price;

  (4)关闭光标

CLOSE cursor_name{光标名称}

例如:

CLOSE cursor_fruits;

  MySQL中光标只能在存储过程和函数中使用。

1.5 流程控制的使用

  流程控制语句用来根据条件控制语句的执行。
(1)IF语句

IF val IS NULL
  THEN SELECT 'val is NULL';
  ELSE SELECT 'val is not NULL';
END IF;

(2)CASE语句

CASE val
  WHEN 1 THEN SELECT 'val is 1';
  WHEN 2 THEN SELECT 'val is 2';
  ELSE SELECT 'val is not 1 or 2';
END CASE;

(3)LOOP语句

DECLARE id INT DEFAULT 0;
add_loop: LOOP  
SET id = id + 1;
  IF id >= 10 THEN  LEAVE add_loop;
  END IF;
END LOOP add_ loop;

(4)LEAVE语句

add_num:LOOP      
 SET @count=@count+1;
  IF @count=50 THEN LEAVE add_num;
  END IF;
END LOOP add_num;

(5)ITERATE语句

CREATE PROCEDURE doiterate()
BEGIN
DECLARE p1 INT DEFAULT 0;
my_loop: LOOP
  SET p1= p1 + 1;
  IF p1 < 10 THEN ITERATE my_loop;
  ELSEIF p1 > 20 THEN LEAVE my_loop;
  END IF;
  SELECT 'p1 is between 10 and 20';
END LOOP my_loop;
END

(6)REPEAT语句

DECLARE id INT DEFAULT 0;
REPEAT
SET id = id + 1;
UNTIL  id >= 10
END REPEAT;

(7)WHILE语句

DECLARE i INT DEFAULT 0;
WHILE i < 10 DO
SET i = i + 1;
END WHILE;