第十五章-存储过程与函数+课后练习

#创建数据库和表

CREATE DATABASE dbtest5;
USE dbtest5;
CREATE TABLE employees
AS
SELECT *FROM atguigudb.employees
CREATE TABLE departments
AS
SELECT *FROM atguigudb.departments;

#1.创建存储过程
#类型一 : 无参数无返回值DELIMITER 指定字符为结束标记因为 存储过程体中要含有分号结尾,所以先设定其他的
#举例1:创建存储过程select_all_data() 查看 employees 表的所有数据

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

#2存储过程的调用CALL select_all_date();
#举例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(),用来查看“emps”表的最高薪资值。

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

#调用
CALL show_max_salary();

#类型二 : 无参数有返回值(OUT)
#举例4:创建存储过程show_min_salary(),查看“emps”表的最低薪资值。并将最低薪资通过OUT参数“ms”输出

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;

#类型三 有参数无返回值 (IN)
#举例5:创建存储过程show_someone_salary(),查看“emps”表的某个员工的薪资,并用IN参数empname输入员工姓名。

DELIMITER //
CREATE PROCEDURE show_someone_salary(IN empname VARCHAR(20))
BEGIN    
     SELECT salary FROM employees    WHERE last_name = empname;
END //
DELIMITER ;
#调用方式1
CALL show_someone_salary('Abel');
#调用方式2
SET @empname = 'Abel';
CALL show_someone_salary(@empname);

#类型四 有参数有返回值 (IN OUT)
#举例6:创建存储过程show_someone_salary2(),查看“emps”表的某个员工的薪资,
并用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 employees    
    WHERE last_name = empname;
END //
DELIMITER ;
#调用
SET @empname = 'Abel';
CALL show_someone_salary2('Abel',@empsalary);
SELECT @empsalary;

#类型五 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 //
DELIMIT#aaDROP PROCEDURE show_mgr_name;
#调用
SET @empname = 'Abel';
CALL show_mgr_name(@empname);
SELECT @empname;

#2.1存储函数
#若在创建存储函数中报错“ you might want to use the less safe log_bin_trust_function_creators variable ”,
#有两种处理方法:
#方式1:加上必要的函数特性“[NOT] DETERMINISTIC”和“{CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA}”
#方式2:
SET GLOBAL log_bin_trust_function_creators = 1;
#举例1:创建存储函数,名称为email_by_name(),参数定义为空,该函数查询Abel的email,并返回,数据类型为字符串型。

DELIMITER //
CREATE FUNCTION email_by_name()RETURNS VARCHAR(25)
#需要加上一些条件    
DETERMINISTIC    
CONTAINS SQL    
READS SQL DATABEGIN    
RETURN(
       SELECT email 
       FROM employees 
       WHERE last_name = 'Abel');
END //
DELIMITER ;
#调用
SELECT email_by_name();
SELECT * FROM employees;
SELECT email,last_name
FROM employees
WHERE last_name = 'Abel';

#举例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);

#对比 PROCEDURE 和 FUNCTION
#存储函数可以放在查询语句中使用,存储过程不行。
存储过程 PROCEDURE CALL存储过程() 理解为有0个或多个 一般用于更新存储函数 FUNCTION SELECT 函数() 只能是一个 一般用于查询结果为一个值并返回时

#3 存储过程和函数的查看
#3.1 使用 SHOW CREATE 语句查看存储过程和函数的创建信息

SHOW CREATE PROCEDURE show_mgr_name;
SHOW CREATE FUNCTION count_by_id;

#3.2 使用SHOW STATUS 语句查看存储过程和函数的状态信息会显示全部的内容,包含其他表
SHOW PROCEDURE STATUS;
#可以使用 LIKE 来获取自己想要输出的表

SHOW PROCEDURE STATUS LIKE 'show_%';
SHOW FUNCTION STATUS LIKE 'count_by%';

#3.3 从information_schema.Routines表中查看存储过程和函数的信息
#routine_type后必须为大写

SELECT * FROM information_schema.Routines
WHERE routine_name='email_by_id' 
AND routine_type = 'FUNCTION';

#4 存储过程和函数修改#修改存储过程或函数,不影响存储过程或函数功能,只是修改相关特性。使用ALTER语句实现。
#SQL SECURITY { DEFINER | INVOKER } ,指明谁有权限来执行。
#DEFINER ,表示只有定义者自己才能够执行。
#INVOKER ,表示调用者可以执行。
#COMMENT ‘string’ ,表示注释信息。

ALTER PROCEDURE show_max_salary
SQL SECURITY INVOKERCOMMENT '查询最高工资';

#4 存储过程和函数删除

DROP PROCEDURE IF EXISTS show_by_id();
DROP FUNCTION IF EXISTS count_by_id();

课后练习

存储过程

#0.准备工作

CREATE DATABASE test15_pro_func;USE test15_pro_func;

#1. 创建存储过程insert_user(),实现传入用户名和密码,插入到admin表中

CREATE TABLE ADMIN(
      id INT PRIMARY KEY AUTO_INCREMENT,
      user_name VARCHAR(15) NOT NULL,
      pwd VARCHAR(25) NOT NULL);

DELIMITER //
CREATE PROCEDURE insert_user(
        IN user_name VARCHAR(15),
        IN pwd VARCHAR(25))
BEGIN    
        INSERT INTO `admin`(user_name,pwd)
        VALUES(user_name,pwd);
END //
DELIMITER ;
#调用
CALL insert_user('Tom','ABC123');
SELECT * FROM ADMIN;

#2. 创建存储过程get_phone(),实现传入女神编号,返回女神姓名和女神电话

CREATE TABLE beauty(
         id INT PRIMARY KEY 
         AUTO_INCREMENT,
         NAME VARCHAR(15) NOT NULL,
         phone VARCHAR(15) UNIQUE,
         birth DATE);

INSERT INTO beauty(NAME,phone,birth)
VALUES 
('朱茵','13201233453','1982-02-12'),    
('孙燕姿','13501233653','1980-12-09'),   
('田馥甄','13651238755','1983-08-21'),    
('邓紫棋','17843283452','1991-11-12'),    
('刘若英','18635575464','1989-05-18'),    
('杨超越','13761238755','1994-05-11');

DELIMITER //
CREATE PROCEDURE get_phone(
        IN id INT,
        OUT NAME VARCHAR(15),
        OUT phone VARCHAR(15))
BEGIN    
        SELECT b.name,b.phone INTO NAME,phone    
        FROM beauty b    
        WHERE b.id = id;
END //
DELIMITER ;    
    
#调用
CALL get_phone(1,@name,@phone);
SELECT @name,@phone;    
SELECT * FROM beauty;

#3. 创建存储过程date_diff(),实现传入两个女神生日,返回日期间隔大小

DELIMITER //
CREATE PROCEDURE date_diff(
      IN date_u1 DATE,
      IN date_u2 DATE,
      OUT u1_u2 INT)
BEGIN    
      SELECT DATEDIFF(date_u1,date_u2) 
      INTO u1_u2;
END //
DELIMITER ;

DROP PROCEDURE date_diff;
#调用
SET @date_u1 =  '2001-04-21';
SET @date_u2 =  '2001-04-22';
CALL date_diff(@date_u2,@date_u1,@u1_u2);
SELECT @u1_u2;

#4. 创建存储过程format_date(),实现传入一个日期,格式化成xx年xx月xx日并返回

DELIMITER //
CREATE PROCEDURE fromat_date(
        IN date_u1 DATE, 
        OUT date_u2 VARCHAR(25))
BEGIN   
     SELECT DATE_FORMAT(date_u1,'%y年%m月%d日') 
     INTO date_u2;
END //
DELIMITER ;

#调用
SET @date_u1 = '2001-04-21';
CALL fromat_date(@date_u1,@date_u2);
SELECT @date_u2;

#5. 创建存储过程beauty_limit(),根据传入的起始索引和条目数,查询女神表的记录 #创建带inout模式参数的存储过程

DELIMITER //
CREATE PROCEDURE beauty_limit(
       IN index_1 INT,
       IN sum_1 INT)
BEGIN    
       SELECT * FROM beauty 
       LIMIT index_1,sum_1;
END //
DELIMITER ;

#调用
SET @index_1 = 2;
SET @sum_1 = 4;
CALL beauty_limit(@index_1,@sum_1);

#6. 传入a和b两个值,最终a和b都翻倍并返回

DELIMITER //
CREATE PROCEDURE b_a(
       INOUT a INT ,
       INOUT b INT)
BEGIN    
       SET a = a * 2;
       SET b = b * 2;
END //
DELIMITER ;

#调用
SET @a = 2;
SET @b = 4;
CALL b_a(@a,@b);
SELECT @a,@b;

#7. 删除题目的存储过程

DROP PROCEDURE IF EXISTS beauty_limit;

#8. 查看题目中存储过程的信息

SHOW CREATE PROCEDURE b_a;
SHOW PROCEDURE STATUS;
SHOW PROCEDURE STATUS LIKE 'b%';
SELECT * FROM information_schema.Routines
WHERE routine_name='b-a' 
AND routine_type = 'PROCEDURE';

#存储函数
#0. 准备工作

USE test15_pro_func;
CREATE TABLE employees
AS
SELECT *FROM atguigudb.`employees`;

CREATE TABLE departments
AS
SELECT *FROM atguigudb.`departments`;

#无参有返回
SET GLOBAL log_bin_trust_function_creators = 1;
#1. 创建函数get_count(),返回公司的员工个数 #有参有返回

DELIMITER //
CREATE FUNCTION get_count()RETURNS INT
BEGIN   
    RETURN(SELECT COUNT(*) FROM employees);
END //
DELIMITER ;

#调用
SELECT get_count();

#2. 创建函数ename_salary(),根据员工姓名,返回它的工资

DELIMITER //
CREATE FUNCTION ename_salary(lname VARCHAR(25))RETURNS DOUBLE
BEGIN
    RETURN(
          SELECT salary
          FROM employees 
          WHERE last_name = lname);
END //
DELIMITER ;

#调用
SET @lname = 'Abel';
SELECT ename_salary(@lname);

#3. 创建函数dept_sal() ,根据部门名,返回该部门的平均工资

DELIMITER //
CREATE FUNCTION dept_sal(dept_id INT)RETURNS DOUBLE
BEGIN
    RETURN(SELECT AVG(salary) 
    FROM employees 
    WHERE department_id = dept_id 
    GROUP BY department_id);
END //
DELIMITER ;

DROP FUNCTION dept_sal;

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

#4. 创建函数add_float(),实现传入两个float,返回二者之和

DELIMITER //
CREATE FUNCTION add_float(
       float_1 FLOAT(10,2),
       float_2 FLOAT(10,2))
       RETURNS FLOAT(10,2)
BEGIN         
       RETURN(SELECT float_1 + float_2 );
END //
DELIMITER ;

DROP FUNCTION add_float;

#调用
SET @float_1 = 534654.4564654;
SET @float_2 = 231453.4687;
SELECT add_float(@float_1,@float_2);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值