mysql 进阶(一)存储过程的使用

存储过程相当于 Java 中的无返回值函数,可以被其它模块反复调用,但是存储过程可以通过输出参数返回多个处理结果,存储过程会在数据库中一直保留,直到被删除。

语法

CREATE
[DEFINER = { user | CURRENT_USER }]
 PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
  Valid SQL routine statement
[begin_label:] BEGIN
  [statement_list]
    ……
END [end_label]

说明:
声明语句结束符,可以自定义:DELIMITER $$DELIMITER //
声明存储过程:create procedure 存储过程名(参数)
存储过程开始和结束符号:BEGIN .... END
变量赋值:
SET 变量名 = 表达式值 [,variable_name = expression ...];
例如:SET @p_in=1;
局部变量声明一定要放在存储过程体的开始:

DECLARE variable_name  [,variable_name...] datatype [DEFAULT value];

其中,datatype 为 MySQL 的数据类型,如: int, float, date,varchar(length)
例如:DECLARE l_int int unsigned default 4000000;
存储过程体: 存储过程体包含了在过程调用时必须执行的语句,例如:dml、ddl 语句,if-then-else 和 while-do 语句、声明变量的 declare 语句等,
过程体格式: 以 begin 开始,以 end 结束 (可嵌套)。

BEGIN
  BEGIN
    BEGIN
      statements;
    END
  END
END

每个嵌套块及其中的每条语句,必须以分号结束,表示过程体结束的 begin-end 块 (又叫做复合语句 compound statement),则不需要分号。
为语句块贴标签:

[begin_label:] BEGIN
  [statement_list]
END [end_label]

例如:

label1: BEGIN
  label2: BEGIN
    label3: BEGIN
      statements;
    END label3 ;
  END label2;
END label1

标签有两个作用:
1、增强代码的可读性。
2、在某些语句 (例如:leave 和 iterate 语句),需要用到标签。
MySQL 存储过程共有三种参数类型,IN,OUT,INOUT, 形式如:
IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)。
OUT 输出参数:表示过程向调用者传出值 (可以返回多个值)(传出值只能是变量)。
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)。

用户变量

用户变量名一般以 @开头
滥用用户变量会导致程序难以理解及管理
用户变量赋值:
SELECT 'Hello World' into @x;
用户变量查询:
SELECT @x;
在存储过程中使用用户变量:

CREATE  PROCEDURE  GreetWorld(  )  
SELECT  CONCAT(@greeting,' World');
SET @greeting='Hello';

执行存储过程:

CALL  GreetWorld(  );

在存储过程间传递全局范围的用户变量:
创建存储过程:

CREATE  PROCEDURE  p1()  
SET @last_procedure='p1';
CREATE  PROCEDURE  p2() 
 SELECT  CONCAT('Last procedure was ',@last_procedure);

调用存储过程:

CALL  p1(  );
CALL  p2(  );

存储过程调用

用 call 和你过程名以及一个括号,括号里面根据需要,加入参数,参数包括输入参数、输出参数、输入输出参数。
例如:

CALL  GreetWorld(  );

存储过程查询

查询存储过程列表:

select name from mysql.proc where db='数据库名';

或者

select routine_name from information_schema.routines where routine_schema='数据库名';

或者

show procedure status where db='数据库名';

查询指定存储过程详细信息:

SHOW CREATE PROCEDURE 数据库.存储过程名;

存储过程修改

语法:

ALTER PROCEDURE sp_name [characteristic……]

Sp_name,表示存储过程的名称
characteristic,表示要修改存储过程的哪个部分
Characteristic 的取值如下
CONTAINS SQL,表示子程序包含 SQL 语句,但是,不包含读或写数据的语句
NO SQL,表示子程序中,不包含 SQL 语句
READS SQL DATA,表示子程序中,包含读数据的语句
MODIFIES DATA,表示子程序中,包含写数据的语句
SQL SECURITY {DEFINER | INVOKER},指明谁有权限来执行
DEFINER,表示只有定义者,自己才能够执行
INVOKER,表示调用者可以执行
COMMENT 'string',表示注释信息

目前,MySQL 还不提供对已存在的存储过程的代码修改。
如果,一定要修改存储过程的 diam,必须,先将存储过程删除之后,在重新编写代码,或者创建一个新的存储过程。

存储过程删除

DROP PROCEDURE  [ IF EXISTS ]  存储过程名;

IF EXISTS 子句是 MySQL 的一个扩展。如果程序不存在,它可以防止发生错误,产生一个用 SHOW WARNINGS 查看的警告。

示例

例 1:

创建
DROP procedure IF EXISTS in_param;
DELIMITER $$
create procedure in_param(in p_in int)
  begin
    insert into log values(p_in);
  end $$
DELIMITER ;
调用
call in_param(100);

OUT 模式 : 参数输出模式

创建
DELIMITER $$
CREATE PROCEDURE user_main_pro2(OUT v_count INT)
BEGIN
  SELECT COUNT(*) INTO v_count FROM t_user_main;
END $$
DELIMITER
调用
call user_main_pro2(@v_count);

mysql 存储过程示例

下一篇 mysql 进阶(二)函数的使用