一、存储过程
1、定义:一组为了完成特定功能的SQL语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来调用存储过程
2、好处:
(1) 重复使用。存储过程可以重复使用,从而可以减少数据库开发人员的工作量。
(2) 提高性能。存储过程在创建的时候就进行了编译,将来使用的时候不用再重新编译。一般的SQL语句每执行一次就需要编译一次,所以使用存储过程提高了效率。
(3) 减少网络流量。存储过程位于服务器上,调用的时候只需要传递存储过程的名称以及参数就可以了,因此降低了网络传输的数据量。
(4 )安全性。参数化的存储过程可以防止SQL注入式的攻击,而且可以将Grant、Deny以及Revoke权限应用于存储过程
3、创建语法
CREATE PROCEDURE 存储过程名(参数列表)
BEGIN
存储过程体(一组合法的SQL语句)
END
注意点:
1)参数列表包含三部分:参数模式 参数名 参数类型,举例:in stuname varchar(20)
2)参数模式:
in:该参数可以作为输入,也就是该参数需要调用方传入值
out:该参数可以作为输出,也就是该参数可以作为返回值
inout:该参数既可以作为输入又可以作为输出,也就是该参数既需要传入值,又可以返回值
3)如果存储过程体仅仅只有一句话,begin end可以省略,存储过程体中的每条sql语句的结尾要求必须加分号。
4)存储过程的结尾可以使用 delimiter 重新设置。语法:delimiter 结束标记,案例:delimiter $
4、调用语法:CALL 存储过程名(实参列表);
1)空参列表
#案例1:插入到admin表中五条记录
DELIMITER $ CREATE PROCEDURE myp1() BEGIN INSERT INTO admin(username,`password`) VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000'); END $ #调用 CALL myp1()$
2)创建带in模式参数的存储过程
#案例2:创建存储过程实现,用户是否登录成功
CREATE PROCEDURE myp4(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
DECLARE result INT DEFAULT 0;#声明并初始化
SELECT COUNT(*) INTO result#赋值
FROM admin
WHERE admin.username = username
AND admin.password = PASSWORD;
SELECT IF(result>0,'成功','失败');#使用
END $
#调用
CALL myp3('张飞','8888')$
3)创建out 模式参数的存储过程
#案例3:根据输入的女神名,返回对应的男神名和魅力值 CREATE PROCEDURE myp7(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT) BEGIN SELECT boys.boyname ,boys.usercp INTO boyname,usercp FROM boys RIGHT JOIN beauty b ON b.boyfriend_id = boys.id WHERE b.name=beautyName ; END $ #调用 CALL myp7('小昭',@name,@cp)$ SELECT @name,@cp$
4)创建带inout模式参数的存储过程
#案例4:传入a和b两个值,最终a和b都翻倍并返回 CREATE PROCEDURE myp8(INOUT a INT ,INOUT b INT) BEGIN SET a=a*2; SET b=b*2; END $ #调用 SET @m=10$ SET @n=20$ CALL myp8(@m,@n)$ SELECT @m,@n$
5、删除存储过程
#语法:drop procedure 存储过程名
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;#× 同时只能删除一个存储过程
6、查看存储过程的信息
DESC myp2;×
SHOW CREATE PROCEDURE 存储过程名称;
7、案例讲解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #一、创建存储过程实现传入用户名和密码,插入到admin表中 2 3 CREATE PROCEDURE test_pro1(IN username VARCHAR(20),IN loginPwd VARCHAR(20)) 4 BEGIN 5 INSERT INTO admin(admin.username,PASSWORD) 6 VALUES(username,loginpwd); 7 END $ 8 9 #二、创建存储过程实现传入女神编号,返回女神名称和女神电话 10 11 CREATE PROCEDURE test_pro2(IN id INT,OUT NAME VARCHAR(20),OUT phone VARCHAR(20)) 12 13 BEGIN 14 SELECT b.name ,b.phone INTO NAME,phone 15 FROM beauty b 16 WHERE b.id = id; 17 18 END $ 19 #三、创建存储存储过程或函数实现传入两个女神生日,返回大小 20 21 CREATE PROCEDURE test_pro3(IN birth1 DATETIME,IN birth2 DATETIME,OUT result INT) 22 BEGIN 23 SELECT DATEDIFF(birth1,birth2) INTO result; 24 END $ 25 #四、创建存储过程或函数实现传入一个日期,格式化成xx年xx月xx日并返回 26 CREATE PROCEDURE test_pro4(IN mydate DATETIME,OUT strDate VARCHAR(50)) 27 BEGIN 28 SELECT DATE_FORMAT(mydate,'%y年%m月%d日') INTO strDate; 29 END $ 30 31 CALL test_pro4(NOW(),@str)$ 32 SELECT @str $ 33 34 #五、创建存储过程或函数实现传入女神名称,返回:女神 and 男神 格式的字符串 35 如 传入 :小昭 36 返回: 小昭 AND 张无忌 37 DROP PROCEDURE test_pro5 $ 38 CREATE PROCEDURE test_pro5(IN beautyName VARCHAR(20),OUT str VARCHAR(50)) 39 BEGIN 40 SELECT CONCAT(beautyName,' and ',IFNULL(boyName,'null')) INTO str 41 FROM boys bo 42 RIGHT JOIN beauty b ON b.boyfriend_id = bo.id 43 WHERE b.name=beautyName; 44 END $ 45 46 CALL test_pro5('柳岩',@str)$ 47 SELECT @str $ 48 49 #六、创建存储过程或函数,根据传入的条目数和起始索引,查询beauty表的记录 50 DROP PROCEDURE test_pro6$ 51 CREATE PROCEDURE test_pro6(IN startIndex INT,IN size INT) 52 BEGIN 53 SELECT * FROM beauty LIMIT startIndex,size; 54 END $ 55 56 CALL test_pro6(3,5)$
二、自定义函数
1、定义:自定义函数是一种与存储过程十分相似的过程式数据库对象。它与存储过程一样,都是由SQL语句和过程式语句组成的代码片段,并且可以被应用程序和其他SQL语句调用。
2、自定义函数与存储过程的区别:
1)自定义函数不能拥有输出参数,这是因为自定义函数自身就是输出参数;而存储过程可以拥有输出参数。
2)自定义函数中必须包含一条 RETURN 语句,而这条特殊的 SQL 语句不允许包含于存储过程中。
3)可以直接对自定义函数进行调用而不需要使用 CALL 语句,而对存储过程的调用需要使用 CALL 语句。
4)函数只会返回一个值,不允许返回一个结果集。函数强调返回值,所以函数不允许返回多个值的情况,即使是查询语句。
关键字 | 调用语法 | 返回值 | 应用场景 | |
函数 | FUNCTION | SELECT 函数() | 只能是一个 | 一般用于查询结果为一个值并返回时,当有返回值而且仅仅一个 |
存储过程 | PROCEDURE | CALL 存储过程() | 可以有0个或多个 | 一般用于更新 |
3、创建语法
CREATE FUNCTION 函数名(参数列表) RETURNS 返回类型
BEGIN
函数体
END
注意点:
1)参数列表 包含两部分:参数名 参数类型
2)函数体:肯定会有return语句,如果没有会报错;如果return语句没有放在函数体的最后也不报错,但不建议;return 值;
3)函数体中仅有一句话,则可以省略begin end
4)使用 delimiter语句设置结束标记
4、调用语法
1)无参有返回
#案例1:返回公司的员工个数 CREATE FUNCTION myf1() RETURNS INT BEGIN DECLARE c INT DEFAULT 0;#定义局部变量 SELECT COUNT(*) INTO c#赋值 FROM employees; RETURN c; END $ SELECT myf1()$
2)有参有返回
#案例2:根据员工名,返回它的工资 CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE BEGIN SET @sal=0;#定义用户变量 SELECT salary INTO @sal #赋值 FROM employees WHERE last_name = empName; RETURN @sal; END $ SELECT myf2('k_ing') $
#案例3:根据部门名,返回该部门的平均工资 CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE BEGIN DECLARE sal DOUBLE ; SELECT AVG(salary) INTO sal FROM employees e JOIN departments d ON e.department_id = d.department_id WHERE d.department_name=deptName; RETURN sal; END $ SELECT myf3('IT')$
5、查看函数
SHOW CREATE FUNCTION myf3;
6、删除函数
DROP FUNCTION myf3;
7、案例
#一、创建函数,实现传入两个float,返回二者之和 CREATE FUNCTION test_fun1(num1 FLOAT,num2 FLOAT) RETURNS FLOAT BEGIN DECLARE SUM FLOAT DEFAULT 0; SET SUM=num1+num2; RETURN SUM; END $ SELECT test_fun1(1,2)$