#第十六章、练习题 #一、变量 #0、准备工作 CREATE DATABASE test16_var_cur; use test16_var_cur; CREATE TABLE employees AS SELECT * FROM atguigudb.`employees`; CREATE TABLE departments AS SELECT * FROM atguigudb.`departments`; ############################################################################ #无参有返回 #1. 创建函数get_count(),返回公司的员工个数 SET GLOBAL log_bin_trust_function_creators = 1; DELIMITER // CREATE FUNCTION get_count() RETURNS INT BEGIN #声明变量 DECLARE emp_count INT; #赋值 SELECT COUNT(*) INTO emp_count FROM employees; RETURN emp_count; END // DELIMITER ; #调用 SELECT get_count(); ############################################################################ #有参有返回 #2. 创建函数ename_salary(),根据员工姓名,返回它的工资 DELIMITER // CREATE FUNCTION ename_salary(emp_name VARCHAR(15)) RETURNS DOUBLE BEGIN #声明变量 SET @sal = 0; #相当于定义了会话用户变量 #赋值 SELECT salary INTO @sal FROM employees WHERE last_name = emp_name; RETURN @sal; END // DELIMITER ; #调用 SET @emp_name := 'Abel'; SELECT ename_salary(@emp_name); #或 SELECT ename_salary('Abel'); SELECT @sal; #由于定义的是会话用户变量,所以这条语句也可以执行 ############################################################################ #3. 创建函数dept_sal() ,根据部门名,返回该部门的平均工资 DELIMITER // CREATE FUNCTION dept_sal(dept_name VARCHAR(25)) RETURNS DOUBLE BEGIN #声明变量 DECLARE avg_sal DOUBLE; SELECT AVG(salary) INTO avg_sal FROM employees e JOIN departments d ON e.department_id = d.department_id WHERE d.department_name = dept_name; RETURN avg_sal; END // DELIMITER ; #调用 SELECT dept_sal('Marketing'); ############################################################################ #4. 创建函数add_float(),实现传入两个float,返回二者之和 DELIMITER // CREATE FUNCTION add_float(value1 FLOAT,value2 FLOAT) RETURNS FLOAT BEGIN #声明变量 DECLARE sum_val FLOAT; SET sum_val = value1 + value2; RETURN sum_val; END // DELIMITER ; #调用 SELECT add_float(1.2,2.3); ############################################################################ #二. 流程控制 #1. 创建函数test_if_case(),实现传入成绩,如果成绩>90,返回A,如果成绩>80,返回B,如果成绩>60,返回C,否则返回D #要求:分别使用if结构和case结构实现 #方式一:使用IF DELIMITER // CREATE FUNCTION test_if_case1(score DOUBLE) RETURNS CHAR BEGIN #声明变量 DECLARE score_level CHAR; IF score > 90 THEN SET score_level = 'A'; ELSEIF score > 80 THEN SET score_level = 'B'; ELSEIF score > 60 THEN SET score_level = 'C'; ELSE SET score_level = 'D'; END IF; RETURN score_level; END // DELIMITER ; #调用 SELECT test_if_case1(85); #方式二:使用CASE DELIMITER // CREATE FUNCTION test_if_case2(score INT) RETURNS CHAR BEGIN #定义变量 DECLARE score_level CHAR; CASE WHEN score > 90 THEN SET score_level = 'A'; WHEN score > 80 THEN SET score_level = 'B'; WHEN score > 60 THEN SET score_level = 'C'; ELSE SET score_level = 'D'; END CASE; RETURN score_level; END // DELIMITER ; #调用 SELECT test_if_case2(96); ############################################################################ #2. 创建存储过程test_if_pro(),传入工资值,如果工资值<3000,则删除工资为此值的员工,如果3000 <= 工资值 <= 5000,则修改此工资值的员工薪资涨1000,否则涨工资500 DELIMITER $ CREATE PROCEDURE test_if_pro(IN emp_sal DOUBLE) BEGIN IF emp_sal < 3000 THEN DELETE FROM employees WHERE salary = emp_sal; ELSEIF emp_sal <= 5000 THEN UPDATE employees SET salary = salary + 1000 WHERE salary = emp_sal; ELSE UPDATE employees SET salary = salary + 500 WHERE salary = emp_sal; END IF; END $ DELIMITER ; #调用 CALL test_if_pro(2900); SELECT *FROM employees; ############################################################################ #3. 创建存储过程insert_data(),传入参数为 IN 的 INT 类型变量 insert_count,实现向admin表中批量插入insert_count条记录 CREATE TABLE admin( id INT PRIMARY KEY AUTO_INCREMENT, user_name VARCHAR(25) NOT NULL, user_pwd VARCHAR(35) NOT NULL ); SELECT * FROM admin; DELIMITER // CREATE PROCEDURE insert_data(IN insert_count INT) BEGIN #声明变量 DECLARE init_count INT DEFAULT 1; #①初始化条件 WHILE init_count <= insert_count DO #②循环条件 #③循环体 INSERT INTO admin(user_name,user_pwd) VALUES(CONCAT('atguigu-',init_count),ROUND(RAND()*1000000)); #④迭代条件 SET init_count = init_count + 1; END WHILE; END // DELIMITER ; #调用 CALL insert_data(100); SELECT * FROM admin; ############################################################################ #三. 游标的使用 /*创建存储过程update_salary(),参数1为 IN 的INT型变量dept_id,表示部门id;参数2为 IN的INT型变量change_sal_count,表示要调整薪资的员工个数。查询指定id部门的员工信息,按照salary升序排列,根据hire_date的情况,调整前change_sal_count个员工的薪资,详情如下。 hire_date salary hire_date < 1995 salary = salary * 1.2 hire_date >=1995 AND hire_date <= 1998 salary = salary * 1.15 hire_date >1998 AND hire_date <= 2001 salary = salary * 1.10 hire_date > 2001 salary = salary * 1.05 */ DELIMITER $ CREATE PROCEDURE update_salary(IN dept_id INT,IN change_sal_count INT) BEGIN #声明变量 DECLARE emp_id INT; #记录员工id DECLARE emp_hire_date DATE; #记录员工入职时间 DECLARE init_count INT DEFAULT 1; #用于表示循环结构的初始化条件 DECLARE add_sal_rate DOUBLE; #记录涨薪的比例 #声明游标 DECLARE emp_cursor CURSOR FOR SELECT employee_id,hire_date FROM employees WHERE department_id = dept_id ORDER BY salary ASC; #打开游标 OPEN emp_cursor; WHILE init_count <= change_sal_count DO #使用游标 FETCH emp_cursor INTO emp_id,emp_hire_date; #获取涨薪的比例 IF (YEAR(emp_hire_date) < 1995) THEN SET add_sal_rate = 1.2; ELSEIF (YEAR(emp_hire_date) <= 1998) THEN SET add_sal_rate = 1.15; ELSEIF (YEAR(emp_hire_date) <= 2001) THEN SET add_sal_rate = 1.10; ELSE SET add_sal_rate = 1.05; END IF; #涨薪 UPDATE employees SET salary = salary * add_sal_rate WHERE employee_id = emp_id; #迭代条件的更新 SET init_count = init_count + 1; END WHILE; #关闭游标 CLOSE emp_cursor; END $ DELIMITER ; #调用 CALL update_salary(50,3); SELECT employee_id,hire_date,salary FROM employees WHERE department_id = 50 ORDER BY salary ASC;