侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Oracle存储过程及调用

数据库  /  管理员 发布于 6年前   165

Oracle存储过程语法

Oracle的存储过程语法如下:

create procedure 存储过程名称(随便取) is    在这里可以定义常量、变量、游标、复杂数据类型这里可以定义变量、常量begin    执行部分end; 

(2)带参数的存储过程语法:

create procedure 存储过程名称(随便取) (变量1 数据类型,变量2 数据类型,...,变量n 数据类型)is    在这里可以定义常量、变量、游标、复杂数据类型这里可以定义变量、常量begin    执行部分end; 

(3)带输入、输出参数的存储过程语法:

create procedure 存储过程名称(随便取) (变量1 in(或out) 数据类型,变量2 in(或out) 数据类型,...,变量n in(或out) 数据类型)is    在这里可以定义常量、变量、游标、复杂数据类型这里可以定义变量、常量begin    执行部分end;

注意:用上面的语法创建存储过程时可能会碰到数据库中已经有了同名的存储过程,这样Oracle就会弹框报错,说名字已被现有对象使用。解决方法有两种:

   方法一:换个存储过程名

   方法二:在最开头的create procedure 之间加上 or replace 关键字,例如:create or replace procedure 存储过程名称。但是这种方法不建议使用,因为这种方法会把之前同名的存储过程替换为你当前写的这个

存储过程案例一:没参数的存储过程

create replace procedure procedure_1isbegin    dbms_output.put_line('procedure_1.......');end;

存储过程案例二:带参数的的存储过程

create procedure procedure_2(v_i number,v_j number)is    v_m number(5);begin    dbms_output.put_line('procedure_2.......');    v_m := v_i + v_j;    dbms_output.put_line(v_i||' + '||v_j||' = '||v_m);end;

存储过程案例三:带输入、输出参数的存储过程

存储过程的参数分为输入参数和输出参数,

输入参数:输入参数一般会在变量名和数据类型之间加in来表示该参数是输入参数

输出参数:输出参数一般会在变量名和数据类型之间加out来表示该变量是输出参数

不写in和out的话,默认为输入参数

create procedure procedure_3(v_i in number,v_j in number ,v_m out number)isbegin    dbms_output.put_line('procedure_3.......');    v_m:=v_i - v_j;    dbms_output.put_line(v_i||' - '||v_j||' = '||v_m);end;

PL/SQL块中调用存储过程

下面以调用上面三个存储过程为例

declare    v_param1 number(5):=2;    v_param2 number(5):=8;    v_result number(5);begin    --调用上面案例一的存储过程    procedure_1();     --调用上面案例二的存储过程    procedure_2(v_param1,v_param2);     --调用上面案例三的存储过程    procedure_3(v_param1,v_param2,v_result);    dbms_output.put_line(v_result);end;/*执行结果:*/procedure_1.......procedure_2.......2 + 8 = 10procedure_3.......2 - 8 = -610

java调用存储过程

案例一:java调用没有返回值的存储过程

要求:编写一个像数据库emp表插入一条编号为6666,姓名为张三,职位为MANAGER的记录

/*存储过程*/create procedure procedure_4(v_empno emp.empno%type,v_ename emp.ename%type,v_job emp.job%type )isbegin    insert into emp (empno,ename,job) values (v_empno,v_ename,v_job);end;//java调用存储过程public static void main(String[] args) {  Connection conn=null;  CallableStatement cs=null;  ResultSet rs=null;  //java调用存储过程  try {    Class.forName("oracle.jdbc.OracleDriver");    conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.01:1521:orcl", "scott", "tiger");    cs=conn.prepareCall("{call procedure_4(?,?,?)}");    //给输入参数赋值    cs.setInt(1, 6666);    cs.setString(2, "张三");    cs.setString(3, "MANAGER");    cs.execute();//执行  } catch (Exception e) {    e.printStackTrace();  }finally{    closeResource(conn,cs,rs);//关闭资源  }  }//执行后就会向数据库的emp表中插入一条编号为6666,姓名为张三,职位为MANAGER的记录

案例二:java调用返回单列单行的存储过程

要求:编写一个根据员工编号查找员工姓名的存储过程,并用java调用该存储过程

/*存储过程*/create procedure procedure_5(v_empno in emp.empno%type,v_ename out emp.ename%type)isbegin    select ename into v_ename from emp where empno=v_empno;end;//java调用存储过程public static void main(String[] args) {  Connection conn=null;  CallableStatement cs=null;  ResultSet rs=null;  try {    Class.forName("oracle.jdbc.OracleDriver");    conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.01:1521:orcl", "scott","tiger");    cs=conn.prepareCall("{call procedure_5(?,?)}");    cs.setInt(1, 6666);//给输入参数赋值    /*指定输出参数的数据类型    语法:oracle.jdbc.OracleTypes.输出参数的数据类型    此例输出参数的数据类型是varchar,所以是oracle.jdbc.OracleTypes.VARCHAR*/    cs.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR);    cs.execute();//执行    //获取输出参数的值,位置要和输出参数对应?的位置对应起来,该例输出参数对应第2个问号,而且输出参数的数据类型为字符型,所以是cs.getString(2)    String a=cs.getString(2);    System.out.println("员工姓名:"+a);  } catch (Exception e) {    e.printStackTrace();  }finally{    closeResource(conn,cs,rs);//关闭资源  }  } /*执行结果,控制台打印:*/结果:员工姓名:张三

案例三:java调用返回单行多列的存储过程

要求:编写一个根据员工编号查找员工姓名、职位和工资的存储过程,并用java调用该存储过程

/*存储过程*/create procedure procedure_6(v_empno in emp.empno%type,v_ename out emp.ename%type,v_job out emp.job%type,v_sal out emp.sal%type)isbegin    select ename,job,sal into v_ename,v_job,v_sal from emp where empno=v_empno;end;//java调用存储过程public static void main(String[] args) {  Connection conn=null;  CallableStatement cs=null;  ResultSet rs=null;  try {    Class.forName("oracle.jdbc.OracleDriver");    conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.01:1521:orcl", "scott","tiger");    cs=conn.prepareCall("{call procedure_6(?,?,?,?)}");    cs.setInt(1, 7788);    //指定输出参数的数据类型,注意:顺序要对应起来    cs.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR);    cs.registerOutParameter(3, oracle.jdbc.OracleTypes.VARCHAR);    cs.registerOutParameter(4, oracle.jdbc.OracleTypes.DOUBLE);    cs.execute();//执行    //获取返回值    String ename=cs.getString(2);//获取姓名    String job=cs.getString(3);//获取职位    double sal=cs.getDouble(4);//获取薪水    System.out.println("员工编号为7788的姓名为:"+ename+" 职位是:"+job+" 薪水是:"+sal);  } catch (Exception e) {    e.printStackTrace();  }finally{    closeResource(conn,cs,rs);//关闭资源  }}/*执行结果,控制台打印:*/员工编号为7788的姓名为:SCOTT 职位是:ANALYST 薪水是:3000.0

案例四:java调用返回多行多列(返回列表)的存储过程

要求:编写一个根据部门编号查找部门所有员工信息的存储过程,并用java调用该存储过程

/*定义游标*/create package my_package astype emp_cursor is ref cursor;end my_package;/*存储过程*/create procedure procedure_7(v_deptno in emp.deptno%type,emp_cursor out my_package.emp_cursor)isbegin    open emp_cursor for select * from emp where deptno=v_deptno;end;//java调用存储过程public static void main(String[] args) {  Connection conn=null;  CallableStatement cs=null;  ResultSet rs=null;  try {    Class.forName("oracle.jdbc.OracleDriver");    conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.01:1521:orcl", "scott","tiger");    cs=conn.prepareCall("{call procedure_7(?,?)}");    cs.setInt(1, 20);//给输入参数赋值    cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR );//指定输出参数的数据类型    cs.execute();    rs=(ResultSet) cs.getObject(2);//获取输出参数的值    while(rs.next()){      //顺序为数据库中字段前后顺序,例如数据库emp表中第5列为hiredate,数据类型为Date,所以获取第5列值时就应该用rs.getDate(5)      System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getDate(5));    }  } catch (Exception e) {    e.printStackTrace();  }finally{    closeResource(conn,cs,rs);//关闭资源  }  }

/*以下就是20号部门所有员工的信息,这里为方便我们只打印了编号、姓名和入职时间

运行结果,控制台打印:*/

7369 SMITH 1980-12-177566 JONES 1981-04-027788 SCOTT 1987-04-197876 ADAMS 1987-05-237902 FORD 1981-12-03 

这是上面java调用存储过程代码中关闭资源方法的代码

public static void closeResource(Connection conn,CallableStatement cs,ResultSet rs){    if(rs!=null){      try {        rs.close();      } catch (SQLException e) {        e.printStackTrace();      }    }    if(cs!=null){      try {        cs.close();      } catch (SQLException e) {        e.printStackTrace();      }    }    if(conn!=null){      try {        conn.close();      } catch (SQLException e) {        e.printStackTrace();      }    }  }

最后给个应用,分页的存储过程

分页存储过程:

/*定义游标*/create package page_package astype page_cursor is ref cursor;end page_package;/*存储过程*/create procedure pro_paging (    v_page_size in number,--每页显示多少条    v_page_count out number,--总页数    v_current_page in number,--当前页    v_total_count out number,--记录总条数    emp_cursor out page_package.page_cursor--返回查询结果集的游标    )is    v_begin number(5):=v_page_size*(v_current_page-1)+1;--查询起始位置    v_end number(5):=v_page_size*v_current_page;--查询结束位置    v_sql varchar2(1000):='select empno,ename from       (select a.empno,a.ename,rownum rn from(select empno,ename from emp) a        where rownum<='|| v_end ||') b     where b.rn>='||v_begin;    /*不能像下面这么写,不然调用该存储过程时会报类型不一致的错,因为最里面查的只有empno,ename,因此外面也要和里面保持一致    v_sql varchar2(1000):=\'select * from       (select a.*,rownum rn from(select empno,ename from emp) a        where rownum<=\'|| v_end ||\') b     where b.rn>='||v_begin;*/    v_ename varchar2(10);    v_empno number(4);begin    open emp_cursor for v_sql;    loop     fetch emp_cursor into v_empno,v_ename;     exit when emp_cursor%notfound;     dbms_output.put_line(v_empno||' '||v_ename);    end loop;    v_sql:='select count(empno) from emp';    execute immediate v_sql into v_total_count;    if(mod(v_total_count,v_page_size)=0) then       v_page_count:=v_total_count/v_page_size;    else       v_page_count:=trunc(v_total_count/v_page_size)+1;    end if;    dbms_output.put_line('共 '||v_total_count||' 条记录');    dbms_output.put_line('共 '||v_page_count||' 页');    dbms_output.put_line('当前页: '||v_current_page);    dbms_output.put_line('每页显示 '||v_page_size||' 条');end;

Java调用的话和上面java调用存储过程的例子一样。这里为了方便 ,就直接在pl/sql中调用了

/*调用分页存储过程*/declare   v_page_count number(5);   v_cursor page_package.page_cursor;   v_total_count number(5);begin   dbms_output.put_line('第一页数据。。。。。。。。。');   pro_paging(5,--每页显示5条   v_page_count,--总页数   1,--当前页   v_total_count,--记录总条数   v_cursor--游标   );   dbms_output.put_line('--------------------------');   dbms_output.put_line('第二页数据。。。。。。。。。');   --显示第二页数据   pro_paging(5,--每页显示5条   v_page_count,--总页数   2,--当前页   v_total_count,--记录总条数   v_cursor--游标   );end;/*运行结果:*/第一页数据。。。。。。。。。6666 张三20 empSu219 empSave27369 SMITH7499 ALLEN共 17 条记录共 4 页当前页: 1每页显示 5 条--------------------------第二页数据。。。。。。。。。7521 WARD7566 JONES7654 MARTIN7698 BLAKE7782 CLARK共 17 条记录共 4 页当前页: 2每页显示 5 条

以上所述是小编给大家介绍的Oracle存储过程及调用,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!


  • 上一条:
    oracle数据库中sql%notfound的用法详解
    下一条:
    Oracle 12C实现跨网络传输数据库详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客