前言:以下内容均以MySQL中的存储过程举例说明
一 存储过程简介
我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
一个存储过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
存储过程通常有以下优点:
i)存储过程增强了SQL语言的功能和灵活性。存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
ii)存储过程允许标准组件是编程。存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。
iii)存储过程能实现较快的执行速度。如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。
iv)存储过程能过减少网络流量。针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的Transaction-SQL语句被组织程存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大增加了网络流量并降低了网络负载。
v)存储过程可被作为一种安全机制来充分利用。系统管理员通过执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。
(PS:以上简介参考至:http://www.jb51.net/article/30825.htm)
二 存储过程的简单使用
(1)格式:
MySQL存储过程创建的格式:CREATE PROCEDURE 过程名 ([过程参数[,…]])
[特性 …] 过程体
(2)创建一个存储过程myproc并进行测试:
mysql> DELIMITER // CREATE PROCEDURE myproc(IN p1 int,INOUT p2 int,OUT p3 int) BEGIN SELECT p1,p2,p3; SET p1 = 10; SET p2 = 20; SET p3 = 30; END // Query OK, 0 rows affected mysql> SET @P1 = 11// Query OK, 0 rows affected mysql> SET @P2 = 22// Query OK, 0 rows affected mysql> CALL myproc(@P1,@P2,@P3)// +----+----+------+ | p1 | p2 | p3 | +----+----+------+ | 11 | 22 | NULL | +----+----+------+ 1 row in set Query OK, 0 rows affected mysql> SELECT @P1,@P2,@P3// +-----+-----+-----+ | @P1 | @P2 | @P3 | +-----+-----+-----+ | 11 | 20 | 30 | +-----+-----+-----+ 1 row in set mysql>
注:
i):MySQL中默认的语句结束符为分号(;),存储过程中的SQL语句也需要需要分号来结束。因此为了避免冲突,首先用”DELIMITER // “将MySQL的结束符设置为“//”
ii)在上面的存储过程“myproc”中定义了三个变量,分别使用了IN、INOUT和OUT这三种类型来申明,它们表示的含义分别是:
IN 输入参数:表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
OUT 输出参数:该值可在存储过程内部被改变,并可返回
INOUT 输入输出参数:调用时指定,并且可被改变和返回
iii)“SET @P1 = 11” 这种形式表示定义了一个名为“@P1”的用户变量,同时“SELECT p1,p2,p3; ”表示输出p1、p2、p3的值。执行“CALL myproc(@P1,@P2,@P3)”后p3的值为空,因为在输出时p3还没有被赋值;执行完“SELECT @P1,@P2,@P3;”后,可以发现@P1的值没有发生改变,因为IN类型只是将值传递到存储过程中去,@P2和@P3的值发生改变是因为在存储过程中已经被重新赋值了
三 使用CallableStatement接口操作存储过程
CallableStatement主要是调用数据库中的存储过程,在使用CallableStatement时可以接收过程的返回值,示例代码如下:
package javase.jdbc; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException; import java.sql.Types; public class ProcDemo { /** * JDBC调用MySQL存储过程示例 * */ public static void main(String[] args) { /** * DELIMITER // CREATE PROCEDURE myproc(IN p1 int,INOUT p2 int,OUT p3 int) BEGIN SELECT p1,p2,p3; SET p1 = 10; SET p2 = 20; SET p3 = 30; END // * * */ String sql = "{CALL myproc(?,?,?)}"; //调用存储过程myproc Connection connection = JDBCConnection.getConnection(); try { CallableStatement cStatement = connection.prepareCall(sql); cStatement.setInt(1, 11); cStatement.setInt(2, 22); cStatement.registerOutParameter(2, Types.INTEGER); //设置返回值类型 cStatement.registerOutParameter(3, Types.INTEGER); //设置返回值类型 cStatement.execute(); //执行存储过程 System.out.println("INOUT的返回值: " + cStatement.getInt("p2")); System.out.println("OUT的返回值: " + cStatement.getInt("p3")); cStatement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
输出:
INOUT的返回值: 20 OUT的返回值: 30