Oracle存储过程、存储函数以及Java程序调用存储过程和存储函数

存储过程、存储函数和表、视图、索引、序列、同义词一样,都属于数据库的对象。


存储过程和存储函数:
指存储在数据库中供所有用户程序调用的子程序叫存储过程、存储函数。


存储过程和存储函数的相同点:完成特定功能的程序
存储过程和存储函数的不同点:是否用return语句返回值,除此之外,可以认为存储过程和存储函数是一样的。


创建和使用存储过程:
用CREATE PROCEDURE命令建立存储过程和存储函数。
语法:
1.create [or replace] PROCEDUCE 过程名(参数列表) IS|AS  PLSQL子程序体;
参数类型不需要写长度,而且可以设置默认值:
job VARCHAR2 DEFAULT 'CLERK'


2.create [or replace] PROCEDUCE 过程名(参数列表) IS|AS  begin ......  end 过程名;






exp:(打印HelloWorld)
create or replace procedure sayHelloWorld
as
  --说明部分
begin
  dbms_output.put_line('Hello World');
end;
/


调用存储过程:
第一种方式(命令行):
execute sayHelloWorld();也可以简写为exec
第二种方式:
begin
 sayHelloWorld();
end;
/




存储过程传递参数的三种方式:
IN  
OUT
IN OUT  既可以作为输入参数,也可以作为输出参数


带参数的存储过程:
举例:为指定的员工,涨100块钱的工资,并打印涨工资前后的薪水


exp:
--创建一个带参的存储过程
create or replace procedure raisesalary(eno in number)
as
--定义一个变量保存涨前的薪水
psal emp.sal%type;
begin
--得到涨前的薪水
select sal into psal from emp where empno = eno;


--给该员工涨工资
update emp set sal = sal+100 where empno = eno;


--在此处需要commit吗?
--注意,一般不在存储过程或存储函数中commit或rollback。


--打印
dbms_output.put_line('涨前'||psal||'   涨后'||(psal+100));




end;
/




调试:
推荐本地调试,简单,方便
如果远程调试,还需要在工具里更改调试器的端口。




存储函数:
函数(Function)为一命名的存储程序,可带参数,并返回一计算值。
函数和过程的结构类似,但必须有一个RETURN子句,用于返回函数值。
语法:
create [or replace] FUNCTION 函数名(参数列表) return 函数值类型 AS PLSQL子程序体;


exp:查询某个员工的年收入
create or replace function queryEmpIncome(eno in number)
return number
as
 --定义变量保存员工的薪水和奖金
 psal emp.sal%type;
 pcomm emp.comm%type;
begin
 select sal,comm into psal,pcomm from emp where empno = eno;
 
 --返回年收入
 return psal*12+nvl(pcomm,0);  --如果pcomm为空,即没有奖金,那么不加nvl把空值变为0的话,整个式子都会为空
end;
/




in 和 out 参数
一般来讲,存储过程和存储函数的区别在于存储函数可以有一个返回值;而存储过程没有返回值。
过程和函数都可以通过out指定一个或多个输出参数。我们可以利用out参数,在过程和参数中实现返回多个值。




原则:如果只有一个返回值,用存储函数;否则,就用存储过程。
exp:out参数,查询某个员工姓名,月薪和职位


create or replace proceduce queryEmpInfo
(eno in number , pename out varchar2 , psal out number , pjob out varchar2)
as


begin
select ename,sal,empjob into pename,psal,pjob from emp where empno = eno;


end;
/




在Java中调用存储过程:
public void testProcedure(){
//call 后接存储过程名,参数用?代替
String sql = "{call queryEmpInfo(?,?,?,?)}";
Connection conn = null;
CallableStatement call = null;
try{
//获取数据库连接
conn = JDBCUtils.getConnection();
//创建statment
call = conn.prepareCall(sql);

//对于输入参数,需要赋值
call.setInt(1, 7839);
//对于输出参数,需要声明类型
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3, OracleTypes.NUMBER);
call.registerOutParameter(4, OracleTypes.VARCHAR);

//执行调用
call.execute();

//取出结果
String name = call.getString(2);
double sal = call.getDouble(3);
String job = call.getString(4);
System.out.println(name+"\t"+sal+"\t"+job);


}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.closeAll(conn, call, null);
}
}


在Java中调用存储函数:
@Test
public void testFunction(){
String sql = "{? = call queryEmpIncome(?)}";
Connection conn = null;
CallableStatement call = null;
try{
//获取数据库连接
conn = JDBCUtils.getConnection();
//创建statment
call = conn.prepareCall(sql);
//声明输出参数
call.registerOutParameter(1, OracleTypes.NUMBER);
//为输入参数赋值
call.setInt(2, 7839);
//执行调用
call.execute();
double income = call.getDouble(1);
System.out.println("该员工的年收入:"+income);
}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.closeAll(conn, call, null);
}
}




在out参数中使用光标:
申明包结构  包也是一个对象,和表,视图,等等同等级
-包头
-包体


案例:查询某个部门中所有员工的所有信息


包头:
CREATE OR REPLACE PACKACE MYPACEAGE AS 
 type empcursor is ref cursor;  --定义一个光标类型
 procedure queryEmpList(dno is number,empList out empcursor);
END MYPACKAGE;


包体:(包体需要实现包头中声明的所有方法)
CREATE OR REPLACE PACKAGE BODY MYPACKAGE AS
 procedure queryEmpList(dno in number,empList out empcursor) AS
   begin
     open empList for select * from emp where deptno = dno;
   end queryEmpList;


END MYPACKAGE;


在应用程序中访问包中的存储过程,需要带上包名:
public void testCursor(){
String sql = "{call MYPACKAGE.queryEmpList(?,?)}";
Connection conn = null;
CallableStatement call = null;
ResultSet rs = null;
try{
//获取数据库连接
conn = JDBCUtils.getConnection();
//创建statment
call = conn.prepareCall(sql);
//对于in参数,赋值
call.setInt(1,10);
call.registerOutParameter(2,OracleTypes.CURSOR);
//执行调用
call.execute();
//取出该部门中所有员工的信息,需要将CallableStatement类型强转为OracleCallableStatement,这样才可 以调用getCursor()方法
rs = ((OracleCallableStatement)call).getCursor(2);
while(rs.next()){
   //取出该员工的员工号  姓名  薪水 和 职位
   int empno = rs.getInt("empno");
   String name = rs.getString("ename");
   double salary = rs.getDouble("sal");
   String job = rs.getString("empjob");
   System.out.println(empno+"\t"+name+"\t"+salary+"\t"+job);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.closeAll(conn, call, rs);
}
}









































































你可能感兴趣的:(Oracle)