最近笔试面试,多次被问到,虽然笔者不怎么用,但是了解一下也是好的。
基本概念
数据库存储过程
是一组预先创建并用指定的名称存储在数据库服务器上的 SQL 语句
,将使用比较频繁或者比较复杂的操作,预先用 SQL 语句写好并用一个指定的名称存储起来
,以后当需要数据库提供与已定义好的存储过程的功能相同的服务时,只需再次执行该存储过程。
通俗点的讲就是一组为了完成特定功能的SQL 语句
,类似一门程序设计语言,也包括了数据类型、流程控制、输入和输出和它自己的函数库。
存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。
(注:T—SQL是SQL语言的一种版本,且只能在SQL SERVER上使用。详细请百度)
数据库存储过程具有如下优点:
- 存储过程只在创建时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,因此使用存储过程可以大大提高数据库执行速度。
- 当对数据库进行复杂操作时,可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
- 存储过程可以重复使用,可减少数据库开发人员的工作量。
- 安全性高,可设定只有某些用户才具有对指定存储过程的使用权
- 通常,复杂的业务逻辑需要多条 SQL 语句。这些语句要分别地从客户机发送到服务器,当客户机和服务器之间的操作很多时,将产生大量的网络传输。如果将这些操作放在一个存储过程中,那么客户机和服务器之间的网络传输就会大大减少,降低了网络负载。
使用 JDBC API 直接调用存储过程
JDBC 中的 CallableStatement
对象为所有的关系数据库管理系统 (RDBMS: Relational Database Management System) 提供了一种标准形式调用存储过程的方法。对存储过程的调用有两种形式:带结果参数和不带结果参数。结果参数是一种输出参数,是存储过程的返回值。
两种形式都可带有数量可变的输入(IN 参数)、输出(OUT 参数)或输入和输出(INOUT 参数)的参数。
使用 CallableStatement 对象调用存储过程的过程如下:
- 使用
Connection.prepareCall
方法创建一个 CallableStatement 对象。 - 使用
CallableStatement.setXXX
方法给输入参数(IN)赋值。 - 使用
CallableStatement.registerOutParameter
方法来指明哪些参数只做输出参数(OUT),哪些是输入输出参数(INOUT)。 - 调用以下方法之一来调用存储过程:
- int
CallableStatement.executeUpdate
: 存储过程不返回结果集。 - ResultSet
CallableStatement.executeQuery
: 存储过程返回一个结果集。 - Boolean
CallableStatement.execute
: 存储过程返回多个结果集。 - int[]
CallableStatement.executeBatch
: 提交批处理命令到数据库执行。
- int
- 如果存储过程返回结果集,则得到其结果集。
- 调用
CallableStatement.getXXX
方法从输出参数 (OUT) 或者输入输出参数 (INOUT) 取值。 - 使用完
CallableStatement
对象后,使用CallableStatement.close
方法关闭CallableStatement
对象。
存储过程名为 exampleJDBC,含有五个参数,前两个分别是 String 和 Int 类型的输入参数,后三个分别是整型,整型和字符型的输出参数。
分别给输入参数赋值 ”Beijing” 和 2008,执行 executeUpdate 命令后,从后三个输出参数中可以得到输出值,没有结果集返回。
Connection con = null;
...
// Create a CallableStatement object
CallableStatement cstmt = con.prepareCall("CALL exampleJDBC (?, ?, ?, ?, ?)");
cstmt.setString (1, “BeiJing”); // Set input parameter
cstmt.setInt (2, 2008); // Set input parameter
cstmt.registerOutParameter (3, Types.INTEGER);
cstmt.registerOutParameter (4, Types.INTEGER);
cstmt.registerOutParameter (5, Types.VARCHAR);
cstmt.executeUpdate(); // Call the stored procedure
int goldnumber = cstmt.getInt(3); // Get the output parameter values
int silvernumber = cstmt.getInt(4);
String errorinfo = cstmt.getString(5);
cstmt.close();
当存储过程返回一个结果集时,只需遍历该结果集便可以得到存储过程执行的所有结果。
CallableStatement cstmt = null;
…
boolean moreResultSets = cstmt.execute();
ResultSet rs1 = cstmt.getResultSet();
while (rs1.next())
System.out.println(rs1.getString(1) + " " + rs1.getString(2));
当存储过程返回多个结果集时,遍历所有结果集才能得到执行的所有结果,使用 getMoreResults() 方法跳转到下一个结果集。
CallableStatement cstmt = null;
…
While (cstmt.getMoreResults()) {
ResultSet rs2 = cstmt.getResultSet();
while (rs2.next())
System.out.println(rs2.getString(1) + " " + rs2.getString(2));
rs2.close();
}
如果存储过程返回多个结果集,每个结果集的数据结构都不一样,或者某些结果集的数据结构未知,则可以使用getColumnName()
方法来得到结果集中数据的列名。
CallableStatement cstmt = null;
…
boolean moreResultSets = cstmt.execute();
while (moreResultSets) {
ResultSet rs = cstmt.getResultSet();
ResultSetMetaData rsmd = rs.getMetaData();
StringBuffer buffer = new StringBuffer();
for (int i = 1; i <= rsmd.getColumnCount(); i++){
buffer.append(rsmd.getColumnName(i)).append("\t");
System.out.println(buffer.toString());
while (rs.next()) {
buffer.setLength(0);
for (int i = 1; i <= rsmd.getColumnCount(); i++)
buffer.append(rs.getString(i)).append("\t");
System.out.println(buffer.toString());
}
}
rs.close();
moreResultSets = cstmt.getMoreResults();
}
使用 JDBC 来调用存储过程是最常见的一种方式,由于 JDBC 是最接近于数据库的 API,因而其效率也是最高的。CallableStatement 对象为所有的 DBMS 提供了标准形式调用存储过程的方法,对于要求实现灵活,执行效率要求比较高应用,直接采用 JDBC API 来实现存储过程能很好地满足需要。
存储过程相关命令汇总
操作 | SQL命令 |
---|---|
创建存储过程 | CREATE PROCEDURE 存储过程名(参数种类1 参数1 数据类型1,[...] BEGIN 具体的procedure(处理) END |
查看数据库中的存储过程 | SHOW PROCEDURE STATUS\G |
查看具体的存储过程 | SHOW CREATE PROCEDURE 存储过程名\G |
调用(执行)存储过程 | CALL 存储过程名(参数1,...); |
删除存储过程 | DROP PROCEDURE 存储过程名 |
变量声明 | DECLARE 变量名 数据类型; |
变量赋值 | SET 变量名= ; |
先到这,后面以后用到再学习总结。