我们前面所学习的MySQL语句都是针对一个表或几个表的单条 SQL 语句,但是在数据库的实际操作中,并非所有操作都那么简单,经常会有一个完整的操作需要多条SQL语句处理多个表才能完成。例如,为了确认学生能否毕业,需要同时查询学生档案表、成绩表和综合表,此时就需要使用多条 SQL 语句来针对几个数据表完成这个处理要求。存储过程可以有效地完成这个数据库操作。
存储过程是数据库存储的一个重要的功能,但是 MySQL 在 5.0 以前并不支持存储过程,这使得 MySQL 在应用上大打折扣。好在 MySQL 5.0 终于开始已经支持存储过程,这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。
存储过程是一组为了完成特定功能的 SQL 语句集合。使用存储过程的目的是将常用或复杂的工作预先用 SQL语句写好并用一个指定名称存储起来,这个过程经编译和优化后存储在数据库服务器中,因此称为存储过程。当以后需要数据库提供与已定义好的存储过程的功能相同的服务时,只需调用“CALL存储过程名字”即可自动完成。
常用操作数据库的 SQL 语句在执行的时候需要先编译,然后执行。存储过程则采用另一种方式来执行 SQL 语句。
一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的特定功能时,存储过程尤为合适。
存储过程通常有如下优点:
MySQL 存储过程是一些 SQL 语句的集合,比如有的时候我们可能需要一大串的 SQL 语句,或者说在编写 SQL语句的过程中还需要设置一些变量的值,这个时候我们就完全有必要编写一个存储过程。下面我们来介绍一下如何创建一个存储过程。 基本语法 可以使用 CREATE PROCEDURE 语句创建存储过程。
语法格式如下:
CREATE PROCEDURE ( [过程参数[,…] ] ) [过程参数[,…] ] 格式 [ IN | OUT | INOUT ]
语法说明如下:
语法格式如下:
DELIMITER $$
语法说明如下: $$ 是用户定义的结束符,通常这个符号可以是一些特殊的符号,如两个“?”或两个“¥”等。 当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为它是 MySQL 的转义字符。
在 MySQL 命令行客户端输入如下SQL语句。
mysql > DELIMITER ??
成功执行这条 SQL 语句后,任何命令、语句或程序的结束标志就换为两个问号“??”了。
若希望换回默认的分号“;”作为结束标志,则在 MySQL 命令行客户端输入下列语句即可:
mysql > DELIMITER ;
注意:DELIMITER 和分号“;”之间一定要有一个空格。在创建存储过程时,必须具有 CREATE ROUTINE 权限。可以使用 SHOW PROCEDURE STATUS 命令查看数据库中存在哪些存储过程,若要查看某个存储过程的具体信息,则可以使用 SHOW CREATE PROCEDURE <存储过程名>。
【实例 1】创建名称为 ShowStuScore 的存储过程,存储过程的作用是从学生成绩信息表中查询学生的成绩信息,输入的 SQL 语句和执行过程如下所示。
1. mysql> DELIMITER // 2. mysql> CREATE PROCEDURE ShowStuScore() 3. -> BEGIN 4. -> SELECT * FROM tb_students_score; 5. -> END // 6. Query OK, 0 rows affected (0.09 sec)
创建存储过程 ShowStuScore 后,通过 CALL 语句调用该存储过程的 SQL 语句和执行结果如下所示。
1. mysql> DELIMITER ; 2. mysql> CALL ShowStuScore(); 3. +--------------+---------------+ 4. | student_name | student_score | 5. +--------------+---------------+ 6. | Dany | 90 | 7. | Green | 99 | 8. | Henry | 95 | 9. | Jane | 98 | 10. | Jim | 88 | 11. | John | 94 | 12. | Lily | 100 | 13. | Susan | 96 | 14. | Thomas | 93 | 15. | Tom | 89 | 16. +--------------+---------------+ 17. 10 rows in set (0.00 sec) 18. Query OK, 0 rows affected (0.02 sec)
【实例 2】创建名称为 GetScoreByStu 的存储过程,输入参数是学生姓名。存储过程的作用是通过输入的学生姓名从学生成绩信息表中查询指定学生的成绩信息,输入的 SQL 语句和执行过程如下所示。
1. mysql> DELIMITER // 2. mysql> CREATE PROCEDURE GetScoreByStu 3. -> (IN name VARCHAR(30)) 4. -> BEGIN 5. -> SELECT student_score FROM tb_students_score 6. -> WHERE student_name=name; 7. -> END // 8. Query OK, 0 rows affected (0.01 sec)
创建存储过程 GetScoreByStu 后,通过 CALL 语句调用该存储过程的 SQL 语句和执行结果如下所示。
1. mysql> DELIMITER ; 2. mysql> CALL GetScoreByStu('Green'); 3. +---------------+ 4. | student_score | 5. +---------------+ 6. | 99 | 7. +---------------+ 8. 1 row in set (0.03 sec) 9. Query OK, 0 rows affected (0.03 sec)
在实际开发过程中,业务需求修改的情况时有发生,这样,不可避免的需要修改 MySQL 中存储过程的特征 。基本语法 可以使用 ALTER PROCEDURE 语句修改存储过程的某些特征。
语法格式如下:
ALTER PROCEDURE [ … ]
提示:这个语法用于修改存储过程的某些特征,如要修改存储过程的内容,可以先删除该存储过程,再重新创建。
修改存储过程的内容和名称 修改存储过程的内容可以通过删除原存储过程,再以相同的命名创建新的存储过
程。
修改存储过程的名称可以通过删除原存储过程,再以不同的命名创建新的存储过程。
当 MySQL 数据库中存在废弃的存储过程是,我们需要将它从数据库中删除。 基本语法 存储过程被创建后,保存在数据库服务器上,直至被删除。可以使用 DROP PROCEDURE 语句删除数据库中已创建的存储过程。
语法格式如下:
DROP { PROCEDURE | FUNCTION } [ IF EXISTS ]
语法说明如下:
删除存储过程 删除存储过程 GetScoreByStu,查看存储过程的运行结果如下所示。
1. mysql> DROP PROCEDURE GetScoreByStu; 2. Query OK, 0 rows affected (0.00 sec) 3. mysql> CALL GetScoreByStu('Green'); 4. ERROR 1305 (42000): PROCEDURE test_db.GetScoreByStu does not exist
语法如下:
1. CREATE 2. PROCEDURE sp_name ([proc_parameter[,...]]) 3. routine_body 4. 5. proc_parameter: 6. [ IN | OUT | INOUT ] param_name type 7. 8. routine_body: 9. Valid SQL routine statement 10. 11. IF search_condition THEN statement_list 12. [ELSEIF search_condition THEN statement_list] ... 13. [ELSE statement_list] 14. END IF
创建一个student表并插入三条数据
1. mysql> create table student( 2. -> id int, 3. -> name varchar(30), 4. -> score float); 5. Query OK, 0 rows affected (0.01 sec) 6. 7. mysql> insert into student values(1,'z3',30),(2,'l4',60),(3,'w5',90); 8. Query OK, 3 rows affected (0.01 sec) 9. Records: 3 Duplicates: 0 Warnings: 0
创建存储过程,输入“a”返回大于等于60分数的学生信息,输入“b”返回大于等于80分数的学生信息,输入“c”返回大于等于90分数的学生信息,输入其他字符串则返回全部学生信息。
1. mysql> delimiter $$ 2. mysql> create procedure t1(in chars varchar(10)) 3. -> begin 4. -> if chars="a" then 5. -> select * from student where score>=60; 6. -> elseif chars="b" then 7. -> select * from student where score>=80; 8. -> elseif chars="c" then 9. -> select * from student where score>=90; 10. -> else select * from student; 11. -> end if; 12. -> end $$ 13. Query OK, 0 rows affected (0.08 sec) 14. 15. mysql> delimiter ; 16. mysql> call t1("a"); 17. +------+------+-------+ 18. | id | name | score | 19. +------+------+-------+ 20. | 2 | l4 | 60 | 21. | 3 | w5 | 90 | 22. +------+------+-------+ 23. 2 rows in set (0.00 sec) 24. 25. Query OK, 0 rows affected (0.01 sec) 26. 27. mysql> call t1("b"); 28. +------+------+-------+ 29. | id | name | score | 30. +------+------+-------+ 31. | 3 | w5 | 90 | 32. +------+------+-------+ 33. 1 row in set (0.00 sec) 34. 35. Query OK, 0 rows affected (0.00 sec) 36. 37. mysql> call t1("c"); 38. +------+------+-------+ 39. | id | name | score | 40. +------+------+-------+ 41. | 3 | w5 | 90 | 42. +------+------+-------+ 43. 1 row in set (0.00 sec) 44. 45. Query OK, 0 rows affected (0.00 sec) 46. 47. mysql> call t1("abc"); 48. +------+------+-------+ 49. | id | name | score | 50. +------+------+-------+ 51. | 1 | z3 | 30 | 52. | 2 | l4 | 60 | 53. | 3 | w5 | 90 | 54. +------+------+-------+ 55. 3 rows in set (0.00 sec) 56. 57. Query OK, 0 rows affected (0.00 sec)
语法如下:
1. CREATE 2. PROCEDURE sp_name ([proc_parameter[,...]]) 3. routine_body 4. 5. proc_parameter: 6. [ IN | OUT | INOUT ] param_name type 7. 8. routine_body: 9. Valid SQL routine statement 10. 11. CASE case_value 12. WHEN when_value THEN statement_list 13. [WHEN when_value THEN statement_list] ... 14. [ELSE statement_list] 15. END CASE
同样,上面使用的if语法创建存储过程,这次使用case语法创建。输入“a”返回大于等于60分数的学生信息,输入“b”返回大于等于80分数的学生信息,输入“c”返回大于等于90分数的学生信息,输入其他字符串则返回全部学生信息。
1. mysql> create procedure t2(in chars varchar(10)) 2. -> begin 3. -> case chars 4. -> when "a" then select * from student where score>=60; 5. -> when "b" then select * from student where score>=80; 6. -> when "c" then select * from student where score>=90; 7. -> else select * from student; 8. -> end case; 9. -> end$$ 10. Query OK, 0 rows affected (0.01 sec) 11. 12. mysql> delimiter ; 13. mysql> call t2("a"); 14. +------+------+-------+ 15. | id | name | score | 16. +------+------+-------+ 17. | 2 | l4 | 60 | 18. | 3 | w5 | 90 | 19. +------+------+-------+ 20. 2 rows in set (0.00 sec) 21. 22. Query OK, 0 rows affected (0.00 sec) 23. 24. mysql> call t2("b"); 25. +------+------+-------+ 26. | id | name | score | 27. +------+------+-------+ 28. | 3 | w5 | 90 | 29. +------+------+-------+ 30. 1 row in set (0.00 sec) 31. 32. Query OK, 0 rows affected (0.00 sec) 33. 34. mysql> call t2("c"); 35. +------+------+-------+ 36. | id | name | score | 37. +------+------+-------+ 38. | 3 | w5 | 90 | 39. +------+------+-------+ 40. 1 row in set (0.00 sec) 41. 42. Query OK, 0 rows affected (0.00 sec) 43. 44. mysql> call t2("d"); 45. +------+------+-------+ 46. | id | name | score | 47. +------+------+-------+ 48. | 1 | z3 | 30 | 49. | 2 | l4 | 60 | 50. | 3 | w5 | 90 | 51. +------+------+-------+ 52. 3 rows in set (0.00 sec) 53. 54. Query OK, 0 rows affected (0.00 sec)
语法如下:
1. CREATE 2. PROCEDURE sp_name ([proc_parameter[,...]]) 3. routine_body 4. 5. proc_parameter: 6. [ IN | OUT | INOUT ] param_name type 7. 8. routine_body: 9. Valid SQL routine statement 10. 11. Name: 'DECLARE VARIABLE' 12. Description: 13. Syntax: 14. DECLARE var_name [, var_name] ... type [DEFAULT value] 15. 16. Syntax: 17. WHILE search_condition DO 18. statement_list 19. END WHILE
创建循环存储过程,实现1+2+3+4...100(我算过了和为5050)while先判断后执行(条件满足情况下,则执行循环体内容,不满足,则结束循环),详情看下面命令吧。
1. mysql> create procedure t3() 2. -> begin 3. -> declare num int default 0; #定义num默认值为0 4. -> declare summ int default 0; #定义summ默认值为0 5. -> while num<=100 do #num小于等于100后停止 6. -> set summ=summ+num; #第一次循环为0,第二次为num上次循环的结果 7. -> set num=num+1; #num+1继续循环 8. -> end while; #跳过满足循环后跳出 9. -> select summ; #打印出summ循环相加的结果 10. -> end $$ #结束 11. Query OK, 0 rows affected (0.00 sec) 12. 13. mysql> delimiter ; 14. mysql> call t3(); 15. +------+ 16. | summ | 17. +------+ 18. | 5050 | 19. +------+ 20. 1 row in set (0.00 sec) 21. 22. Query OK, 0 rows affected (0.00 sec)
上面的命令虽然实现了循环,但是局限性很大只能打印出加到100,也就是说每次打印的都是5050,如果这次我们需要的更多呢?下面可以使用参数代替。
1. mysql> delimiter $$ 2. mysql> create procedure t4(in a int) 3. -> begin 4. -> declare num int default 0; 5. -> declare summ int default 0; 6. -> while num<=a do 7. -> set summ=summ+num; 8. -> set num=num+1; 9. -> end while; 10. -> select summ; 11. -> end $$ 12. Query OK, 0 rows affected (0.00 sec) 13. 14. mysql> delimiter ; 15. mysql> call t4(10); 16. +------+ 17. | summ | 18. +------+ 19. | 55 | 20. +------+ 21. 1 row in set (0.01 sec) 22. 23. Query OK, 0 rows affected (0.01 sec) 24. 25. mysql> call t4(1000); 26. +--------+ 27. | summ | 28. +--------+ 29. | 500500 | 30. +--------+ 31. 1 row in set (0.01 sec) 32. 33. Query OK, 0 rows affected (0.01 sec)
语法如下:
1. CREATE 2. PROCEDURE sp_name ([proc_parameter[,...]]) 3. routine_body 4. 5. proc_parameter: 6. [ IN | OUT | INOUT ] param_name type 7. 8. routine_body: 9. Valid SQL routine statement 10. 11. Syntax: 12. REPEAT 13. statement_list 14. UNTIL search_condition 15. END REPEAT
下面的循环也是根据1+2+3...+100,但是和while不同的是repeat的结构是先执行后判断(先执行相关操作 ,再判断是否满足条件,满足,结束循环)。
1. mysql> delimiter $$ 2. mysql> create procedure t5(in a int) 3. -> begin 4. -> declare num int default 0; 5. -> declare summ int default 0; 6. -> repeat 7. -> set summ=summ+num; 8. -> set num=num+1; 9. -> until num>a end repeat; 10. -> select summ; 11. -> end $$ 12. Query OK, 0 rows affected (0.05 sec) 13. 14. mysql> delimiter ; 15. mysql> call t5(10); 16. +------+ 17. | summ | 18. +------+ 19. | 55 | 20. +------+ 21. 1 row in set (0.02 sec) 22. 23. Query OK, 0 rows affected (0.03 sec) 24. 25. mysql> call t5(100); 26. +------+ 27. | summ | 28. +------+ 29. | 5050 | 30. +------+ 31. 1 row in set (0.00 sec) 32. 33. Query OK, 0 rows affected (0.00 sec)
学习不是一两天的事,活到老学到老,坚持下去总有一天会有成果。MySQL专栏持续更新,对你有帮助的话收藏起来吧!
Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者