存储过程和函数

存储过程和函数是事先经过编译并存储在数据库中的一段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,造成数据库服务器的压力,

所以存储过程/函数中不要进行大量的复杂运算,应该将这些运算操作分摊到应用服务器上执行.

mysql 存储过程与函数_12 MySQL存储过程与函数相关推荐

  1. mysql 导出函数_mysql导出存储过程或函数

    查询数据库中的存储过程和函数 方法一: select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE' ...

  2. mysql存储过程大于小于_mysql5.0存储过程操作符知识_函数方法[Mysql学习]

    mysql存储过程基本函数 一.字符串类 CHARSET(str) //返回字串字符集 CONCAT (string2  [,... ]) //连接字串 INSTR (string ,substrin ...

  3. mysql 函数 局部变量_MySQL 存储过程 存储函数 局部变量 游标 概念示例

    一个存储过程是一个可编程的函数,它可以在MySQL中创建并保存.它是由一些SQL语句和一些特殊的控制结构语句组成. 当希望在不同的应用程序或平台上执行相同的函数,或者封装特定的功能时,存储过程是一个非 ...

  4. mysql 视图 分页_mysql查看所有存储过程,函数,视图,触发器,表,分页

    查询数据库中的存储过程和函数 方法一: select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE' ...

  5. MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁

    浏览目录: 1.视图 2.触发器 3.存储过程 4.函数 5.事物 6.数据库锁 7.数据库备份 1.视图 视图:是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据 视 ...

  6. mysql函数 游标_存储过程/游标/mysql 函数

    存储过程和函数(存储在 mysql数据库中的 proc表,所以检查有没有这个表) 存储过程是一种存储程序(如正规语言里的子程序一样),mysql支持有两种:存储过程,在其他SQL语句中可以返回值的函数 ...

  7. 【MySQL学习】4、MySQL存储过程和函数

    文章目录 1.存储过程和函数概念 2.存储过程的使用 (1)创建存储过程 (2)调用存储过程 (3)查看存储过程 (4)删除存储过程 3.存储过程的语法 (1)声明变量 (2)if条件判断 (3)传递 ...

  8. MySQL学习笔记(2)——存储过程与存储函数

    MySQL学习笔记(2)--存储过程与存储函数 文章目录 MySQL学习笔记(2)--存储过程与存储函数 一.存储过程 1.概念:预先编译好的sql语句的集合,理解成批处理语句 2.好处: 3.语法: ...

  9. mysql 存储过程 格式化_转 mysql 存储过程初探

    https://www.cnblogs.com/qmfsun/p/4838032.html MySQL命令执行sql文件的两种方法 https://www.cnblogs.com/mark-chan/ ...

最新文章

  1. 将已有项目提交到github/从github上pull到本地
  2. python 少儿趣味编程下载_趣味儿童编程软件(scratch)
  3. 程序员面试金典--第k个数
  4. python中 __name__及__main()__的妙处
  5. express项目创建
  6. 用JavaFX编写图块引擎
  7. 局域网聊天软件源码解析
  8. 变分法和变分贝叶斯推断
  9. 设某微型计算机内存ram区,微机原理第三章习题.doc
  10. python-12:怎么在爬虫代码中伪装header
  11. python教程视频哪个好-Python 基础视频教程那个好?
  12. bzoj 3383: [Usaco2004 Open]Cave Cows 4 洞穴里的牛之四(set+BFS)
  13. spark sql常用方法
  14. springsecurity安全登录框架
  15. Tracup丨什么是甘特图?关于甘特图的百科全书
  16. 打通最后100米:苏宁小店如何成为家门口的“共享冰箱”
  17. bootstrap datepicker 在bootstrap modal中不显示问题
  18. 服装尺寸 html,国家标准规范服装尺寸表.doc
  19. 华为MA5300配置RADIUS认证
  20. ajax localhsot,ajax请求nodejs后台,开启服务器后,localhost:3000/index.html页面既没有报错,也没有文字。。。...

热门文章

  1. 使用yeoman搭建脚手架并发布到npm
  2. 【PHP 每日函数】第 03 周期
  3. 如何用纯 CSS 创作一个方块旋转动画
  4. 聊聊rocketmq的RemotingException
  5. spring+kafka消费者的2种配置方式
  6. Single Number II
  7. MonoBehaviour生命周期
  8. C#使用Xamarin开发可移植移动应用(1.入门与Xamarin.Forms页面),附源码
  9. 代码组(1) 对代码组的管理
  10. Neutron 物理部署方案 - 每天5分钟玩转 OpenStack(68)