存储过程没有返回值,函数有返回值
存储过程就是一组预先编译好的SQL语句的封装,需要执行时客户端向服务器发送调用请求,服务器就会将这一系列预先存储好的SQL语句全部执行。
简单举例:存储过程的创建
DELIMITER意味将$设置为结束标识,这样就可以在存储过程中使用分号进行分隔了,但注意要在末尾改回来
DELIMITER $
CREATE PROCEDURE select_all_data()
BEGIN
SELECT * FROM employees;
END $
delimiter ;
调用存储过程:
CALL select_all_data();
求平均值的存储过程:
DELIMITER //
CREATE PROCEDURE avg_employee_salary()
BEGIN
SELECT AVG(salary) AS avg_salary FROM employees;
END //
DELIMITER ;
CALL avg_employee_salary();
求最大值的存储过程:
DELIMITER $
CREATE PROCEDURE show_max_salary()
BEGIN
SELECT MAX(salary)
FROM employees;
END $
DELIMITER ;
CALL show_max_salary()
查看最低薪资并将其输出
# 查询工资最低并将其保存到ms变量中并输出
DELIMITER $
CREATE PROCEDURE show_min_salary(OUT ms DOUBLE)
BEGIN
SELECT MIN(salary) INTO ms
FROM employees;
END $
DELIMITER ;
# 调用该函数
CALL show_min_salary(@temp);
# 调用变量
SELECT @temp;
查询某个员工的薪资
# 查询某个员工的薪资(使用IN作为形参传入值)
DELIMITER $
CREATE PROCEDURE show_someone_salary(IN empname VARCHAR(20))
BEGIN
SELECT salary FROM employees WHERE last_name = empname;
END $
DELIMITER ;
# 调用
CALL show_someone_salary('Abel');
# 或者这样调用
SET @empname := 'Abel';
CALL show_someone_salary(@empname);
查询某个员工的薪资,传入员工名称,传出员工薪资
# 查询某个员工的薪资,传入员工名称,传出员工薪资
DELIMITER //
CREATE PROCEDURE show_someone_salary2(IN empname Varchar(20), OUT empsalary DECIMAL(10, 2))
BEGIN
SELECT salary INTO empsalary
FROM employees
WHERE last_name = empname;
END //
DELIMITER ;
# 调用
SET @empname := 'Abel';
CALL show_someone_salary2(@empname, @empsalary);
SELECT @empsalary;
选中员工的领导,并将传入的形参赋值为领导的名称:
# 选中员工的领导,并将传入的形参赋值为领导的名称:
DELIMITER $
CREATE PROCEDURE show_mgr_name(INOUT empname VARCHAR(20))
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;
注意:在存储过程中进行的数据操作,一旦操作逻辑较为复杂时,难以进行排错
存储函数就是指用户自定义的函数,这种函数必定有返回值。
创建一个存储函数用来返回Abel的邮箱
# 暂时改变分隔符
DELIMITER //
# 创建函数
CREATE FUNCTION email_by_name()
# 设置函数的返回值类型
RETURNS VARCHAR(25)
# 函数的一些限制,CONTAINS SQL意味着包含SQL语句,READS SQL DATA代表这是一条读数据,默认情况下这个限制是必须添加的
DETERMINISTIC
CONTAINS SQL
READS SQL DATA
# 真正的函数体
BEGIN
RETURN (SELECT email FROM employees WHERE last_name = 'Abel');
END //
# 将分隔符修改回分号
DELIMITER ;
# 调用函数
SELECT email_by_name();
创建一个存储函数,传入emp_id并查询其email并返回
注意如果不添加函数特征就必须设置全局属性log_bin_trust_function_creators属性为1
# 保证函数的创建必定成功,不需要添加函数的特征(DETERMINISTIC)
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(100);
# 使用变量进行调用
SET @temp1 := 100;
SELECT email_by_id(@temp1);
传入部门id并返回部门的人数
# 创建
DELIMITER //
CREATE FUNCTION count_by_id(dep_id INT)
RETURNS INT
BEGIN
RETURN (
SELECT COUNT(*)
FROM employees
WHERE department_id = dep_id
);
END //
DELIMITER ;
# 调用
SELECT count_by_id(100);
存储过程更倾向于将查询所得到的结果赋值给某个参数,其更适用于更新修改的操作中,其可以有多个赋值操作
存储函数则会将结果作为返回值,其可以更加灵活的运用在各种SQL语句中,其返回值只能为一个,一般用于只有一个结果的查询操作
注意以下信息都可以在控制台界面进行查看,在语句最后直接加’/G’进行查看
# 存储过程的查看创建信息
SHOW CREATE PROCEDURE avg_employee_salary;
# 存储函数的查看创建信息
SHOW CREATE FUNCTION count_by_id;
# 查看其状态信息
SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS LIKE 'avg_employee_salary';
SHOW FUNCTION STATUS LIKE 'count_by_id';
# 所有的存储过程与存储函数都会存储在information_schema.Routines中,对这个表进行查询也可以获取信息
SELECT *
FROM information_schema.Routines
WHERE ROUTINE_NAME = 'email_by_id'
注意存储过程与存储函数在创建好之后就不允许修改函数体,但我们可以对权限、注释等信息进行进一步修改
# 修改存储过程或存储函数的相关信息
ALTER PROCEDURE show_max_salary
SQL SECURITY INVOKER
COMMENT '最高工资'
# 删除
DROP FUNCTION IF EXISTS count_by_id;