第十六章、练习题.sql 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #第十六章、练习题
  2. #一、变量
  3. #0、准备工作
  4. CREATE DATABASE test16_var_cur;
  5. use test16_var_cur;
  6. CREATE TABLE employees
  7. AS
  8. SELECT * FROM atguigudb.`employees`;
  9. CREATE TABLE departments
  10. AS
  11. SELECT * FROM atguigudb.`departments`;
  12. ############################################################################
  13. #无参有返回
  14. #1. 创建函数get_count(),返回公司的员工个数
  15. SET GLOBAL log_bin_trust_function_creators = 1;
  16. DELIMITER //
  17. CREATE FUNCTION get_count()
  18. RETURNS INT
  19. BEGIN
  20. #声明变量
  21. DECLARE emp_count INT;
  22. #赋值
  23. SELECT COUNT(*) INTO emp_count FROM employees;
  24. RETURN emp_count;
  25. END //
  26. DELIMITER ;
  27. #调用
  28. SELECT get_count();
  29. ############################################################################
  30. #有参有返回
  31. #2. 创建函数ename_salary(),根据员工姓名,返回它的工资
  32. DELIMITER //
  33. CREATE FUNCTION ename_salary(emp_name VARCHAR(15))
  34. RETURNS DOUBLE
  35. BEGIN
  36. #声明变量
  37. SET @sal = 0; #相当于定义了会话用户变量
  38. #赋值
  39. SELECT salary INTO @sal FROM employees WHERE last_name = emp_name;
  40. RETURN @sal;
  41. END //
  42. DELIMITER ;
  43. #调用
  44. SET @emp_name := 'Abel';
  45. SELECT ename_salary(@emp_name);
  46. #或
  47. SELECT ename_salary('Abel');
  48. SELECT @sal; #由于定义的是会话用户变量,所以这条语句也可以执行
  49. ############################################################################
  50. #3. 创建函数dept_sal() ,根据部门名,返回该部门的平均工资
  51. DELIMITER //
  52. CREATE FUNCTION dept_sal(dept_name VARCHAR(25))
  53. RETURNS DOUBLE
  54. BEGIN
  55. #声明变量
  56. DECLARE avg_sal DOUBLE;
  57. SELECT AVG(salary) INTO avg_sal
  58. FROM employees e JOIN departments d
  59. ON e.department_id = d.department_id
  60. WHERE d.department_name = dept_name;
  61. RETURN avg_sal;
  62. END //
  63. DELIMITER ;
  64. #调用
  65. SELECT dept_sal('Marketing');
  66. ############################################################################
  67. #4. 创建函数add_float(),实现传入两个float,返回二者之和
  68. DELIMITER //
  69. CREATE FUNCTION add_float(value1 FLOAT,value2 FLOAT)
  70. RETURNS FLOAT
  71. BEGIN
  72. #声明变量
  73. DECLARE sum_val FLOAT;
  74. SET sum_val = value1 + value2;
  75. RETURN sum_val;
  76. END //
  77. DELIMITER ;
  78. #调用
  79. SELECT add_float(1.2,2.3);
  80. ############################################################################
  81. #二. 流程控制
  82. #1. 创建函数test_if_case(),实现传入成绩,如果成绩>90,返回A,如果成绩>80,返回B,如果成绩>60,返回C,否则返回D
  83. #要求:分别使用if结构和case结构实现
  84. #方式一:使用IF
  85. DELIMITER //
  86. CREATE FUNCTION test_if_case1(score DOUBLE)
  87. RETURNS CHAR
  88. BEGIN
  89. #声明变量
  90. DECLARE score_level CHAR;
  91. IF score > 90 THEN SET score_level = 'A';
  92. ELSEIF score > 80 THEN SET score_level = 'B';
  93. ELSEIF score > 60 THEN SET score_level = 'C';
  94. ELSE SET score_level = 'D';
  95. END IF;
  96. RETURN score_level;
  97. END //
  98. DELIMITER ;
  99. #调用
  100. SELECT test_if_case1(85);
  101. #方式二:使用CASE
  102. DELIMITER //
  103. CREATE FUNCTION test_if_case2(score INT)
  104. RETURNS CHAR
  105. BEGIN
  106. #定义变量
  107. DECLARE score_level CHAR;
  108. CASE WHEN score > 90 THEN SET score_level = 'A';
  109. WHEN score > 80 THEN SET score_level = 'B';
  110. WHEN score > 60 THEN SET score_level = 'C';
  111. ELSE SET score_level = 'D';
  112. END CASE;
  113. RETURN score_level;
  114. END //
  115. DELIMITER ;
  116. #调用
  117. SELECT test_if_case2(96);
  118. ############################################################################
  119. #2. 创建存储过程test_if_pro(),传入工资值,如果工资值<3000,则删除工资为此值的员工,如果3000 <= 工资值 <= 5000,则修改此工资值的员工薪资涨1000,否则涨工资500
  120. DELIMITER $
  121. CREATE PROCEDURE test_if_pro(IN emp_sal DOUBLE)
  122. BEGIN
  123. IF emp_sal < 3000
  124. THEN DELETE FROM employees WHERE salary = emp_sal;
  125. ELSEIF emp_sal <= 5000
  126. THEN UPDATE employees SET salary = salary + 1000 WHERE salary = emp_sal;
  127. ELSE
  128. UPDATE employees SET salary = salary + 500 WHERE salary = emp_sal;
  129. END IF;
  130. END $
  131. DELIMITER ;
  132. #调用
  133. CALL test_if_pro(2900);
  134. SELECT *FROM employees;
  135. ############################################################################
  136. #3. 创建存储过程insert_data(),传入参数为 IN 的 INT 类型变量 insert_count,实现向admin表中批量插入insert_count条记录
  137. CREATE TABLE admin(
  138. id INT PRIMARY KEY AUTO_INCREMENT,
  139. user_name VARCHAR(25) NOT NULL,
  140. user_pwd VARCHAR(35) NOT NULL
  141. );
  142. SELECT * FROM admin;
  143. DELIMITER //
  144. CREATE PROCEDURE insert_data(IN insert_count INT)
  145. BEGIN
  146. #声明变量
  147. DECLARE init_count INT DEFAULT 1; #①初始化条件
  148. WHILE init_count <= insert_count DO #②循环条件
  149. #③循环体
  150. INSERT INTO admin(user_name,user_pwd)
  151. VALUES(CONCAT('atguigu-',init_count),ROUND(RAND()*1000000));
  152. #④迭代条件
  153. SET init_count = init_count + 1;
  154. END WHILE;
  155. END //
  156. DELIMITER ;
  157. #调用
  158. CALL insert_data(100);
  159. SELECT * FROM admin;
  160. ############################################################################
  161. #三. 游标的使用
  162. /*创建存储过程update_salary(),参数1为 IN 的INT型变量dept_id,表示部门id;参数2为 IN的INT型变量change_sal_count,表示要调整薪资的员工个数。查询指定id部门的员工信息,按照salary升序排列,根据hire_date的情况,调整前change_sal_count个员工的薪资,详情如下。
  163. hire_date salary
  164. hire_date < 1995 salary = salary * 1.2
  165. hire_date >=1995 AND hire_date <= 1998 salary = salary * 1.15
  166. hire_date >1998 AND hire_date <= 2001 salary = salary * 1.10
  167. hire_date > 2001 salary = salary * 1.05
  168. */
  169. DELIMITER $
  170. CREATE PROCEDURE update_salary(IN dept_id INT,IN change_sal_count INT)
  171. BEGIN
  172. #声明变量
  173. DECLARE emp_id INT; #记录员工id
  174. DECLARE emp_hire_date DATE; #记录员工入职时间
  175. DECLARE init_count INT DEFAULT 1; #用于表示循环结构的初始化条件
  176. DECLARE add_sal_rate DOUBLE; #记录涨薪的比例
  177. #声明游标
  178. DECLARE emp_cursor CURSOR FOR SELECT employee_id,hire_date FROM employees
  179. WHERE department_id = dept_id ORDER BY salary ASC;
  180. #打开游标
  181. OPEN emp_cursor;
  182. WHILE init_count <= change_sal_count DO
  183. #使用游标
  184. FETCH emp_cursor INTO emp_id,emp_hire_date;
  185. #获取涨薪的比例
  186. IF (YEAR(emp_hire_date) < 1995)
  187. THEN SET add_sal_rate = 1.2;
  188. ELSEIF (YEAR(emp_hire_date) <= 1998)
  189. THEN SET add_sal_rate = 1.15;
  190. ELSEIF (YEAR(emp_hire_date) <= 2001)
  191. THEN SET add_sal_rate = 1.10;
  192. ELSE
  193. SET add_sal_rate = 1.05;
  194. END IF;
  195. #涨薪
  196. UPDATE employees
  197. SET salary = salary * add_sal_rate
  198. WHERE employee_id = emp_id;
  199. #迭代条件的更新
  200. SET init_count = init_count + 1;
  201. END WHILE;
  202. #关闭游标
  203. CLOSE emp_cursor;
  204. END $
  205. DELIMITER ;
  206. #调用
  207. CALL update_salary(50,3);
  208. SELECT employee_id,hire_date,salary
  209. FROM employees
  210. WHERE department_id = 50
  211. ORDER BY salary ASC;