Oracle存储过程及调用

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_1
is
begin
    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)
is
begin
    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 = 10
procedure_3.......
2 - 8 = -6
10

java调用存储过程

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

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

/*存储过程*/
create procedure procedure_4(v_empno emp.empno%type,v_ename emp.ename%type,v_job emp.job%type )
is
begin
    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)
is
begin
    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)
is
begin
    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 as
type 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)
is
begin
    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-17
7566 JONES 1981-04-02
7788 SCOTT 1987-04-19
7876 ADAMS 1987-05-23
7902 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 as
type 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 empSu2
19 empSave2
7369 SMITH
7499 ALLEN
共 17 条记录
共 4 页
当前页: 1
每页显示 5 条
--------------------------
第二页数据。。。。。。。。。
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
共 17 条记录
共 4 页
当前页: 2
每页显示 5 条

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

(0)

相关推荐

  • Oracle 大小写转换函数实例详解

    Oracle 大小写转换函数 小写转大写UPPer 大写转小写LOWER 例: select lower(ename) from emp; select upper(ename) from emp; --是否包含字母(大写和小写) select case when regexp_like('123','.([a-z]+|[A-Z])') then '包含字母' else '不包含字母' end from dual; --是否包含小写字母 select case when regexp_like(

  • Oracle两张表关联批量更新其中一张表的数据

    方法一(推荐): UPDATE 表2 SET 表2.C = (SELECT B FROM 表1 WHERE 表1.A = 表2.A) WHERE EXISTS (SELECT 1 FROM 表1 WHERE 表1.A = 表2.A); 尤其注意最后的外层where条件尤为重要,是锁定其批量更新数据的范围. 方法二: MERGE INTO 表2 USING 表1 ON (表2.A = 表1.A) -- 条件是 A 相同 WHEN MATCHED THEN UPDATE SET 表2.C = 表1.

  • Oracle自我补充之trunc()函数的使用方法

    1.TRUNC(for dates) TRUNC函数为指定元素而截去的日期值. 其具体的语法格式如下: TRUNC(date[,fmt]) 其中: date 一个日期值 fmt 日期格式,该日期将由指定的元素格式所截去.忽略它则由最近的日期截去 下面是该函数的使用情况: TRUNC(TO_DATE('24-Nov-1999 08:00 pm'),'dd-mon-yyyy hh:mi am') ='24-Nov-1999 12:00:00 am' TRUNC(TO_DATE('24-Nov-199

  • Oracle Linux 6.8安装 mysql 5.7.17的详细教程

    安装MySQL 5.7.17的方法如下所示: 1.下载 http://www.codeyyy.com/linux/149-150-153.html 2.上传解压 tar -xvf mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz 3.新建mysql目录 mkdir -p /usr/local/mysql/data mv mysql-5.7.17-linux-glibc2.5-x86_64/* /usr/local/mysql/ 4.添加用户组 groupadd

  • Oracle 数据库忘记sys与system管理员密码重置操作方法

    首先打开cmd 执行 orapwd file=C:\app\PWDorcl.ora password=orclorcl C:\app\PWDorcl.ora是你要存放的路径文件 Password=orclorcl是你要改的密码 然后回车,在该路径下就会生成一个文件.把这文件替换你本机oracl的密码文件.Sys和system密码就会改成你要重新设置的密码 例如我的本机路径是C:\app\product\11.2.0\dbhome_1\database 以上所述是小编给大家介绍的Oracle 数据

  • Oracle存储过程和存储函数创建方法(详解)

    select * from emp; -----------------存储过程------------------------ --定义 create[or replace] procedure 存储过程名称(参数名 [in]/out 数据类型)    is/as    begin --逻辑表达式  end [存储过程名称]; --定义存储过程计算年薪,并答应输出 create or replace procedure proc_salyears(v_no in number)    is  

  • oracle数据库中sql%notfound的用法详解

    SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回false.这样的语句在实际应用中,是非常有用的.例如要update一行数据时,如果没有找到,就可以作相应操作.如: begin update table_name set salary = 10000 where emp_id = 10; if sql%notfound then insert into

  • Oracle存储过程及调用

    Oracle存储过程语法 Oracle的存储过程语法如下: create procedure 存储过程名称(随便取) is 在这里可以定义常量.变量.游标.复杂数据类型这里可以定义变量.常量 begin 执行部分 end; (2)带参数的存储过程语法: create procedure 存储过程名称(随便取) (变量1 数据类型,变量2 数据类型,...,变量n 数据类型) is 在这里可以定义常量.变量.游标.复杂数据类型这里可以定义变量.常量 begin 执行部分 end; (3)带输入.输

  • Oracle报存储过程中调用DBLink同义词出现错误:PLS-00201: 必须声明标识符

    前几天编写一个存储过程,需要访问远程数据库的字段,于是建立一个dbLink并建了同义词: CREATE PUBLIC DATABASE LINK orcl@dbc CONNECT TO orcl IDENTIFIED BY orcl USING 'orcl'; CREATE SYNONYM mtb FOR mytable@orcl@dbc: 这里之所以用orcl@bdc为dblink的名称是为了设置global_names=true. 然后新建一个存储过程调用该同义词: v_result mtb

  • Mybatis传list参数调用oracle存储过程的解决方法

    怎么利用MyBatis传List类型参数到数据库存储过程中实现批量插入数据? MyBatis中参数是List类型时怎么处理?大家都知道MyBatis批处理大量数据是很难做到事务回滚的(事务由Spring管理),都将逻辑写在存储中又是及其头疼的一件事(参数长度也有限制),那么我想的是将参数在后台封装为单个或多个list集合,直接通过MyBatis将此参数传到数据库存储过程中,一来摆脱了MyBatis批量插入数据的诸多限制(例如:不能实时返回主键.foreach标签循环集合长度有限制),二来就是在存

  • Mybatis调用Oracle存储过程的方法图文详解

    1:调用无参数的存储过程. 创建存储过程: Mapper.xml 配置:经测试其他标签(update.insert.select)也可以. Mapper.java MapperTest.java 测试 2:有参数的存储过程调用: 2.1存储过程的创建: 2.2Mapper.xml 的配置: 2.3Mapper.java 2.4MapperTest.java 测试 控制台输出: 3:存储过程的结果集调用. 3.1创建存储过程: 3.2 Mapper.xml 配置 配置 resultMap结果集字段

  • Python使用cx_Oracle调用Oracle存储过程的方法示例

    本文实例讲述了Python使用cx_Oracle调用Oracle存储过程的方法.分享给大家供大家参考,具体如下: 这里主要测试在Python中通过cx_Oracle调用PL/SQL. 首先,在数据库端创建简单的存储过程. create or replace procedure test_msg(i_user in varchar2, o_msg out varchar2) is begin o_msg := i_user ||', Good Morning!'; end; 然后,开始在Pytho

  • C#调用Oracle存储过程的方法

    本文实例讲述了C#调用Oracle存储过程的方法.分享给大家供大家参考.具体实现方法如下: Oracle数据库代码如下: 复制代码 代码如下: create or replace procedure proce_test(paramin in varchar2,paramout out varchar2,paraminout in out varchar2) as   varparam varchar2(28); begin   varparam:=paramin;   paramout:=va

  • Java调用Oracle存储过程详解

    Java调用Oracle存储过程详解 步骤: 1.编写Oracle存储过程 2.编写数据库获取连接工具类 3.编写简单应用调用存储过程 实现: 1.Oracle存储过程: /*测试表*/ create table test( id varchar2(32), name varchar2(32) ); /*存储过程 插入数据*/ CREATE OR REPLACE PROCEDURE insert_procedure( PARA1 IN VARCHAR2, PARA2 IN VARCHAR2 )

  • asp.net中调用oracle存储过程的方法

    存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它. 存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程. 不多说了,本文通过两种方法介绍asp.net中调用oracle存储过程的方法,具体内容请看下面代码. 调用oracle存储过程方法一: ORACLE代码 CREATE OR REP

  • Spring boot调用Oracle存储过程的两种方式及完整代码

    前言 因工作需要将公司SSH项目改为Spingboot项目,将项目中部分需要调用存储过程的部分用entityManagerFactory.unwrap(SessionFactory.class).openSession()来获取Session实现后发现项目访问数据库超过十次就会挂掉,原因是Springboot连接池数量默认为10,猜测是每次访问数据库后连接未释放导致的,手动关闭session后问题解决. 解决问题的过程中又发现了另外两种调用方式: 直接用EntityManager的createS

  • C#调用Oracle存储过程方法介绍(附源码)

    C#调用Oracle存储过程的代码如下所示: using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Data; using System.Data.OracleClient; using System.Drawing; using Syste

随机推荐