阅读MySQL文档第20章:存储程序和函数

本文把阅读到的重点摘抄下来。

一、一个子程序要么是一个程序要么是一个函数。使用CALL语句来调用程序,程序只能用输出变量传回值。就像别其它函数调用一样,函数可以被从语句外调用(即通过引用函数名),函数能返回标量值。存储子程序也可以调用其它存储子程序。

二、个存储子程序或函数与特定的数据库相联系:

  当一个子程序被调用时,一个隐含的USE db_name 被执行(当子程序终止时停止执行)。

  你可以使用数据库名限定子程序名。这可以用来引用一个不在当前数据库中而是在其他数据库中的子程序。比如,要引用一个与test数据库关联的存储程序p或函数f,你可以说CALL test.p()或test.f()。

  数据库移除的时候,与它关联的所有存储子程序也都被移除。 

三、

  创建存储程序:

    CREATE PROCEDURE sp_name ([proc_parameter[,...]])
        [characteristic ...] routine_body 
创建函数:
    CREATE FUNCTION sp_name ([func_parameter[,...]])
        RETURNS type
        [characteristic ...] routine_body

  由括号包围的参数列必须总是存在。如果没有参数,也该使用一个空参数列()。每个参数默认都是一个IN参数。要指定为其它参数,可在参数名之前使用关键词 OUT或INOUT。指定参数为IN, OUT, 或INOUT 只对PROCEDURE是合法的。RETURNS子句只能对FUNCTION做指定,对函数而言这是强制的。它用来指定函数的返回类型,而且函数体必须包含一个RETURN value语句。

四、MySQL允许子程序包含DDL语句,如CREATE和DROP。也允许存储程序(但不是存储函数)包含SQL 交互语句,如COMMIT。存储函数不可以包含那些做明确的和绝对的提交或者做回滚的语。

五、移除存储程序和函数

  DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name

  这个语句被用来移除一个存储程序或函数。即,从服务器移除一个制定的子程序。在MySQL 5.1中,你必须有ALTER ROUTINE权限才可用此子程序。这个权限被自动授予子程序的创建者。

六、SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION

七、存储程序的调用

  CALL sp_name([parameter[,...]])

  CALL语句可以用声明为OUT或的INOUT参数的参数给它的调用者传回值。

八、BEGIN ... END复合语句

  [begin_label:] BEGIN

    [statement_list]

  END [end_label]

  存储子程序可以使用BEGIN ... END复合语句来包含多个语句。statement_list 代表一个或多个语句的列表。statement_list之内每个语句都必须用分号(;)来结尾。 

  复合语句可以被标记。除非begin_label存在,否则end_label不能被给出,并且如果二者都存在,他们必须是同样的。

九、DECLARE语句

  DECLARE仅被用在BEGIN ... END复合语句里,并且必须在复合语句的开头,在任何其它语句之前。 光标必须在声明处理程序之前被声明,并且变量和条件必须在声明光标或处理程序之前被声明。

十、存储程序中的变量

  1.DECLARE局部变量

   DECLARE var_name[,...] type [DEFAULT value]

   这个语句被用来声明局部变量。要给变量提供一个默认值,请包含一个DEFAULT子句。值可以被指定为一个表达式,不需要为一个常数。如果没有DEFAULT子句,初始值为NULL。局部变量的作用范围在它被声明的BEGIN ... END块内。它可以被用在嵌套的块中,除了那些用相同名字声明变量的块。 

   2.SELECT ... INTO语句

    SELECT col_name[,...] INTO var_name[,...] table_expr

    这个SELECT语法把选定的列直接存储到变量。因此,只有单一的行可以被取回。注意: SQL变量名不能和列名一样。

十一、光标

  ①、声明光标

  DECLARE cursor_name CURSOR FOR select_statement

  这个语句声明一个光标。也可以在子程序中定义多个光标,但是一个块中的每一个光标必须有唯一的名字。

  SELECT语句不能有INTO子句。

  ②、光标OPEN语句
    OPEN cursor_name
    这个语句打开先前声明的光标。

  ③、光标FETCH语句
    FETCH cursor_name INTO var_name [, var_name] ...
    这个语句用指定的打开光标读取下一行(如果有下一行的话),并且前进光标指针。

  ④、光标CLOSE语句
    CLOSE cursor_name
    这个语句关闭先前打开的光标。 
    如果未被明确地关闭,光标在它被声明的复合语句的末尾被关闭。

  注意:光标必须在声明处理程序之前被声明,并且变量和条件必须在声明光标或处理程序之前被声明。

CREATE PROCEDURE curdemo()
BEGIN

DECLARE done INT DEFAULT 0;
DECLARE a CHAR(16);
DECLARE b,c INT;


DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;


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

OPEN cur1;
OPEN cur2;

REPEAT
  FETCH cur1 INTO a, b;
  FETCH cur2 INTO c;
  IF NOT done THEN
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END IF;
UNTIL done END REPEAT;

CLOSE cur1;
CLOSE cur2;

END

十二、流程控制语句

  ①、IF语句

IF search_condition THEN

  statement_list
[ELSEIF search_condition THEN

  statement_list] ...
[ELSE

  statement_list]
END IF

②、CASE语句

第一种:

CASE case_value
  WHEN when_value THEN

    statement_list
  [WHEN when_value THEN

    statement_list] ...
  [ELSE

    statement_list]
END CASE

第二种:

CASE
  WHEN search_condition THEN

    statement_list
  [WHEN search_condition THEN

    statement_list] ...
  [ELSE

    statement_list]
END CASE

  ③、LOOP语句
    [begin_label:] LOOP
      statement_list
    END LOOP [end_label]
  LOOP允许某特定语句或语句群的重复执行,实现一个简单的循环构造。在循环内的语句一直重复直循环被退出,退出通常伴随着一个LEAVE 语句。
  LOOP语句可以被标注。除非begin_label存在,否则end_label不能被给出,并且如果两者都出现,它们必须是同样的。

  ④、LEAVE语句
    LEAVE label
  这个语句被用来退出任何被标注的流程控制构造。它和BEGIN ... END或循环一起被使用。

  ⑤、ITERATE label
    ITERATE只可以出现在LOOP, REPEAT, 和WHILE语句内。ITERATE意思为:“再次循环。”

  例如:

CREATE PROCEDURE doiterate(p1 INT)
BEGIN
  label1: LOOP
    SET p1 = p1 + 1;
    IF p1 < 10 THEN

      ITERATE label1;

    END IF;
    LEAVE label1;
  END LOOP label1;
  SET @x = p1;
END

⑥、REPEAT语句
[begin_label:] REPEAT
  statement_list
UNTIL search_condition
END REPEAT [end_label]


REPEAT语句内的语句或语句群被重复,直至search_condition 为真。

REPEAT 语句可以被标注。 除非begin_label也存在,end_label才能被用,如果两者都存在,它们必须是一样的。

例如:

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)
-> BEGIN
-> SET @x = 0;
-> REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
-> END
-> //
Query OK, 0 rows affected (0.00 sec)

mysql> CALL dorepeat(1000)//
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x//
+------+
| @x |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)

   ⑦、WHILE语句

[begin_label:] WHILE search_condition DO
  statement_list
END WHILE [end_label]


WHILE语句内的语句或语句群被重复,直至search_condition 为真。

WHILE语句可以被标注。 除非begin_label也存在,end_label才能被用,如果两者都存在,它们必须是一样的。

例如:

CREATE PROCEDURE dowhile()
BEGIN
  DECLARE v1 INT DEFAULT 5;

  WHILE v1 > 0 DO
  ...
  SET v1 = v1 - 1;
END WHILE;
END

原文地址:https://www.cnblogs.com/GooPolaris/p/7920303.html