存储过程

一、概念

(1)定义:存储过程(Stored Procedure)是一组完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

  更通俗一点来说,可以这样理解:常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,这些SQL语句像一个方法一样实现了某些功能(对单表或多表的增删查改),以后需要数据库提供与已定义好的存储过程功能相同的服务时,只需调用execute即可自动完成命令。

 

(2)例子:

从【百度百科】拿过来的一个例子,如下:

CREATE PROCEDURE order_tot_amt
@o_id int,
@p_tot int output
AS
SELECT @p_tot = sum(Unitprice*Quantity)
FROM orderdetails
WHERE orderid=@o_id
GO
解说:该例子建立一个简单的存储过程order_tot_amt,这个存储过程根据用户输入的定单ID号码(@o_id),在订单明细表 (orderdetails)中计算该定单销售总额【单价(Unitprice)*数量(Quantity)】,这一金额通过@p_tot这一参数输出给调用这一存储过程的程序。

二、存储过程的基本语法

(1)存储过程可以分为如下几类:

  A、系统存储过程

  B、本地存储过程

  C、临时存储过程

  D、远程存储过程

  E、扩展存储过程

存储过程的基本语法,请参考[存储过程详解],该文描述较为详细,本文简单引用部分内容,如下:

--------------创建存储过程-----------------

CREATE PROC [ EDURE ] procedure_name [ ; number ]
    [ { @parameter data_type }
        [ VARYING ] [ = default ] [ OUTPUT ]
    ] [ ,...n ]

[ WITH
    { RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]

[ FOR REPLICATION ]

AS sql_statement [ ...n ]

--------------调用存储过程-----------------

EXECUTE Procedure_name '' --存储过程如果有参数,后面加参数格式为:@参数名=value,也可直接为参数值value

--------------删除存储过程-----------------

drop procedure procedure_name    --在存储过程中能调用另外一个存储过程,而不能删除另外一个存储过程

上述代码中参数的解说如下:

1.procedure_name:存储过程的名称,在前面加#为局部临时存储过程,加##为全局临时存储过程。

2.; number:是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去;例如,名为 orders 的应用程序使用的过程可以命名为 orderproc;1、orderproc;2 等;DROP PROCEDURE orderproc 语句将除去整个组。

3.@parameter:存储过程的参数,可以有一个或多个。用户必须在执行过程时提供每个参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2.100 个参数,使用 @ 符号作为第一个字符来指定参数的名称,参数名称必须符合标识符的规则。每个存储过程的参数仅用于该过程本身,相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。

4.data_type:参数的数据类型,所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字;对于可以是 cursor 数据类型的输出参数,没有最大数目的限制。

5.VARYING:指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化),仅适用于游标参数。

6.default:参数的默认值,如果定义了默认值,不必指定该参数的值即可执行过程;默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。

7.OUTPUT:表明参数是返回参数,该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPUT 参数。使用 OUTPUT 关键字的输出参数可以是游标占位符。 

8.AS :指定过程要执行的操作。

9.sql_statement:过程中包含的任意数目和类型的 Transact-SQL 语句,但有一些限制。

 

(2)例题

有时候会遇见一些关于存储过程的考题,可以看一下[SQL存储过程实例详解]中的几个例题

 

(3)更多内容

show procedure status
  显示数据库中所有存储的存储过程基本信息,包括所属数据库,存储过程名称,创建时间等
 
show create procedure sp_name
  显示某一个mysql存储过程的详细信息
 
exec sp_helptext sp_name
  显示你这个sp_name这个对象创建文本

 

参考资料

(1)http://blog.sina.com.cn/s/blog_52d20fbf0100ofd5.html

(2)http://www.cnblogs.com/hoojo/archive/2011/07/19/2110862.html

(3)http://www.jb51.net/article/31805.htm


三、在Java中调用存储过程

存储过程是做数据库开发时经常使用的技术,它可以通过节省编译时间的方式来提升系统性能,我们这里的示例使用MySQL数据库。

(1)如何调用不带参数的存储过程 

 假设我们现在有一个简单的存储过程,它只是返回user表中的所有记录,存储过程如下:

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetUser`()
BEGIN
select ID,NAME from user;
END

我们可以使用CallableStatement来调用存储过程:

private static void execStoredProcedureTest() throws SQLException
 {
     String driver = "org.apache.derby.jdbc.EmbeddedDriver";
     String dbURL = "jdbc:mysql://localhost/test";
     Class.forName(driver);
     Connection con = DriverManager.getConnection(dbURL, "root", "123");
     CallableStatement cst = con.prepareCall("call GetUser()");
     ResultSet rs = cst.executeQuery();
     while(rs.next())
     {
         int id = rs.getInt("ID");
         String name = rs.getString("NAME");
         System.out.println("ID:" + id + "; NAME=" + name);
     }
     rs.close();
     cst.close();
     con.close();
 }

执行结果如下:

ID:1; NAME=Zhang San
ID:2; NAME=TEST

 

(2)如何调用带参数的存储过程

MySQL的存储过程中的参数分为三种:in/out/inout,我们可以把in看做入力参数,out看做出力参数,JDBC对这两种类型的参数设置方式不同:

  1)in, JDBC使用类似于cst.set(1, 10)的方式来设置

  2)out,JDBC使用类似于cst.registerOutParameter(2, Types.VARCHAR);的方式来设置

我们来看一个in参数的示例,假设我们希望返回ID为特定值的user信息,存储过程如下:

CREATE DEFINER=`root`@`localhost` PROCEDURE `GetUserByID`(in id int)
 BEGIN
 set @sqlstr=concat('select * from user where ID=', id);
 prepare psmt from @sqlstr;
 execute psmt;
 END

Java的调用代码如下:

private static void execStoredProcedureTest2(int id) throws SQLException
 {
     String driver = "org.apache.derby.jdbc.EmbeddedDriver";
     String dbURL = "jdbc:mysql://localhost/test";
     Class.forName(driver);
     Connection con = DriverManager.getConnection(dbURL, "root", "123");
     CallableStatement cst = con.prepareCall("call GetUserByID(?)");
     cst.setInt(1, id);
     ResultSet rs = cst.executeQuery();
     while(rs.next())
     {
         String name = rs.getString("NAME");
         System.out.println("ID:" + id + "; NAME=" + name);
     }
     rs.close();
     cst.close();
     con.close();
 }

我们执行下面的语句:

execStoredProcedureTest2(1);

结果如下:

ID:1; NAME=Zhang San

对于out类型的参数,调用方式类似,不再赘述。

 


小结

本小节来看一下存储过程的优点,如下:

  (1)存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。

  (2)当对数据库进行复杂操作时(如对多个表进行Insert、Delete、Query、Update时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合起来使用。

  (3)存储过程可以重复使用,可减少数据库开发人员的工作量

  (4)安全性高,可设定只有某些用户才具有对指定存储过程的使用权


 

参考资料:

java 调用mysql的存储过程(简单示例)

http://blog.csdn.net/caiwenfeng_for_23/article/details/8472559

 

java 调用MySQL存储过程

http://lcy0202.iteye.com/blog/1556132

 

posted @ 2015-06-24 11:02  时空穿越者  阅读(220)  评论(0编辑  收藏  举报