学习地址:https://www.imooc.com/learn/370
存储过程和存储函数定义:指存储在数据库中供所有用户程序调用的子程序叫做存储过程
、存储函数。
相同点:完成特定功能的程序。
区别:是否用return语句返回值。
语法:
create [or replace] procedure 过程名(参数列表)
as
plsql程序体
create or replace procedure sayhelloworld
as
--说明部分
begin
dbms_output.put_line('Hello World');
end;
调用存储过程:
1.exec sayhelloworld();
2.begin
sayhelloworld();
sayhelloworld();
end;
1 exec 存储过程名();2 begin 存储过程名();end /
创建带参数的存储过程:
-- 给指定的员工涨100块钱的工资,并且打印涨前后涨后的薪水 eno:员工号
create or replace procedure raisesalary(eno in number) -- in 这是一个输入参数
as
-- 定义一个变量保存涨前的薪水
psal emp.sal%type;
begin
-- 得到员工涨前的薪水
select sal into psal from emp where empno=eno;
-- 给该员工涨100块钱
update emp set sal=sal+100 where empno=eno;
-- 一般,这里不需要 commit ! 也不需要 rollback
-- 注意:一般不在存储过程或者存储函数中,commit 和 rollback
-- 打印
dbms_output.put_line('涨前:'||psal||',涨后:'||(psal+100));
end;
/
-- 调用:
begin
raisesalary(7839);
raisesalary(7566);
end;
/
一般不在存储过程中提交或者回滚,大多时间是在调用一次或者多次的时候提交或者回滚
,这样会防止出现意外情况。
创建存储函数的语法:
示例:根据员工号,查询员工年收入。
create or replace function queryempincom(eno in numbr)
return number
as
--定义变量保存员工的薪水和奖金
psal emp.sal%type;
pcomm emp.comm%type;
begin
--得到该员工的月薪和奖金
select sal,comm into pasl,pcomm from emp where empno=eno;
--直接返回年收入
return psal*12+nvl(pcomm,0);
end;
存储过程和存储函数都可以通过Out指定一个或多个输出参数。我们可以利用out参数,在
过程和函数中实现返回多个值。
存储过程可以通过out参数返回值。
什么时候用存储过程、存储函数?
一般原则:如果只有一个返回值,用存储函数;否则,用存储过程。
示例:
create or replace procedure queryempinfor(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;
使用JDBC连接数据库:
public class JDBCUtile{ private static String driver="orable.jdbc.OracleDriver"; private static String url="jdbc:oracle:thin:@192.168.56.101:1521:orcl"; private static String user="scott"; private static String password="tiger"; // 注册数据库的驱动 static{ try{ Class.forName(driver); // --> DriverManager.registerDriver(driver); }catch(ClassNotFoundException e){ throw new ExceptionInInitializerError(e); } } // 获取数据库连接 public static Connection getConnection(){ try{ return DriverManager.getConnection(url,user,password); }catch(SQLException e){e.printStackTrace(); } return null; } // 释放数据库的资源 public static void release(Connection conn,Statement st,ResultSet rs){ if(rs != null){try{ rs.close();}catch(SQLException e){e.printStackTrace();}finally{rs=null;}} if(st != null){try{st.close();}catch(SQLException e){e.printStackTrace();}finally{st=null;}} if(conn != null){try{conn.close();}catch(SQLException e){e.printStackTrace();}finally{conn=null;}} } }
在应用程序中访问存储过程和存储函数
使用CallachleStatement接口
public void testProcedure(){ //{call <procedure-name>[(<arg1>,<arg2>,...)]} String sql="call queryempinform(?,?,?,?)"; Connection conn=null; CallableStatement call=null; try{ // 得到一个连接 conn=JDBCUtils.getConnection(); // 通过连接创建出statement call=conn.prepareCall(sql); // 对于in参数,需赋值,对于out参数,需要申明 call.setInt(1, 7839); // 设置第一个?为 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+" "+sal+" "+job); }catch(Exception e){ e.printStackTrace(); }finally{ JDBCUtils.release(conn,call,null); } }
在out参数中使用光标:
包头: CREATE OR REPLACE PACKAGE MYPACKAGE AS type empcursor is ref cursor; procedure queryEmpList(dno in 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; -- 使用desc查看程序包的结构 desc MYPACKAGE
所有存储函数的功能都可以有存储过程来代替,为什么在oracle数据库中依然保留存储函数?
原因:数据库版本升级所造成,版本升级最基本的要求就是要向前向下兼容,在oracle数据库最早的版本中是有存储过程和存储函数的区别。如果新版本不支持存储函数,那么老的数据库中若存在存储函数就可能运行出错。