oracle 存储过程及REF CURSOR的使用

摘要:主要记录了oracle的stored procedure相关知识、从定义到使用。从最简单的例子入手、逐渐深入。同时后面结合了ref cursor的使用。顺便补充了在java中如何使用。
一:简介

1、存储过程定义:
存储过程(Stored Procedure )是一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

存储过程是由流控制的和SQL 语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。在ORACLE 中,若干个有联系的过程可以组合在一起构成程序包。

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

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

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

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

简单说,你在你的机器上写了个存储过程,这个存储过程像那些表里的数据一样被放在遥远的数据库服务器当中,但是它又是可执行的代码,其他能连到数据库服务器的用户,可以调用你写的存储过程
它的作用是隐藏细节,就是说,你写的存储过程代码可能很复杂,但是其他人调用它却很简单,不用具体知道它是如何做的,且一次能完成多个指令

3、分类:

oracle有系统存储过程和自定义存储过程2种存储过程。

系统存储过程就是由oracle预先提供的一组完成特定功能的存储过程,安装完oracle就有了。

自定义存储过程就是存在oracle数据库里由一组plsql语句组成的自定义过程(procedure)。它可以供其它oracle自定义存储过程、自定义函数和job调用或者由客户端程序调用。

二:基本使用方法及示例

1、基本结构:

CREATEORREPLACE PROCEDURE 存储过程名字
(参数1INNUMBER,参数2INNUMBERAS
变量1INTEGER:=0;
变量2DATE;
BEGIN
END存储过程名字 

2、 无参形式的procedure:

--无参procedure
createorreplace procedure pro_no_param
is
begin
  dbms_output.put_line('the procedure without params'); 
endpro_no_param;

--调用
--one: 无参的procedure名字后面必须要()call pro_no_param();

--two:procedure名称后面可以没有();
begin
  pro_no_param();
end; 

3、 参数类型为IN的procedure:

--有参procedure  只有IN类型
createorreplace procedure pro_in_param(
       v_1innumber,
       v_2invarchar2,
       v_3indate
)
is
begin
  dbms_output.put_line('v1: ' || v_1 || ' v2: ' || v_2 || ' v2: '|| (to_char(v_3, 'yyyy-mm-dd')));
endpro_in_param;

begin
  pro_in_param(1,'chy', sysdate);
end;

4、 参数类型为OUT的procedure:

--有参procedure  只有OUT类型
createorreplace procedure pro_out_param(
       v1outnumber,
       v2outchar
)
is
begin
  v1 := 2;
  v2 := 'andyChen';
endpro_out_param;


--记得声明用于存放procedureout值的变量
--语句结束了一定记得结尾的 —— ;
declare
  v_1 number;
  v_2 varchar2(200);
begin
  pro_out_param(v_1, v_2);
  dbms_output.put_line('v1: ' || v_1 || ' v2: ' || v_2);
end; 

5、 参数类型同时为IN和OUT的procedure:
–同时为INOUT参数的procedure
–用同一变量接收传入的值然后将这个变量当作输出的值赋给执行时声明的变量

createorreplace procedure pro_in_out_param(
       in_out_paraminoutvarchar2
)
is
begin
      in_out_param := 'in_out_param and ' || in_out_param;
endpro_in_out_param;

declare
   in_out_param varchar2(222) := 'detail param';
begin
   pro_in_out_param(in_out_param);
   dbms_output.put_line(in_out_param);
end;

三:实例


CREATETABLEuser_info
(
 id   VARCHAR2(4) notnullprimary key,
 nameVARCHAR2(15),
 pwd  VARCHAR2(15),
 address VARCHAR2(30)
);

--创建一个添加用户的stored_procedure;
createorreplace procedure pro_addUser(
       n_id user_info.id%type,
       n_name user_info.name%type,
       n_pwd     user_info.pwd%TYPE,
       n_address user_info.address%TYPE
)
as
begin
  --插入数据
  insertintouser_info(id,name,pwd,address)
  values(n_id, n_name, n_pwd, n_address);
endpro_addUser;

--调用、有变量需要声明的时候才有declare、没有就直接begin
begin
    pro_addUser('1','chy','admin','nanjin');
    if SQL%found then
      dbms_output.put_line('add successed');
    endif;
end;

--根据id查询用户名和密码
createorreplace procedure pro_getUserInfo(
       n_id       user_info.id%type,
       n_nameoutuser_info.name%type,
       n_pwd outuser_info.pwd%type
)
as
begin
  selectuser_info.name, user_info.pwd inton_name, n_pwd 
  fromuser_info
  whereuser_info.id=n_id;
endpro_getUserInfo;


--调用
declare
    v_id    user_info.id%type := '1';
    v_name  user_info.name%type;
    v_pwd   user_info.pwd%type;
begin
    pro_getUserInfo(v_id, v_name, v_pwd);
    dbms_output.put_line('name: ' || v_name || ' pwd: ' || v_pwd);
end;

-- 打印九九乘法表
createorreplace procedure pro_multiplication_table
is
       i integer;
       j integer;
begin
       foriin1..9 loop
         forjin1..9 loop
           if i>=j then
             DBMS_output.put(To_Char(j)||'*'||to_char(i)||'='||to_char(i*j)||'   ');
           endif;
         endloop;
         DBMS_output.put_line('');
       endloop;
end pro_multiplication_table;     

--调用
call pro_multiplication_table();

--使用自定义游标、根据工作and薪水查询员工姓名
createorreplace procedure pro_getName(
       n_sal        emp.sal%type,
       n_ename outemp.ename%type,
       n_jobinoutemp.job%type
)
is
       n_count number;
       cursorcurisselectename fromempwhereemp.sal > n_sal andemp.job=n_job;
       n_row  cur%rowtype;
begin
       selectcount(*)inton_countfromempwhereemp.sal > n_sal andemp.job=n_job;
       if n_count > 1 then
         forn_rowincur loop
           DBMS_output.put_line('职工姓名为:'||n_row.ename||'    工作为:'||n_job);
         endloop;
       else
           DBMS_output.put_line('未查到符合条件的记录!'); 
       endif;
end pro_getName;     

-- 调用
declare
   v_sal   emp.sal%type := 2000;
   v_job   emp.job%type :='MANAGER';
   v_ename emp.ename%type;
begin
   pro_getName(v_sal, v_ename, v_job);
end;  

--ref cursor的使用
--创建存放弱引用和强引用的cursor的包
createorreplace package refcursor_pkg 
as
type weak_ref_cursor isrefcursor;
type strong_ref_cursor isrefcursorreturnemp%rowtype;
endrefcursor_pkg;

--将弱引用的cursor作为结果返回
createorreplace procedure test(
       p_deptnoinnumber,
       p_cursoroutrefcursor_pkg.weak_ref_cursor
)
isbegin
       openp_cursorforselect* fromempwheredeptno=p_deptno;
endtest;

/**或者不用包直接使用下面这种定义
createorreplace procedure test_1( 
       p_deptnoINnumber,
       p_cursorOUTSYS_REFCURSOR
)
is
begin
  openp_cursorFORselect*fromempwhere deptno = p_deptno;
endtest_1;
*/

declare
    v_deptno number := 20;
    v_cursor refcursor_pkg.weak_ref_cursor;
    r_emp emp%rowtype;
begin
    test(v_deptno, v_cursor);
    loop
      fetchv_cursorintor_emp;
      exitwhenv_cursor%notfound;
      dbms_output.put_line('empno: ' || r_emp.empno || ' ename: ' || r_emp.ename || ' job: ' || r_emp.job);
    endloop;
    closev_cursor;
end;   
//java中使用refcursor

publicvoid method() throws SQLException{
  Connectionconn = getConnection();
  CallableStatement cstmt = null;
  ResultSet rs = null;
  intdeptno = 10;
  Objecttemp;
  try{
      cstmt = conn.prepareCall("begin  test(?,?); end;");
      cstmt.setInt(1, deptno);
      cstmt.registerOutParameter(2, OracleTypes.CURSOR);
      cstmt.execute();
      rs = (ResultSet) cstmt.getObject(2);
      ResultSetMetaData rsm = rs.getMetaData();
      intcolumnCount = rsm.getColumnCount();
      while (rs.next()){
         for(intj=0;j< columnCount;j++){
            temp= rs.getObject(j+1);
         }
      }
  } finally {
      if (!rs==null){
        rs.close();
      }
      if (!stmt==null){
        stmt.close();
      }
      if (!conn==null){
        conn.close();
      } 
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值