【SQL】之存储过程与函数
存储过程的英文是
Stored Procedure
。它的思想很简单,就是一组经过预先编译的 SQL 语句的封装。
执行过程:存储过程预先存储在 MySQL 服务器上,需要执行的时候,客户端只需要向服务器端发出调用存储过程的命令,服务器端就可以把预先存储好的这一系列 SQL 语句全部执行。
和视图、函数的对比:
它和视图有着同样的优点,清晰、安全,还可以减少网络传输量。不过它和视图不同, 视图是虚拟表,通常不对底层数据表直接操作,而 存储过程是程序化的 SQL, 可以直接操作底层数据表,相比于面向集合的操作方式,能够实现一些更复杂的数据处理。一旦存储过程被创建出来,使用它就像使用函数一样简单,我们直接通过调用存储过程名即可。相较于函数,存储过程是 没有返回值的。
存储过程
类型1:无参数无返回值
-- 类型1:无参数无返回值
#创建存储过程1
DELIMITER $
CREATE PROCEDURE select_all_data()
BEGIN
SELECT * FROM emps;
END $
DELIMITER;
#存储过程1的调用
CALL select_all_data();
#创建存储过程2
DELIMITER //
CREATE PROCEDURE avg_employee_salary()
BEGIN
SELECT AVG(salary) FROM emps;
END //
DELIMITER;
#调用存储过程2
CALL avg_employee_salary();
#创建存储过程3
DELIMITER //
CREATE PROCEDURE show_max_salary()
BEGIN
SELECT MAX(salary) FROM emps;
END //
DELIMITER;
#调用存储过程3
CALL show_max_salary();
类型2:带out
DESC emps;
DELIMITER //
CREATE PROCEDURE show_min_salary(OUT ms DOUBLE)
BEGIN
SELECT MIN(salary) INTO ms
FROM emps;
END //
DELIMITER;
#调用
CALL show_min_salary(@ms);
#查看此变量值
SELECT @ms;
类型3:带in
#创建存储过程,查看某个员工的薪资,并用in参数empname 输入 员工姓名
DELIMITER //
CREATE PROCEDURE show_someone_salary(IN empname VARCHAR(20))
BEGIN
SELECT salary FROM emps
WHERE last_name=empname;
END //
DELIMITER;
#调用方式1:
CALL show_someone_salary('Abel');
#调用方式2:
SET @empname = 'Abel';
#SET @empname := 'Abel'; 赋值符号 :=
CALL show_someone_salary(@empname);
类型4:带in和out
-- 类型4:带in和out
#创建存储过程,查看emp表的某个员工的薪资,并用in参数empname输入员工姓名,用out参数empsalary输出员工薪资
DELIMITER //
CREATE PROCEDURE show_someone_salary2(IN empname VARCHAR(20),OUT empsalary DECIMAL(10,2))
BEGIN
SELECT salary INTO empsalary FROM emps
WHERE last_name=empname;
END //
DELIMITER;
#调用
SET @empname='Abel';
CALL show_someone_salary2(@empname,@empsalary);
SELECT @empsalary;
类型5:带inout
#创建存储过程,查询某个员工领导的姓名,并用inout参数empname输入员工姓名,
DELIMITER $
CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(25))
BEGIN
SELECT last_name INTO empname
FROM emps
WHERE employee_id=(
SELECT manager_id FROM emps
WHERE last_name=empname
);
END $
DELIMITER;
#调用
SET @empname='Abel';
CALL show_mgr_name(@empname);
SELECT @empname;
存储函数
MySQL支持自定义函数,定义好之后,调用方式与调用MySQL预定义的系统函数一样。
-- 存储函数
#方法1:加上必要的函数特征
#创建存储函数,参数定义为空,查询Abel的email,并返回,数据类型为字符串型。
DELIMITER //
CREATE FUNCTION email_by_name()
RETURNS VARCHAR (25)
DETERMINISTIC
CONTAINS SQL
READS SQL DATA
BEGIN
RETURN (SELECT email FROM emps
WHERE last_name='Abel');
END //
DELIMITER;
#调用1
SELECT email_by_name();
SELECT email,last_name FROM emps
WHERE last_name='Abel';
#方法2:
#创建函数前执行此语句,保证函数创建会成功
SET GLOBAL log_bin_trust_function_creators=1;
#创建存储函数,传入参数emp_id,改函数查询emp_id的email,并返回,数据类型为字符串型
DELIMITER //
CREATE FUNCTION email_by_id(emp_id INT)
RETURNS VARCHAR(25)
BEGIN
RETURN (SELECT email FROM emps WHERE employee_id=emp_id);
END //
DELIMITER;
#调用2
SELECT email_by_id(102);
SET @emp_id :=102;
SELECT email_by_id(@emp_id);
#举例3:
#创建存储函数count_by_id(),参数传入dept_id,该函数查询dept_id部门的员工人数,并返回,数据类型为整型
DELIMITER //
CREATE FUNCTION count_by_id(dept_id INT)
RETURNS INT
BEGIN
RETURN(SELECT COUNT(*) FROM emps WHERE department_id=dept_id);
END //
DELIMITER;
#调用3
SET @dept_id := 50;
SELECT count_by_id(@dept_id);
存储过程和存储函数对比
存储过程一般用于更新,存储函数一般用于查询结果为一个值并返回时。
存储过程调用语法call,存储函数select。
存储过程可以返回0个或多个返回值,存储函数只能是一个。
存储函数可以放在查询语句中使用,存储过程不行。反之,存储过程的功能更加强大,包括能够执行对表的操作(比如创建表,删除表等)和事务操作,这些功能是存储函数不具备的。
存储过程和函数的查看,修改,删除
存储过程,存储函数的查看:
-- 存储过程,存储函数的查看
#1.show create语句查看存储过程和函数的创建信息
SHOW CREATE PROCEDURE show_mgr_name;
SHOW CREATE FUNCTION count_by_id;
#2.SHOW STATUS语句查看存储过程和函数的状态信息
SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS LIKE 'show_max_salary';
#3.从information_schema.Routines表中查看存储过程和函数的信息
SELECT * FROM information_schema.Routines
WHERE ROUTINE_NAME='email_by_id' AND ROUTINE_TYPE = 'FUNCTION'; #function区分大写
#存储过程和存储函数重名时,补routine_type
存储过程,函数的修改
-- 存储过程,函数的修改
#修改存储过程或函数,不影响存储过程或函数功能,只是修改相关特性。使用ALTER语句实现。
ALTER PROCEDURE show_max_salary
SQL SECURITY INVOKER
COMMENT '查询最高工资';
#删除
DROP FUNCTION count_by_id;
DROP PROCEDURE IF EXISTS show_min_salary;