#第十五章、存储过程与函数

#0、准备工作
CREATE DATABASE DBTEST15;

USE dbtest15;

#复制员工表
CREATE TABLE employees
AS
SELECT *
FROM atguigudb.employees;

#复制部门表
CREATE TABLE departments
AS
SELECT *
FROM atguigudb.departments;

SELECT * FROM employees;

SELECT * FROM departments;

#1、创建存储过程

#类型1：无参数无返回值

#举例1：创建存储过程select_all_data()，查看employees表的所有数据

DELIMITER $

CREATE PROCEDURE select_all_data()
BEGIN
	SELECT * FROM employees;
END $

DELIMITER ;

#2、存储过程的调用

CALL select_all_data();

#例2：创建存储过程avg_employee_salary()，返回所有员工的平均工资

DELIMITER //

CREATE PROCEDURE avg_employee_salary()
BEGIN
		SELECT AVG(salary)
		FROM employees;
END //

DELIMITER ;

#调用
CALL avg_employee_salary();

#举例3：创建存储过程show_max_salary()，用来查看“employees”表的最高薪资值。

DELIMITER $

CREATE PROCEDURE show_max_salary()
BEGIN
		SELECT MAX(salary)
		FROM employees;
END $

DELIMITER ;

#调用
CALL show_max_salary();

#类型2：带OUT
#举例4：创建存储过程show_min_salary()，查看“employees”表的最低薪资值。并将最低薪资通过OUT参数“ms”输出

DESC employees;

DELIMITER //

CREATE PROCEDURE show_min_salary(OUT ms DOUBLE)
BEGIN
		SELECT MIN(salary) INTO ms
		FROM employees;
END //

DELIMITER ;

#调用
CALL show_min_salary(@ms);

#查看变量值
SELECT @ms;

#类型3：带IN
#举例5：创建存储过程show_someone_salary()，查看“employees”表的某个员工的薪资，并用IN参数empname输入员工姓名。

DELIMITER //

CREATE PROCEDURE show_someone_salary(IN empname VARCHAR(25))
BEGIN
		SELECT salary FROM employees
		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
#举例6：创建存储过程show_someone_salary2()，查看“employees”表的某个员工的薪资，并用IN参数empname输入员工姓名，用OUT参数empsalary输出员工薪资。

DELIMITER //

CREATE PROCEDURE show_someone_salary2(IN empname VARCHAR(25),OUT empsalary DOUBLE)
BEGIN
		SELECT salary INTO empsalary
		FROM employees
		WHERE last_name = empname;
END //

DELIMITER ;

#调用
SET @empname = 'Abel';
CALL show_someone_salary2(@empname,@empsalary)

SELECT @empsalary;

#类型5：带INOUT
#举例7：创建存储过程show_mgr_name()，查询某个员工领导的姓名，并用INOUT参数“empname”输入员工姓名，输出领导的姓名。

DELIMITER $

CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(25))
BEGIN
		SELECT last_name INTO empname
		FROM employees
		WHERE employee_id = (
												SELECT manager_id
												FROM employees
												WHERE last_name = empname
												);
END $

DELIMITER ;

#调用
SET @empname := 'Abel';
CALL show_mgr_name(@empname);
SELECT @empname;

#2、存储函数
#举例1：创建存储函数，名称为email_by_name()，参数定义为空，该函数查询Abel的email，并返回，数据类型为字符串型。

DELIMITER //

CREATE FUNCTION email_by_name()
RETURNS VARCHAR(25)
				DETERMINISTIC
				CONTAINS SQL
				READS SQL DATA
BEGIN
		RETURN (SELECT email FROM employees WHERE last_name = 'Abel');
END //

DELIMITER ;

#调用
SELECT email_by_name();

#举例2：创建存储函数，名称为email_by_id()，参数传入emp_id，该函数查询emp_id的email，并返回，数据类型为字符串型。

#创建函数前执行此语句，保证函数的创建会成功
SET GLOBAL log_bin_trust_function_creators = 1;

#声明函数
DELIMITER //

CREATE FUNCTION email_by_id(emp_id INT)
RETURNS VARCHAR(25)
BEGIN
		RETURN (SELECT email FROM employees WHERE employee_id = emp_id);
END //

DELIMITER ;

#调用方式一
SELECT email_by_id(101);

#调用方式二
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 employees WHERE department_id = dept_id);
END //

DELIMITER ;

#调用
SET @dept_id := 50;
SELECT count_by_id(@dept_id);

#3、存储过程、存储函数的查看

#方式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';

SHOW FUNCTION STATUS LIKE 'email_by_id';

#方式3、从information_schema.Routines表中查看存储过程和函数的信息

SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'email_by_id';

SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'email_by_id' AND ROUTINE_TYPE = 'FUNCTION';

SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = 'show_min_salary' AND ROUTINE_TYPE = 'PROCEDURE';

#4、存储过程、函数的修改
ALTER PROCEDURE show_max_salary
SQL SECURITY INVOKER
COMMENT '查询最高工资';

#5、存储过程、函数的删除

DROP FUNCTION IF EXISTS count_by_id;

DROP PROCEDURE IF EXISTS show_min_salary;






















