mysql的存储过程和函数

一、存储过程

 1.介绍:

·存储过程就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法;

·存储过程跟Oracle触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,但是功能比触发器更加强大,触发器是某件事触发后自动调用;

2.特点:

·有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能;

·函数的普遍特性:模块化,封装,代码复用;

·速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤;

3.优缺点对比:

优点 缺点
1.执行速度:对于复杂的业务逻辑,因为在存储过程创建的时候,数据库已经对其进行了一次解析和优化。存储过程一旦执行,在内存中就会保留一份这个存储过程,这样下次再执行同样的存储过程时,可以从内存中直接调用,所以执行速度会比普通sql快。 1.不可滥用:sql是一门结构化查询语言,不是面向对象的,本质还是过程化的语言,处理复杂的业务逻辑不如面向对象的开发语言,如果全把业务逻辑写在存储过程里,违背了这一原则。
2.减少网络传输:存储过程的数据访问全在数据库服务器里,不需要传输数据到其他服务器。 2.较难迁移:不同的数据库差别大,更换数据库需要重写。
3.可维护性:有些存储过程比程序更好维护,因为可以直接改db的存储过程而不用动程序。 3.不利管理:过多的逻辑不便于维护,不利于分层管理
4.安全性:防止sql注入,当然,sql本身也可以。 4.不支持集群、水平扩展,数据库切割之后存储过程并不能知道数据存储在哪个数据库。
5.可扩展性:应用程序和数据库分离,独立进行,方便维护优化。 5.调试、修改繁琐:如果想要更改存储过程的输入参数或者更改返回的数据,那么相应的应用程序的调用方也要修改参数,更新调用

4.使用总结:

1.对于个别对性能要求高、复杂的业务逻辑,使用存储过程可以提高sql的查询效率。

2.存储过程不应该大范围使用、滥用,要适度使用。

5.入门存储过程:

语法:

CREATE PROCEDURE sp_name ([ proc_parameter ]) [ characteristics..] routine_body 

 proc_parameter指定存储过程的参数列表,列表形式如下:

[IN|OUT|INOUT] param_name type

其中:

·in表示输入参数,调用时指定,过程中修改不可被返回。

·out表示输出参数,可在过程内部被改变,可以返回。

·inout表示既可以输入也可以输出,调用时指定,可改变,可返回。

·param_name表示参数名称。

·type表示参数的类型,该类型可以是MYSQL数据库中的任意类型。

下面新建一个存储过程:

1.首先判断是否有testproce1()这个存储过程,如果有就drop掉。

DROP PROCEDURE IF EXISTS `testproce1`;
2.创建testproce1()存储过程。
DELIMITER //
CREATE DEFINER = `root`@`localhost` PROCEDURE `testproce1`(IN a int ,IN b int ,OUT sum int)
BEGIN
	#Routine body goes here...
	DECLARE c INT;
	if a is NULL then set a=0;
	end IF;
	if b is null then set b=0;
	end IF;
	set sum=a+b;
END //
DELIMITER ;

注意:两个关键字

·DELIMITER:这里DELIMITER其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了。默认情况下,delimiter是分号;。这样做的目的是因为MYSQL默认的语句结束符为分号;因为mysql一遇到分号,它就要自动执行。为了避免与存储过程中SQL语句结束符相冲突,需要使用DELIMITER改变存储过程的结束符,并以“END//”结束存储过程。

·DECLARE:mysql中的DECLARE语句是在复合语句中声明变量的指令。 在过程中定义的变量并不是真正的定义,也就是仅仅是形参。后面可跟DEFAULT 关键字,形如:DECLARE i INT DEFAULT 0;指定变量i的默认值是0。如果没有指定默认值,那么i的默认值为NULL。

执行:

3.执行testproce1()存储过程
set @b=1;
call testproce1(3,@b,@s);
SELECT @s as s;

结果:

6.存储过程中的控制语句

·IF语句,上文代码里就用到了,需要判断时使用,IF 条件THEN 结果 ,结束时使用 END IF结束。

·CASE语句,详见代码:

DROP PROCEDURE IF EXISTS `testproc2`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `testproc2`(IN type int)
BEGIN
	#Routine body goes here...
	DECLARE c VARCHAR(500);
	CASE type
	when 0 then 
	set c='我是0'; 
	when 1 then  
	set c='我是1';
	ELSE
	set c='我是其他';
	END CASE;
	SELECT c ;
END;

执行:

call testproc2(0);

结果:

·while循环语句,详见代码:

DROP PROCEDURE IF EXISTS `testproc3`;

CREATE DEFINER = `root`@`localhost` PROCEDURE `testproc3`(IN n int)
BEGIN
    #Routine body goes here...
    DECLARE i int;
    DECLARE s int;
    SET i = 0;
    SET s = 0;
    WHILE i <= n DO
        set s = s + i;
        set i = i + 1; 
    END WHILE;
    SELECT s; 
END;

执行:

call testproc3(5);

结果:

·LOOP语句,LOOP语句可以使某些特定的语句重复执行,实现一个简单的循环,详见代码示例:

add_num: LOOP  
SET @count=@count+1;  
END LOOP add_num ; 

这是一个死循环。因为LOOP语句本身没有停止循环的语句,必须是遇到LEAVE语句等才能停止循环。

·LEAVE语句,LEAVE语句主要用于跳出循环控制,详见代码示例:

add_num: LOOP 
SET @count=@count+1; 
IF @count=100 THEN 
LEAVE add_num ; 
END LOOP add_num ; 

LEAVE配合LOOP使用即可执行循环,以上代码意思是,循环执行count+1,当count累加到100时,跳出循环。

·ITERATE语句,用于跳出循环控制,详见代码示例:

add_num: LOOP 
SET @count=@count+1; 
IF @count=100 THEN 
LEAVE add_num ; 
ELSE IF MOD(@count,3)=0 THEN 
ITERATE add_num; 
SELECT * FROM employee ; 
END LOOP add_num ;

ITERATE是跳出本次循环,不会执行接下来的语句,而进行下一次循环,LEAVE是直接结束整个循环。二者有本质区别。

·REPEAT语句,REPEAT语句是有条件控制的循环语句。代码如下:

REPEAT 
SET @count=@count+1; 
UNTIL @count=100 
END REPEAT ; 

该示例表示循环执行count加1的操作,count值为100时结束循环。

REPEAT循环都用END REPEAT结束。

7.调用存储过程

MySQL中使用CALL语句来调用存储过程:

call 存储过程名(参数...);

二、函数

1.介绍:mysql自定义函数和mysql内部函数用法是一样的,直接调用。

2.入门:

phone表:

id name count type create_time
1 iphone     5 苹果  2018-12-01 02:19:06
2 huawei     2 华为 2018-12-05 02:19:10
3 oppo     1  OPPO   2018-12-05 02:19:12

创建函数和过程类似,详见代码:

DROP FUNCTION IF EXISTS `testfun2`;

CREATE DEFINER = `root`@`localhost` FUNCTION `testfun2`(`name` varchar(15))
 RETURNS int(11)
BEGIN
	#Routine body goes here...
	
    declare c int;
    select id from phone where type=name into c;
    return c; 

END;

调用:

select * FROM phone where id = testfun2('OPPO');

结果:

三、针对存储过程和函数的操作

1.查看

·使用SHOW STATUS语句查看存储过程和函数的状态

示例:查看testfun1函数的状态

SHOW  FUNCTION STATUS LIKE '%testfun1%'

结果:

可以发现,show status 语句可以查看函数的创建时间、修改时间和字符集等信息。

·使用SHOW CREATE语句查看存储过程和函数的定义

示例:

show CREATE FUNCTION testfun1;

结果:

可以发现:show creat 语句可以查看定义。

·使用SELECT * FROM information_schema.Routines查看函数

SELECT * FROM information_schema.Routines 
WHERE ROUTINE_NAME=' testfun1' ; 

结果:

其中Routines表里的ROUTINE_NAME字段存储的是过程和函数的名称。

2.修改

存储过程和函数的修改只能修改权限,具体过程和函数代码现还不支持修改,要是想修改,只能先drop掉,然后重新编写新的过程和函数。

3.删除

语法:

DROP { PROCEDURE| FUNCTION } sp_name; 

示例:

删除函数testfun1()

DROP FUNCTION testfun1; 

删除过程testproc1()

DROP PROCEDURE testfun1; 

4.PS

存储过程的参数可以使用中文,在定义存储过程的时候加上character set gbk就可以了

示例:

CREATE PROCEDURE useInfo(IN u_name VARCHAR(50) CHARACTER SET gbk,OUT u_age INT)

希望这篇博客可以很好地认识mysql过程和函数,汇集整理了很多大神的博客,如有遗漏,欢迎大家补上~

猜你喜欢

转载自blog.csdn.net/harry5508/article/details/84958751