初始化数据库表
mysql> create table user(
-> id int primary key auto_increment,
-> name varchar(250),
-> email varchar(100),
-> age tinyint
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into user (name, email, age) values
-> ('ronie', 'ronie@163.com', 20),
-> ('jack', 'jack@163.com', 34),
-> ('jerry', 'jerry@163.com', 22),
-> ('lucy', 'lucy@163.com', 21);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from user;
+----+-------+---------------+------+
| id | name | email | age |
+----+-------+---------------+------+
| 1 | ronie | ronie@163.com | 20 |
| 2 | jack | jack@163.com | 34 |
| 3 | jerry | jerry@163.com | 22 |
| 4 | lucy | lucy@163.com | 21 |
+----+-------+---------------+------+
4 rows in set (0.00 sec)
存储过程和函数
存储程序可以分为存储过程和函数。在MySQL中,创建存储过程和函数使用的语句分别是CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句来调用存储过程,只能用输出变量返回值。函数可以从语句外调用(引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。
创建存储过程和函数
创建存储过程
语法:CREATE PROCEDURE sp_name ([proc_parameter]) [characteristics ...] routine_body
。- proc_parameter为指定存储过程的参数列表,
[ IN | OUT | INOUT ] param_name type
,IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出;param_name表示参数名称;type表示参数的类型,该类型可以是MySQL数据库中的任意类型。 characteristics指定存储过程的特性,取值:
- LANGUAGE SQL:说明routine_body部分是由SQL语句组成的,当前系统支持的语言为SQL。SQL是LANGUAGE特性的唯一值。
- [NOT] DETERMINISTIC:指明存储过程执行的结果是否正确。DETERMINISTIC表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。NOT DETERMINISTIC表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为NOT DETERMINISTIC。
- { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:指明子程序使用SQL语句的限制。CONTAINS SQL表明子程序包含SQL语句,但是不包含读写数据的语句;NO SQL表明子程序不包含SQL语句;READS SQL DATA说明子程序包含读数据的语句;MODIFIES SQL DATA表明子程序包含写数据的语句。默认情况下,系统会指定为CONTAINS SQL。
- SQL SECURITY { DEFINER | INVOKER }:指明谁有权限来执行。DEFINER表示只有定义者才能执行。INVOKER表示拥有权限的调用者可以执行。默认情况下,系统指定为DEFINER。
- COMMENT 'string':注释信息,可以用来描述存储过程或函数。
-- DELIMITER //语句的作用是将MySQL的结束符设置为//,因为MySQL默认的语句结束符号为分号;。 -- 为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER改变存储过程的结束符,并以END //结束存储过程。 -- 存储过程定义完毕之后再使用DELIMITER ;恢复默认结束符。DELIMITER也可以指定其他符号作为结束符。 mysql> DELIMITER // mysql> create procedure avg_age() -> begin -> select avg(age) from user; -> end // Query OK, 0 rows affected (0.02 sec) mysql> DELIMITER ; mysql> call avg_age(); +----------+ | avg(age) | +----------+ | 24.2500 | +----------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER // mysql> create procedure num_of_user(out arg int) -> begin -> select count(*) into arg from user; -> end // Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER ; mysql> call num_of_user(@num); Query OK, 1 row affected (0.00 sec) mysql> select @num; +------+ | @num | +------+ | 4 | +------+ 1 row in set (0.00 sec)
- proc_parameter为指定存储过程的参数列表,
创建存储函数
语法:CREATE FUNCTION func_name ([proc_parameter]) return type [characteristics ...] routine_body
。CREATE FUNCTION为用来创建存储函数的关键字;func_name表示存储函数的名称;func_parameter为存储过程的参数列表,RETURNS type语句表示函数返回数据的类型;characteristic指定存储函数的特性,取值与创建存储过程时相同。如果在存储函数中的RETURN语句返回一个类型不同于函数的RETURNS子句中指定类型的值,返回值将被强制为恰当的类型。mysql> DELIMITER // mysql> create function max_age() -> returns tinyint -> reads sql data -> return (select max(age) from user); -> // Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER ; mysql> select max_age(); +-----------+ | max_age() | +-----------+ | 34 | +-----------+ 1 row in set (0.00 sec)
变量
在存储过程中使用DECLARE语句定义变量,
DECLARE var_name[,varname]… date_type [DEFAULT value];
。var_name为局部变量的名称。DEFAULT value子句给变量提供一个默认值。值除了可以被声明为一个常数之外,还可以被指定为一个表达式。如果没有DEFAULT子句,初始值为NULL。mysql> DELIMITER // mysql> create procedure example(out arg int) -> begin -> declare var int default 10; -> select var into arg; -> end -> // Query OK, 0 rows affected (0.01 sec) mysql> call example(@num); -> // Query OK, 1 row affected (0.00 sec) mysql> select @num// +------+ | @num | +------+ | 10 | +------+ 1 row in set (0.00 sec) mysql>
为变量赋值,为变量赋值可以改变变量的默认值。在MySQL中,使用SET语句为变量赋值,
SET var_name = expr [, var_name = expr] ...;
。mysql> DELIMITER // mysql> create procedure example(out arg int) -> begin -> declare var int default 10; -> set var=30; -> select var into arg; -> end -> // Query OK, 0 rows affected (0.01 sec) mysql> call example(@num)// Query OK, 1 row affected (0.00 sec) mysql> select @num// +------+ | @num | +------+ | 30 | +------+ 1 row in set (0.00 sec) mysql> select * from user; -> // +----+-------+---------------+------+ | id | name | email | age | +----+-------+---------------+------+ | 1 | ronie | ronie@163.com | 20 | | 2 | jack | jack@163.com | 34 | | 3 | jerry | jerry@163.com | 22 | | 4 | lucy | lucy@163.com | 21 | +----+-------+---------------+------+ 4 rows in set (0.00 sec) mysql> drop procedure example// Query OK, 0 rows affected (0.00 sec) mysql> create procedure example(out n char(50), out m int) -> begin -> select name, age into n, m from user where id=1; -> end -> // Query OK, 0 rows affected (0.00 sec) mysql> call example(@name, @age); -> // Query OK, 1 row affected (0.00 sec) mysql> select @name, @age// +-------+------+ | @name | @age | +-------+------+ | ronie | 20 | +-------+------+ 1 row in set (0.00 sec)
定义条件和处理程序
- 定义条件
定义条件使用DECLARE语句,DECLARE condition name CONDITION FOR [condition type][condition_ type] :SQLSTATE [VALUE] sqlstate value| mysql error code
。condition_name参数表示条件的名称;condition_type参数表示条件的类型;sqlstate_value和MySQL_error_code都可以表示MySQL的错误,sqlstate_value为长度为5的字符串类型错误代码,MySQL_error_code为数值类型错误代码。 处理程序
使用DECLARE语句定义处理程序,语法:DECLARE handler_ type HANDLER FOR condition value[, . ..] sp_ statement handler_ type: CONTINUEI EXIT| UNDO condition value: SQLSTATE [VALUE] sqlstate_ value | condition name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_ error code
handler_type为错误处理方式,参数取3个值:CONTINUE、EXIT和UNDO。CONTINUE表示遇到错误不处理,继续执行;EXIT表示遇到错误马上退出;
condition_value表示错误类型,可以有以下取值:- SQLSTATE [VALUE] sqlstate_value包含5个字符的字符串错误值;
- condition_name表示DECLARE CONDITION定义的错误条件名称;
- SQLWARNING匹配所有以01开头的SQLSTATE错误代码;
- NOT FOUND匹配所有以02开头的SQLSTATE错误代码;
- SQLEXCEPTION匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码。
- MySQL_error_code匹配数值类型错误代码。
sp_statement参数为程序语句段,表示在遇到定义的错误时需要执行的存储过程或函数。
mysql> DELIMITER // mysql> create procedure example(in tb_name varchar(250), out num int) -> begin -> declare drop_tb_error condition for 1051; -> declare exit handler for drop_tb_error select 1051 into num; -> drop table @tb_name; -> end// Query OK, 0 rows affected (0.01 sec) mysql> set @tb_name='not_exists'// Query OK, 0 rows affected (0.00 sec) mysql> call example(@tb_name, @num)// Query OK, 1 row affected (0.00 sec) mysql> select @num// +------+ | @num | +------+ | 1051 | +------+ 1 row in set (0.00 sec)
Comments | NOTHING