存储过程(Stored Procedure)介绍
本文主要介绍存储过程的相关知识。
1. 概述
1.1 what
存储过程(Stored Procedure)是:大型数据库系统中,一组为了完成特定功能的 SQL 语句集,这些SQL语句集存储在数据库中,经过第一次编译后,后续调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程是数据库的一个重要对象。
1.2 why
使用存储过程的原因,通常也可以用存储过程的优点来讲述。如下:
- 当对数据库进行复杂操作时(如对多个表进行增删改查),可将这些复杂操作使用存储过程封装起来,与数据库提供的事务处理结合起来使用。
- 存储过程只在创造时进行编译,以后每次执行存储过程都不需重新编译;而一般SQL语句每执行一次就需要编译一次,所以使用存储过程可提高数据库执行速度。
- 存储过程有助于减少应用程序和数据库服务器之间的流量,因为应用程序不必发送多个冗长的SQL语句,而只需要发送存储过程的名称(和参数)。
- 存储过程对任何应用程序都是可重用的和透明的。存储过程可以重复使用。存储过程将数据库接口暴露给所有应用程序,开发人员不需要重复开发存储过程中已支持的功能,从而可以减少数据库开发人员的工作量。
- 存储过程是安全的。参数化的存储过程可以防止SQL注入式攻击;同时,数据库管理员可以为访问数据库中存储过程的应用程序授予适当的权限,而不向基础数据库表提供任何权限。
1.3 how
当前,几大数据库厂商提供的编写存储过程的工具都没有统一,虽然它们针对存储过程的编写风格有些相似,但由于没有标准,所以各家的开发调试过程也不一样。
本文在下一节中会针对不同的数据库,分别介绍其存储过程的使用方法。
2. 用法
2.1 MySQL
2.1.1 一个简单的存储过程示例
DELIMITER //
CREATE PROCEDURE GetOccupation(OUT s TEXT)
BEGIN
SELECT occupation into s FROM roles WHERE role_id = 1;
END //
DELIMITER ;
其中:
- 命令“DELIMITER //”,与存储过程语法无关。DELIMITER语句将标准分隔符分号“;”更改为双反斜杠“//”。更改分隔符的原因,在于我们想将存储过程的内容作为一个整体传递给数据库服务器,而不是让mysql工具单独解释每个SQL语句(在上面的示例中,假如不更改分隔符,那么SELECT语句就会单独执行,倘若存储过程中存在多个类似的语句,那么每条语句都会被单独执行,这显然不是我们想要的)。在END关键字之后,使用分隔符“//”来表示存储过程的内容到此结束。最后的DELIMITER命令将分隔符更改回分号“;”。
- 使用“CREATE PROCEDURE”语句创建一个新的存储过程。在CREATE PROCEDURE语句之后指定待创建的存储过程的名称。在上面的示例中,存储过程的名称为:GetOccupation,其后携带着该存储过程的参数信息(即TEXT类型的出参s)。
- BEGIN和END之间的部分称为存储过程的主体。将声明性SQL语句放在主体之中以处理业务逻辑。在上面的存储过程中,我们使用了一个简单的SELECT语句来查询roles表中的occupation字段的数据。
2.1.2 创建存储过程
将存储过程录入数据库中有多种方式,在此我们通过MySQL客户端命令行工具,录入前面的存储过程示例。如下:
说明:我们也可以通过将存储过程内容编写为一个文件,直接将该文件内容导入数据库中;或者通过GUI工具创建存储过程。
2.1.3 查询存储过程信息
通过MySQL客户端命令行工具,查询存储过程信息,命令如下:
SHOW PROCEDURE STATUS;
在创建了存储过程后,查询结果如下:
另外,可以通过如下命令查询存储过程的详细内容,如下:
SHOW CREATE PROCEDURE PROCEDURE_NAME
对于前面创建的存储过程,查询结果如下:
说明:“\G”的作用是将查询的结果旋转90度变成纵向显示。
2.1.4 调用存储过程
通过MySQL客户端命令行工具,调用指定的存储过程,命令样式如下:
CALL PROCEDURE_NAME[(参数信息)];
其中,PROCEDURE_NAME为存储过程名称,并根据存储过程的参数设置情况,附带相应的参数信息。
此处调用前面创建的存储过程GetOccupation,如下:
上述结果显示,我们设置的参数“out_info”作为存储过程GetOccupation的出参,在调用该存储过程后,获得了相应的查询结果。
2.1.5 删除存储过程
通过MySQL客户端命令行工具,删除指定的存储过程,命令样式如下:
DROP PROCEDURE PROCEDURE_NAME;
在本例中,如下:
上述结果显示:使用DROP命令删除存储过程GetOccupation之后,再次查询存储过程信息时,已经查询不到该存储过程信息了,说明删除存储过程成功了。