1、存储过程

1》创建存储过程:create procedure

create procedure sp_name ([in | out | inout] param_name type)
[characteristics ...] routine_body

characteristics指定存储过程的特性:

1>language sql:说明routine_body部分是由sql语句组成的,当前系统支持的语言为sql,sql是language特性的唯一值。

2>[not] deterministic:指明存储过程执行的结果是否确定。deterministic表示结果是确定的。每次执行存储过程时,相同的输入会得到相同的输出。not deterministic表示结果是不确定的,相同的输入可能得到不同的输出。如果没有指定任意一个值,默认为not deterministic。

3>{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。

4>sql security{definer | invoker}:指明谁有权限来执行。definer表示只有定义者才能执行。invoker表示拥有权限的调用者可以执行。默认情况下,系统指定为definer。

5>comment 'string':注释信息,可以用来描述存储过程或函数。

routine_body:sql代码的内容,可以用begin...end;来表示sql代码的开始和结束。

//最简单的存储过程
create procedure p_get_avg()
begin
...
end;
//"delimiter //"的作用是将MySQL的结束符设置为//,因为MySQL默认的语句结束符号为分号";",
//为了避免与存储过程中sql语句的结束符相冲突,需要使用delimiter改变存储过程的结束符,并
//"end//"结束存储过程。"delimiter ;"则是恢复默认的";"结束符。
mysql> delimiter //
mysql> create procedure p_get_avg()
-> begin
-> select * from test;
-> end//
Query OK, 0 rows affected (0.02 sec) mysql> delimiter ;

2、存储函数

1》创建存储函数:create function

//指定in、out、inout只对procedure是合法的,在function中总是默认为in类型
//如果return返回的类型不同于returns指定的类型,返回值将会被强制转换为恰当的类型。
create function func_name([in | out | inout] param_name type)
returns type
[characteristic ...] routine_body
mysql> delimiter //
mysql> create function f_get_avg()
-> returns char(25)
-> begin
-> return (select name from test where id=1);
-> end//
Query OK, 0 rows affected (0.00 sec) mysql> delimiter ;
mysql> delimiter //
mysql> drop function if exists f_get_avg;
-> CREATE FUNCTION f_get_avg()
-> RETURNS int
-> begin
-> declare i int default 0;
-> select 666 into i from dual;
-> return i;
-> end//
Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected (0.02 sec) mysql> delimiter ;
mysql> select f_get_avg();
+-------------+
| f_get_avg() |
+-------------+
| 666 |
+-------------+
1 row in set (0.00 sec) mysql>
注:trigger和function都需要写成 select ...into  这种句式,否者会报1415错误?
CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() RETURNS int(11)
begin
declare i int default 0;
/*select 666 into i from dual;*/
return i;
end
CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() RETURNS int(11)
begin
declare i int default 0;
/*select 666 into i from dual;*/
set i=999;
return i;
end

3、变量的使用

1》在存储过程中使用declare语句定义变量:

declare var_name [,var_name]... data_type [default value];
即:
declare var1,var2,var3 int;

2》为变量赋值:定义变量后,MySQL使用set语句为变量赋值

set var_name = expr [,var_name=expr] ...;
或者
select col_name[,...] into var_name[,...] tb_expr;
即:
set var1=10,var2=20;

4、定义条件和处理程序:都是使用declare关键字

1》定义条件

//codition_name:表示条件的名称;condition_type参数表示条件的类型;
//sqlstste_value和mysql_error_code:都可以表示MySQL的错误
//sqlstate_value:为长度为5的字符串类型错误代码。
//mysql_error_code:为数值类型错误代码。
//例如:error 1142(42000)中,sqlstate_value的值是42000,mysql_error_code的值为1142。
declare condition_name condition for [condition_type] 其中[condition_type]:sqlstate [value] sqlstate_value
| mysql_error_code
即:
declare condition_name condition for sqlstate [value] sqlstate_value
或者
declare condition_name condition for mysql_error_code

举例:

//定义"error 1148(42000)"错误,名称为command_not_allowed
//方法一:使用sqlstate_value
declare command_not_allowed condition for sqlstate '';
//方法二:使用mysql_error_code
declare command_not_allowed condition for 1148;

2》定义处理程序

declare handler_type handler for condition_value[,...] sp_statement

sp_statement:程序语句段,表示遇到定义的错误时,需要执行的存储过程或函数 //错误处理方式
//continue:表示遇到错误不处理。继续执行;
//exit:遇到错误马上退出;
//undo:表示遇到错误后撤回之前的操作,MySQL暂时不支持这样的操作。
handler_type:continue | exit | undo

//错误类型
//sqlstate [value] sqlstate_value:包含5个字符的字符串错误值
//condition_name:表示declare condition定义的错误条件名称
//mysql_error_code:匹配数值类型错误代码
//sqlwarning:匹配所有以01开头的sqlstate错误代码
//not found:匹配所有以02开头的sqlstate错误代码
//sqlexception:匹配所有没有被sqlwarning或not found捕获的sqlstate错误代码
condition_value:
sqlstate [value] sqlstate_value
| condition_name
| mysql_error_code
| not found
| sqlexception
| sqlwarning

举例:

//方法一:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='NO_SUCH_TABLE'; //方法二:捕获mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info=' NO_SUCH_TABLE '; //方法三:先定义条件,然后调用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info=' NO_SUCH_TABLE '; //方法四:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR'; //方法五:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info=' NO_SUCH_TABLE '; //方法六:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';
mysql> DELIMITER //
mysql> CREATE PROCEDURE handlerdemo ()
-> BEGIN
-> DECLARE CONTINUE HANDLER FOR SQLSTATE '' 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 (0.02 sec) mysql> DELIMITER ;
mysql> CALL handlerdemo();
Query OK, 0 rows affected (0.02 sec) mysql> select @x;
+------+
| @x |
+------+
| 3 |
+------+
1 row in set (0.00 sec) mysql> select @x2;
+------+
| @x2 |
+------+
| 1 |
+------+
1 row in set (0.00 sec) mysql> select * from t;
+----+
| s1 |
+----+
| 1 |
+----+
1 row in set (0.00 sec) mysql>

@x是一个用户变量,执行结果@x等于3,说明存储过程被执行到了最后面一句。如果省去异常处理那一句,第2个insert因为主键约束强制失败之后,存储过程可能已经采取默认(exit)路径,此时select @x返回的结果可能是2。

"@var_name"表示用户变量,使用set语句为其赋值,用户变量与连接有关,一个客户端定义的变量不能被其他客户端看到或使用。
当客户端连接退出时,该客户端连接的所有变量将自动释放。

5、光标的使用:MySQL中的光标只能在存储过程、存储函数中使用

1》声明光标

declare cursor_name cursor for select_statement;

2》打开关标

open cursor_name;

3》使用光标

fetch cursor_name into var_name[,var_name] ...;

4》关闭光标

close cursor_name;

  举个例子:

create procedure p3()
begin
declare id int;
declare name varchar(15);
declare flag int default 0;
-- 声明游标
declare mc cursor for select * from class1;
declare continue handler for not found set flag = 1;
-- 打开游标
open mc;
-- 获取结果
loop_label_0:loop
fetch mc into id,name;
if flag=1 then -- 当无法fetch会触发handler continue
leave loop_label_0;
end if;
-- 这里是为了显示获取结果
insert into class2 values(id,name);
-- 关闭游标
end loop;
close mc;
end; call p3();-- 不报错
select * from class2;

6、流程控制使用

MySQL中用于流程控制的语句有:if、case、loop、leave、iterate、repeat、while语句。每个流程可能包含一个单独语句,或者使用begin...end构造的符合语句,构造可以被嵌套。

1》if语句

//statement_list可以包含一个或者多个语句
if expr_condition then
statement_list
[elseif expr_condition then statement_list ...] ...
[else statement_list]
end if

2》case语句。与“控制流程函数”中的case是不同的。

//第一种方式:
//匹配表达式的值
case case_expr
when when_value then statement_list
[when when_value then statement_list] ...
[else statement_list] //不能有else null子句
end case //第二种方式:
//逐个表达式执行,直到有一个表达式为true被执行
case
when expr_condition then statement_list
[when expr_condition then statement_list] ...
[else statement_list] //不能有else null子句
end case

3》loop语句

[loop_label:] loop
statement_list
//如果要跳出循环,这时候label是必须的
if expr_condition then leave loop_label
end if;
end loop [loop_label]

4》leave语句

//用来退出任何被标注的流程控制构造,包括begin...end和循环体。
leave label

5》iterate语句

//将执行顺序转到语句段开头处
//iterate只可以出现在loop、repeat、while语句内,iterate表示再次循环,label参数表示循环的标志。
//iterate语句必须跟在循环标志前面。
iterate label
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语句

创建一个带条件判断的循环过程,每次语句执行完毕,会对条件表达式进行判断,如果表达式为真,则循环结束;否则重复执行循环中的语句。相当于do...while语句。

[repeat_label:]repeat
statement_list
until expr_condition
end repeat [repeat_label]

7》while语句

[while_label:]while expr_condition do
statement_list
end while [while_label]

7、调用存储过程、存储函数

存储过程的调用必须使用call语句,并且存储过程和数据库相关,如果要执行其他数据库中的存储过程,需要指定数据库名称。

存储函数的调用与MySQL中定义的函数的调用方式相同。

1》调用存储过程

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

CREATE DEFINER=`root`@`localhost` PROCEDURE `p_get_name`(in i_id int,out o_name varchar(25))
  begin
    select name into o_name from test t where t.id=i_id;
  end

-----------------------------------
mysql> call p_get_name(1,@name);
Query OK, 1 row affected (0.00 sec) mysql> select @name;
+-------+
| @name |
+-------+
| Lucy |
+-------+
1 row in set (0.00 sec) mysql>

2》调用存储函数:与MySQL内部定义的函数一样的使用方法。

CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() RETURNS char(50) CHARSET utf8
begin
return (select avg(salary) from test);
end --------------------------------------
mysql> select f_get_avg();
+-------------+
| f_get_avg() |
+-------------+
| 1180 |
+-------------+
1 row in set (0.00 sec) mysql>

8、查看存储过程和函数,方法有3种:

1》show status

//[like 'pattern']指匹配存储过程或函数的名称
show {procedure | function} status [like 'pattern']
mysql> show procedure status like 'p_get_name%' \G
*************************** 1. row ***************************
Db: mybatis
Name: p_get_name
Type: PROCEDURE
Definer: root@localhost
Modified: 2019-09-05 00:28:04
Created: 2019-09-05 00:28:04
Security_type: DEFINER
Comment:
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec) mysql>

2》show create

show create {procedure | function} sp_name
mysql> show create function f_get_avg \G
*************************** 1. row ***************************
Function: f_get_avg
sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITU
TION
Create Function: CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() R
ETURNS char(50) CHARSET utf8
begin
return (select avg(salary) from test);
end
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec) mysql>

3》从系统的information_schema数据库查询

MySQL中存储过程和存储函数的信息存储在information_schema数据库下的Routines表中。

select * from information_schema.Routines
where routine_name=' sp_name ' and routine_type='procedure | function';
mysql> select * from information_schema.routines where routine_name='p_get_name'
and routine_type='procedure' \G
*************************** 1. row ***************************
SPECIFIC_NAME: p_get_name
ROUTINE_CATALOG: def
ROUTINE_SCHEMA: mybatis
ROUTINE_NAME: p_get_name
ROUTINE_TYPE: PROCEDURE
DATA_TYPE:
CHARACTER_MAXIMUM_LENGTH: NULL
CHARACTER_OCTET_LENGTH: NULL
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: NULL
COLLATION_NAME: NULL
DTD_IDENTIFIER: NULL
ROUTINE_BODY: SQL
ROUTINE_DEFINITION: begin
select name into o_name from test t where t.id=i_id;
end
EXTERNAL_NAME: NULL
EXTERNAL_LANGUAGE: NULL
PARAMETER_STYLE: SQL
IS_DETERMINISTIC: NO
SQL_DATA_ACCESS: CONTAINS SQL
SQL_PATH: NULL
SECURITY_TYPE: DEFINER
CREATED: 2019-09-05 00:28:04
LAST_ALTERED: 2019-09-05 00:28:04
SQL_MODE: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBS
TITUTION
ROUTINE_COMMENT:
DEFINER: root@localhost
CHARACTER_SET_CLIENT: utf8
COLLATION_CONNECTION: utf8_general_ci
DATABASE_COLLATION: utf8_general_ci
1 row in set (0.00 sec) mysql>

9、修改存储过程、函数(并不是修改其中的代码)

alter {procedure | function} sp_name [characteristic ...]
characteristic指定存储过程的特性,可能的取值有:
  contains sql:表示子程序包含sql语句,但不包含读或写数据的语句。
no sql:表示子程序中不包含sql语句。
reads sql data:表示子程序中包含读数据的语句。
modifies sql data:表示子程序中包含写数据的语句。
sql security {definer | invoker}:指明谁有权限来执行。
definer:表示只有定义者自己才能够执行。
invoker:表示调用者可以执行。
comment 'string':表示注释信息。

10、删除存储过程、函数

drop {procedure | function} [if exists] sp_name

MySQL-快速入门(8)存储过程、存储函数的更多相关文章

  1. MySql基础笔记(一)Mysql快速入门

    Mysql快速入门 一)基本概念 1)表 行被称为记录,是组织数据的单位.列被称为字段,每一列表示记录的一个属性. 2)主键 主键用于唯一的标识表中的每一条记录.可以定义表中的一列或者多列为主键, 但 ...

  2. MySQL 快速入门教程

    转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...

  3. MySQL快速入门(二)

    目录 MySQL快速入门(二) 约束条件 自增 自增的特性 主键 外键 级联更新/删除 表与表之间的关系 外键约束 操作表方法 查询关键字 练习数据 select··from where 筛选 gro ...

  4. Oracle学习(十二):存储过程/存储函数

    1.知识点 --第一个存储过程 /* 打印Hello World create [or replace] PROCEDURE 过程名(參数列表) AS PLSQL子程序体: 调用存储过程: 1. ex ...

  5. MySql(三)存储过程和函数

    MySql(三)存储过程和函数 一.什么是存储过程和函数 二.存储过程和函数的相关操作 一.什么是存储过程和函数 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数 ...

  6. MySQL 快速入门(一)

    目录 MySQL快速入门 简介 存储数据的演变过程 数据库分类 概念介绍 MySQL安装 MySQL命令初始 环境变量配置 MySQL环境变量配置 修改配置文件 设置新密码 忘记密码的情况 基本sql ...

  7. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...

  8. [易学易懂系列|rustlang语言|零基础|快速入门|(7)|函数Functions与闭包Closure]

    [易学易懂系列|rustlang语言|零基础|快速入门|(7)函数Functions与闭包Closure] 有意思的基础知识 函数Functions与闭包Closure 我们今天再来看看函数. 在Ru ...

  9. <MySQL>入门七 存储过程和函数

    -- 存储过程和函数 /* 存储过程和函数:类似java中的方法 好处: 1.提高代码的重用性 2.简化操作 */ /* 存储过程 含义:一组预先编译好的SQL语句的集合.理解成批处理语句 1.提高代 ...

  10. Mysql快速入门(看完这篇能够满足80%的日常开发)

    这是一篇mysql的学习笔记,整理结合了网上搜索的教程以及自己看的视频教程,看完这篇能够满足80%的日常开发了. 菜鸟教程:https://www.runoob.com/mysql/mysql-tut ...

随机推荐

  1. excel中汉字转拼音

    Excel中文转拼音(完整版)打开Excel->工具->宏->Viaual Basic编辑器在弹出来的窗口中对着VBAproject点右键->插入->模块下面会出现一个名 ...

  2. layui.form is not a function

    改变: var form = layui.form; 如果你是从1.x升级2.x造成的,那只需要在定义的时候吧后面的()去掉就可以了.请关注更新日志:1.x 升 2.0 特别注意事项layDate日期 ...

  3. Power-Aware GateSim Debug

    For PAG debug, the following steps may be useful. 1. Get correct netlists from PD which contain powe ...

  4. 计算器work_day05

    day_work_05 ------Python是一个优雅的大姐姐 作业计算器 设计思路 按照运算优先级和正则先算括号内的值,提出来判断符号问题,然后依次计算. 分析题目设计了四个函数,分别为a)去括 ...

  5. Ansible跳板机自动部署

    首先,安装ansible,略过此步骤. 一.控制机(jenkens.ansible所在机器与跳板机之间互信,跳板机与目的机之间互信) 1.在客户端生成公钥私钥对 命令:ssh-keygen -t rs ...

  6. Spring Cloud架构教程 (二)Hystrix监控数据聚合

    上一篇我们介绍了使用Hystrix Dashboard来展示Hystrix用于熔断的各项度量指标.通过Hystrix Dashboard,我们可以方便的查看服务实例的综合情况,比如:服务调用次数.服务 ...

  7. 基于AdminLTE的jquery头像更新

    最近在写实验室管理系统中的个人信息模块,上边要求实现更改头像功能.百度了一大堆,无实用的.(要么各种币) 本文介绍的只是实现了简单功能(毕竟现在初学阶段) 需要引用文件,顺序也不能错. <scr ...

  8. css中如何使用border属性与display属性

    border属性介绍 border属性设置元素边框. 边框3个要素如:粗细.线型.颜色. 边框线型属性值说明表如: 属性指 描述 none 定义无边框. hidden 与 "none&quo ...

  9. 自定义input上传图片组件

    自定义input上传图片组件,美化样式 前段时间因为项目需求,做过一个上传图片组件,这里分享下大致思路,希望对有需要的童鞋有所帮助~~~ 功能需求:1.上传图片限制大小.分辨率.类型 2.上传图片支持 ...

  10. Linux小记 -- 更新系统软件包

    系统信息 操作系统:Ubuntu 18.04.2 LTS 内核版本:4.15.0-51-generic 何时需要更新 重新启动Ubuntu发现如下motd(message of tody),此时需要更 ...