MySQL-快速入门(8)存储过程、存储函数
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) begindeclare i int default 0; /*select 666 into i from dual;*/return i; end
CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() RETURNS int(11) begindeclare 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 '42000';//方法二:使用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 '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 (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() begindeclare 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_exprwhen when_value then statement_list[when when_value then statement_list] ...[else statement_list] //不能有else null子句 end case//第二种方式: //逐个表达式执行,直到有一个表达式为true被执行 casewhen expr_condition then statement_list[when expr_condition then statement_list] ...[else statement_list] //不能有else null子句 end case
3》loop语句
[loop_label:] loopstatement_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: LOOPSET 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:]repeatstatement_list until expr_condition end repeat [repeat_label]
7》while语句
[while_label:]while expr_condition dostatement_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 beginreturn (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: mybatisName: p_get_nameType: PROCEDUREDefiner: root@localhostModified: 2019-09-05 00:28:04Created: 2019-09-05 00:28:04Security_type: DEFINERComment: character_set_client: utf8 collation_connection: utf8_general_ciDatabase 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_avgsql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITU TIONCreate Function: CREATE DEFINER=`root`@`localhost` FUNCTION `f_get_avg`() R ETURNS char(50) CHARSET utf8 beginreturn (select avg(salary) from test); end character_set_client: utf8 collation_connection: utf8_general_ciDatabase 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_nameROUTINE_CATALOG: defROUTINE_SCHEMA: mybatisROUTINE_NAME: p_get_nameROUTINE_TYPE: PROCEDUREDATA_TYPE: CHARACTER_MAXIMUM_LENGTH: NULLCHARACTER_OCTET_LENGTH: NULLNUMERIC_PRECISION: NULLNUMERIC_SCALE: NULLDATETIME_PRECISION: NULLCHARACTER_SET_NAME: NULLCOLLATION_NAME: NULLDTD_IDENTIFIER: NULLROUTINE_BODY: SQLROUTINE_DEFINITION: beginselect name into o_name from test t where t.id=i_id; endEXTERNAL_NAME: NULLEXTERNAL_LANGUAGE: NULLPARAMETER_STYLE: SQLIS_DETERMINISTIC: NOSQL_DATA_ACCESS: CONTAINS SQLSQL_PATH: NULLSECURITY_TYPE: DEFINERCREATED: 2019-09-05 00:28:04LAST_ALTERED: 2019-09-05 00:28:04SQL_MODE: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBS TITUTIONROUTINE_COMMENT:DEFINER: root@localhostCHARACTER_SET_CLIENT: utf8COLLATION_CONNECTION: utf8_general_ciDATABASE_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
转载于:https://www.cnblogs.com/ZeroMZ/p/11461295.html
MySQL-快速入门(8)存储过程、存储函数相关推荐
- WebDay18 MySQL存储过程 存储函数 触发器 事务
MySQL存储过程 存储函数 触发器 事务 一.MySQL存储过程和函数 1.存储过程和函数的概念 2.存储过程和函数的好处 3.存储过程和函数的区别 4.创建存储过程 5.调用存储过程 6.查看存储 ...
- Day463.视图存储过程存储函数 -mysql
视图 1. 常见的数据库对象 对象 描述 表(TABLE) 表是存储数据的逻辑单元,以行和列的形式存在,列就是字段,行就是记录 数据字典 就是系统表,存放数据库相关信息的表.系统表的数据通常由数据库系 ...
- MySQL 案例实战--MySQL数据库 存储过程 存储函数
MySQL数据库 存储过程 & 存储函数 前言 一.什么是存储过程 & 存储函数 二.存储过程的创建和调用 三.存储函数的创建和调用 前言 本环境是基于 Centos 7.8 系统构建 ...
- MySQL 快速入门教程
转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...
- 阿里云rds for mysql平台介绍_阿里云RDS for MySQL 快速入门——笔记
1初始化配置 1.1设置白名单 创建RDS实例后,需要设置RDS实例的白名单,以允许外部设备访问该RDS实例.默认的白名单只包含默认IP地址127.0.0.1,表示任何设备均无法访问该RDS实例. 设 ...
- mysql rds云数据库_云数据库 RDS MySQL快速入门手册
云数据库 RDS MySQL是一款基于成熟云计算技术提供的高性能数据库服务,具有入门版.基础版.通用版.进阶版这四种,但最近有朋友表示,说自己并不会使用云数据库 RDS MySQL,为了帮助大家更好设 ...
- 视图存储过程存储函数
文章目录 视图 常见数据库对象 视图概述 为什么使用视图? 视图的理解 创建视图 创建单表视图 创建多表联合视图 基于视图创建视图 查看视图 更新视图的数据 一般情况 不可更新的视图 修改.删除视图 ...
- Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表.---查询语句创建表 create table emp as ...
- mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例
一个存储过程是一个可编程的函数,它可以在MySQL中创建并保存.它是由一些SQL语句和一些特殊的控制结构语句组成. 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定的功能时,存储过程是一个非 ...
- Mysql 存储过程 / 存储函数
目录 0 课程视频 1 基本语法 1.0 作用 ->在数据库中 封装sql语句 -> 复用 -> 减少网络交互 ->可接收参数返回数据 1.1 创建 1.2 调用 1.3 查看 ...
最新文章
- android支付宝插件,GitHub - DmcSDK/cordova.plugin.alipay: cordova 支付宝支付插件,支持IOS Android。...
- 手语识别 机器学习_机器学习入门实践,让机器识别一只猫
- android studio 一直在 svn performing vcs refresh
- Miniconda3及pip换源(conda清华源关闭)
- Spring Cloud构建微服务架构:消息驱动的微服务(入门)【Dalston版】
- 一文搞懂RSA算法原理及简单实现
- 酒驾、超速、加塞、路怒、拒载?来吧,我们专治各种不服
- HTML5 Video DOM 入门体验
- matlab dotchart,MATLAB中如何用对数方式显示图形坐标?
- 从研发到管理,这十大技巧助我提升了领导力
- React中受控组件和非受控组件
- 和jwt应用场景_一文了解web无状态会话token技术JWT
- (七)、Java异常类型及处理
- flashcs3java_Flash CS3组件开发图文教程
- mysql索引超出了数组接线_索引超出了数组界限如何解决?
- EIA/TIA 568A 568B 标准
- od反汇编linux,新手学习反汇编之OD寻找功能call
- 高级项目经理的企业需求、企业地位
- 2012年***名单。
- 2021-09-08
热门文章
- MACOS,应用签名后就崩溃?
- LINUX SHELL能不能调用桌面刷新命令,或者模拟键盘输入F5?
- 全网首发:deb打包时报错dh: Please specify the compatibility level in debian/compat
- JDK8的shenandoah GC/zgc啥时能转正?
- 世界首次发现?包名导致eclipse找不到包含main的类
- 程序员至少一半时间用于测试
- 解决办法:nvidia-settings:ERROR: Unable to load info from any available system
- 1970年代宇航员在月球上生活,如何实现电力供应
- SHELL下如何去掉字串里的空格(或指定字符)
- LINUX下使用scp命令与其他机器远程交换文件