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)
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)存储过程、存储函数的更多相关文章
- MySql基础笔记(一)Mysql快速入门
Mysql快速入门 一)基本概念 1)表 行被称为记录,是组织数据的单位.列被称为字段,每一列表示记录的一个属性. 2)主键 主键用于唯一的标识表中的每一条记录.可以定义表中的一列或者多列为主键, 但 ...
- MySQL 快速入门教程
转:MySQL快速 入门教程 目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据 ...
- MySQL快速入门(二)
目录 MySQL快速入门(二) 约束条件 自增 自增的特性 主键 外键 级联更新/删除 表与表之间的关系 外键约束 操作表方法 查询关键字 练习数据 select··from where 筛选 gro ...
- Oracle学习(十二):存储过程/存储函数
1.知识点 --第一个存储过程 /* 打印Hello World create [or replace] PROCEDURE 过程名(參数列表) AS PLSQL子程序体: 调用存储过程: 1. ex ...
- MySql(三)存储过程和函数
MySql(三)存储过程和函数 一.什么是存储过程和函数 二.存储过程和函数的相关操作 一.什么是存储过程和函数 存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数 ...
- MySQL 快速入门(一)
目录 MySQL快速入门 简介 存储数据的演变过程 数据库分类 概念介绍 MySQL安装 MySQL命令初始 环境变量配置 MySQL环境变量配置 修改配置文件 设置新密码 忘记密码的情况 基本sql ...
- Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(7)|函数Functions与闭包Closure]
[易学易懂系列|rustlang语言|零基础|快速入门|(7)函数Functions与闭包Closure] 有意思的基础知识 函数Functions与闭包Closure 我们今天再来看看函数. 在Ru ...
- <MySQL>入门七 存储过程和函数
-- 存储过程和函数 /* 存储过程和函数:类似java中的方法 好处: 1.提高代码的重用性 2.简化操作 */ /* 存储过程 含义:一组预先编译好的SQL语句的集合.理解成批处理语句 1.提高代 ...
- Mysql快速入门(看完这篇能够满足80%的日常开发)
这是一篇mysql的学习笔记,整理结合了网上搜索的教程以及自己看的视频教程,看完这篇能够满足80%的日常开发了. 菜鸟教程:https://www.runoob.com/mysql/mysql-tut ...
随机推荐
- python 字符词串和字符串的转换
type(' i am ') str type(''.join('i am')) str ''.join('sda sadaa') 'sda sadaa' q=str('i am the teache ...
- git的用法的总结
git的基本用法(一) 1).git的初始化 --配置用户名和邮箱 不然后面无法提交 git config --global user.name "myname"; git con ...
- vscode匹配括号插件
给大家推荐一个vscode匹配括号的插件: Bracket Pair Colorizer.超级好用哦
- Redis实战(十四)Redis实现Session共享
序言 登录的处理流程: 1.登录页面提交用户名密码. 2.登录成功后生成token.Token相当于原来的jsessionid,字符串,可以使用uuid. 3.把用户信息保存到redis.Key就是t ...
- HTML5 大文件断点续传完整思路整理
需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...
- Zookeeper简介及安装(一)
1 Zookeeper入门1.1 概述Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目. 1.2 特点 1.3 数据结构 1.4 应用场景提供的服务包括:统一命名服务 ...
- sh_08_打印分隔线
sh_08_打印分隔线 def print_line(char, times): print(char * times) print_line("hi ", 40)
- vue-cli 构建的 Vue 项目用 localhost 加 端口 能访问,但是切换到 ip 加 端口 就不能访问
问题出在 webpack 的配置 在 config 文件夹下, 找到 index.js 目录, 找到如下代码 host: 'localhost', // can be overwritten by p ...
- java分页原理及分类
1.使用List接口最终subList()方法实现分页 2.直接使用数据库SQL语句实现分页 3.使用hibernate等框架实现跨数据库的分页 mybatis是面向SQL的,本质上和第二种分页方式相 ...
- 复选框checked 选中后不显示打钩
复选框checked 选中后不显示打钩 checkbox属性checked="checked"已有,但复选框却不显示打钩的原因 复选框绑定了click事件,点一次选中,再点击取 ...