存储过程和函数
存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合.
调用存储过程和函数可以简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输,提高数据处理的效率.
存储过程和函数的区别在于:
函数必须有返回值,而存储过程没有.
存储过程的参数可以使用 IN,OUT,INOUT 类型;而函数的参数只能是IN类型.
如果有函数从其他类型数据库迁移到MySQL就可能需要把函数改造成存储过程.
存储过程和函数的相关操作
首先确认是否有相应的权限.
创建存储过程/函数 需要CREATE ROUTINE权限.
修改/删除 存储过程/函数 需要ALTER ROUTINE权限.
执行存储过程/函数 需要EXECUTE权限.
1).创建/修改 存储过程或函数
CREATE PROCEDURE sp_name ([proc_param[,...]])
[characteristic …]
routine_body
CREATE FUNCTION sp_name ([func_param[,...])
RETURNS type
[characteristic …]
routine_body
其中,
proc_param :
[IN|OUT|INOUT] param_name type
func_param :
param_name type
type : any valid MySQL data type .
characteristic :
LANGUAGE SQL
| [NOT] DETERMINISTIC
| {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
| SQL SECURITY {DEFINER | INVOKER}
| COMMENT 'string'
routine_body :
valid SQL procedure statement or statements .
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
characteristic :
{CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
|SQL SECURITY {DEFINER|INVOKER}
|COMMENT 'string'
调用存储过程/函数,使用关键字CALL :
CALL sp_name ([[parameter [,...]])
注意: 存储过程/函数 中允许包含DDL ,也可以在存储过程中执行COMMIT/ROLLBACK 操作,还可以调用其他的过程/函数;
但是存储过程/函数 中不允许使用 LOAD DATA INFILE 语句.
Demo :
DELIMITER $$
CREATE PROCEDURE film_in_stock (IN p_film_id INT , IN p_store_id INT , OUT p_film_count INT)
READS SQL DATA
BEGIN
SELECT inventory_id
FROM inventory
WHERE film_id = p_film_id
AND store_id = p_store_id
AND inventory_in_stock(inventory_id);
SELECT FOUND_ROWS() INTO p_film_count;
END $$
DELIMITER ;
CALL film_in_stock(2,2,@a);
SELECT @a ;
注意 : 与视图的创建语法不同,存储过程/函数 的CREATE语法不支持使用 CREATE OR REPLACE对存储过程/函数进行修改.如需修改,可以执行ALTER语法.
characteristic特征值的简单说明:
1).LANGUAGE SQL
说明下面过程的BODY是使用SQL语句编写(系统默认的),以后MySQL可能支持其它语言.
2).[NOT] DETERMINISTIC:
目前还未被优化程序使用
DETERMINISTIC 每次输入一样输出也一样的程序
NOT DETERMINISTIC(系统默认).
3).{CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}
目前这些特征值只是提供给服务器,并未用来约束存储过程实际使用数据的情况.
CONTAINS SQL 表示子程序不包含读或者写数据的语句
NO SQL 表示子程序不包含SQL语句
READS SQL DATA 表示子程序包含读数据的语句
MODIFIES SQL DATA 表示子程序包含写数据的语句
默认值是 CONTAINS SQL
4).SQL SECURITY {DEFINER | INVOKER}
指定子程序 该用创建子程序者的权限来执行,还是使用调用者的权限来执行.默认值是DEFINER , 即使用创建者的权限执行.
5).COMMENT 'string'
存储过程/函数 的注释信息.
2.删除存储过程/函数
一次性只能删除一个存储过程/函数.需要有ALTER ROUTINE 权限.
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
3.查看存储过程/函数
1).查看存储过程/函数 的状态
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
2).查看存储过程/函数 的定义
SHOW CREATE {PROCEDURE|FUNCTION} sp_name
3).通过查看information_schema.Routines 了解存储过程/函数 的信息
包含名称,类型,语法,创建人等信息.
demo:SELECT * FROM routines WHERE ROUTINE_NAME = 'film_in_stock' \G
4.变量的使用
1).变量的定义
DECLARE var_name [,...] type [DEFAULT value]
2).变量的赋值
SET var_name = expr [,var_name = expr] ...
其中,expr 可以是字面量,函数返回值,SELECT 语句(要求结果有且只有一行)等.
或者使用SELECT .. INTO .. 语句
SELECT col_name[,..] INTO var_name[,..] table_expr
Demo :
DECLARE $$
CREATE FUNCTION get_customer_balance( p_customer_id INT , p_effective_date DATETIME )
RETURNS DECIMAL(5,2)
DETERMINISTIC
READS SQL DATA
BEGIN
...
DECLARE v_payments DECIMAL(5,2) ;
...
SELECT IFNULL (SUM(payment,amount),0) INTO v_payments
FROM payment
WHERE payment.payment_date <= p_effective_date
AND payment.customer_id = p_customer_id ;
...
RETURN v_rentfees + v_overfees - v_payments ;
END $$
DECLARE ;
CALL get_customer_balance(1,'2018-03-02 09:11:15') ;
5.定义条件和处理
1).条件的定义
DECLARE condition_name CONDITION FOR condition_value
其中,condition_value :
SQLSTATE [VALUE] sqlstate_value | mysql_error_code
2).条件的处理
DECLARE handler_type HANDLER FOR condition_value[,..] sp_statement
handler_type :
CONTINUE | EXIT | UNDO(暂不支持)
condition_value:
SQLSTATE [VALUE] sqlstate_value
|condition_name
|SQLWARNING
|NOT FOUND
|SQLEXCEPTION
|mysql_error_code
demo:todo
6.光标的使用 --就是游标
可以使用游标对结果集进行循环处理
1).声明光标
DECLARE cursor_name CURSOR FOR select_statement
select_statement 中的SELECT语句 不能包含 INTO , 即不可以是SELECT .. INTO ..语句
SELECT 语句查询出来的列数 , 必须与FETCH游标中的接收数据的变量数 一致.
2).OPEN光标
OPEN cursor_name
3).FETCH光标
FETCH cursor_name INTO var_name[,var_name,..]
4).CLOSE光标
CLOSE cursor_name
Demo : —— 需要注意 DECLARE 声明的顺序 : 变量 -> 游标 -> 条件处理 .
DELIMITER $$
CREATE PROCEDURE payment_stat()
BEGIN
DECLARE i_staff_id INT ;
DECLARE d_amount DECIMAL(5,2);
DECLARE cur_payment CURSOR FOR SELECT staff_id,amount FROM payment ;
DECLARE EXIT HANDLER FOR NOT FOUND CLOSE cur_payment ;
SET @x1 = 0 ;
SET @x2 = 0 ;
OPEN cur_payment ;
REPEAT
FETCH cur_payment INTO i_staff_id,d_amount ;
IF i_staff_id = 2
THEN
SET @x1 = @x1 + d_amount ;
ELSE
SET @x2 = @x2 + d_amount ;
END IF ;
UNTIL 0 END REPEAT ;
CLOSE cur_payment ;
END ;
$$
DELIMITER ;
CALL payment_stat();
注意:变量,条件,处理程序,游标都是通过DECLARE定义的,但是顺序是由先后要求的.
变量和条件 必须声明在最前面,然后是游标的声明,最后才是处理程序的声明.
7.流程控制
1).IF语句
IF search_condition
THEN statement_list
[
ELSEIF search_condition
THEN statement_list
]
[
ELSE statement_list
]
END IF
2).CASE语句
CASE case_value
WHEN when_value THEN
statement_list
[
WHEN when_value THEN
statement_list
]
...
[
ELSE
statement_list
]
END CASE
或者
CASE WHEN search_condition THEN
statement_list
[
WHEN search_condition THEN
statement_list
]
...
[
ELSE
statement_list
]
END CASE
Demo : 改写游标demo中IF语句
CASE
WHEN i_staff_id = 2
THEN
SET @x1=@x1+d_amount ;
ELSE
SET @x2= @x2+d_amount ;
END CASE ;
或
CASE i_staff_id
WHEN 2
THEN
SET @x1 = @x1 + d_amount ;
ELSE
SET @x2 = @x2 + d_amount ;
END CASE ;
3).LOOP 语句
简单的循环,需要配合其他的语句定义来实现退出循环,通常使用LEAVE语句实现.
[begin_label:] LOOP
statement_list
END LOOP [end_label]
如果没有退出循环语句,就是个死循环.
4).LEAVE 语句
从标注的流程中退出,通常和BEGIN..END / 循环 一起使用.
Demo :
DELIMITER $$
CREATE PROCEDURE actor_insert()
BEGIN
SET @x = 0 ;
ins : LOOP
SET @x = @x+1;
IF @x=100
THEN
LEAVE ins ;
END IF ;
INSERT INTO actor(first_name,last_name)
VALUES('Test','201');
END LOOP ins ;
END ;
$$
DELIMITER ;
CALL actor_insert();
5).ITERATE 语句
必须用在循环中,表示跳过当前循环的剩下语句,进入下次循环.作用相当于Java中的continue.
Demo:
DELIMITER $$
CREATE PROCEDURE actor_insert()
BEGIN
SET @x = 0 ;
ins : LOOP
SET @x = @x + 1;
IF @x = 10
THEN
LEAVE ins ;
ELSEIF mod(@x,2) = 0
THEN
ITERATE ins ;
END IF ;
INSERT INTO actor (actor_id , first_name,last_name)
VALUES(@x*10,'Test',@x);
END LOOP ins ;
END ;
$$
DELIMITER ;
CALL actor_insert() ;
6).REPEAT 语句
有条件的循环语句,相当于Java中的do_while
不同的是REPEAT是满足条件时就退出循环,while是满足就执行.Repeat 和 do..while 一样,至少执行一次.
Demo参考游标的demo
7).WHILE 语句
[begin_label:] WHILE search_condition
DO statement_list
END WHILE [end_label]
总结:存储过程/函数的优势是可以将数据的处理放在数据库服务器上进行,避免将大量的结果集传输给客户端,减少数据传输,
但是在数据库服务器上进行大量的复杂运算会占用服务器的cpu,造成数据库服务器的压力,
所以存储过程/函数中不要进行大量的复杂运算,应该将这些运算操作分摊到应用服务器上执行.
- 12.Mysql存储过程和函数
12.存储过程和函数12.1 什么是存储过程和函数存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程和函数简化应用开发人员的工作,减少数据在数据库和应用服务器之间的传输, ...
- MYSQL存储过程和函数学习笔记
学至Tarena金牌讲师,金色晨曦科技公司技术总监沙利穆课程笔记的综合. 1. 什么是存储过程和函数 将SQL语句放入一个集合里,然后直接调用存储过程和函数来执行已经定义好的SQL语句,通过存储过程和 ...
- Paip.断点调试MYSQL存储过程跟函数的解决方案大法
Paip.断点调试MYSQL存储过程跟函数的解决方案大法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn ...
- Mysql存储过程和函数
Mysql存储过程和函数 基本概念: 创建存储过程和函数是指将经常使用的一组SQL语句的组合在一起,并将这些SQL语句当作一个整体存储在MySQL服务器中.例如,银行经常需要计算用户的利息.不同类别的 ...
- MySql存储过程与函数详解
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...
- mysql 存储过程,函数,触发器
存储过程和函数 mysql> HELP CREATE PROCEDURE; Name: 'CREATE PROCEDURE' Description: Syntax: CREATE [DEFIN ...
- MySql存储过程、函数
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...
- Mysql - 存储过程/自定义函数
在数据库操作中, 尤其是碰到一些复杂一些的系统, 不可避免的, 会用到函数/自定义函数, 或者存储过程. 实际项目中, 自定义函数和存储过程是越少越好, 因为这个东西多了, 也是一个非常难以维护的地方 ...
- MySQL 存储过程和函数
概述 一提到存储过程可能就会引出另一个话题就是存储过程的优缺点,这里也不做讨论,一般别人问我我就这样回答你觉得它好你就用它.因为mysql中存储过程和函数的语法非常接近所以就放在一起,主要区别就是函数 ...
随机推荐
- Python环境搭建-4 pip的安装和使用
pip的安装和使用 我们都知道python有很多的第三方库或者说是模块.这些库针对不同的应用,发挥不同的作用.我们在实际的项目中肯定会用到这些模块.那如何将这些模块导入到自己的项目中呢? Python ...
- 3_02_MSSQL课程_Ado.Net_连接池_连接字符串
连接池技术:是一种对象池技术. 连接对象频繁的开启和关闭操作. innerConnection 先从池子里面拿,如果没有创建新的!!连接池有大小,最大/最小. 提高了连接对象的重用. Asp.ne ...
- Duilib XML嵌套/自定义控件
转载:https://www.jianshu.com/p/0fe8610dcc8d // https://github.com/Washington-DC/Duilib-ListView //这是 ...
- Dubbo 18 问
dubbo是什么 dubbo是一个分布式框架,远程服务调用的分布式框架,其核心部分包含: 集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集 ...
- Number()、parseInt()、parseFloat()、~~、~
一.Number() 如果是Boolean值,true和false值将分别被转换为1和0. 如果是数字值,只是简单的传入和返回. 如果是null值,返回0. 如果是undefined,返回NaN. 如 ...
- activiti 全局流程监听ActivitiEventListener,实现监听不同类型事件,不需要在acitivit中配置任务监听,非常方便
如果我们像给任务配置监听,按照常规的做法是这样的 一个个配置,比较麻烦. 现在利用ActivitiEventListener,监听全局事件,并且可以判断不同的事件类型,进而执行不同的业务逻辑. 1.定 ...
- VS2010如何在同一个解决方案下建立多个项目以及切换运行不同项目
前言: 在编一些小程序时,往往我们不需要一个问题就建立一个解决方案,我们完全可以让多个项目放在同一个解决方案下,切换启动项运行即可.接下来介绍具体的步骤 一.建立空白解决方案以及添加新项目 1.先建立 ...
- sklearn实现决策树算法
1.决策树算法是一种非参数的决策算法,它根据数据的不同特征进行多层次的分类和判断,最终决策出所需要预测的结果.它既可以解决分类算法,也可以解决回归问题,具有很好的解释能力.另外,对于决策树的构建方法具 ...
- ubuntu用命令行打开vscode
1.打开终端 2.输入code即可
- 分享Linux CentOS7 VMware 系统目录结构、 ls命令 、文件类型、alias命令——笔记
一. 系统目录结构 生成目录树结构: tree -a 显示所有 tree -d 仅显示目录 tree -L n n代表数字..表示要显示几层... tree -f 显示完整路径.. yum insta ...