存储过程学习

/*
  概述--
  定义:存储在数据库中供所有用户调用的子程序叫存储过程或存储函数。
  两者区别:
  相同点:都是能完成特定功能的程序。
  不同点:存储函数必须有一个return,用于返回函数的返回值,存储过程没有。
  注意:
     存储过程和存储函数不能被修改,只能创建或者替换,如果需要修改,直接
     使用replace procedure 过程名修改。过程和函数都可以带参数列表和不带
     参数列表。
*/

/******************************* 存储过程 **********************************/

  语法:
        create or replace procedure 过程名(参数列表)
       as
       变量定义说明
       begin
         PLSQL子程序
       end;

*/
/*
  存储过程调用:
  exec helloword();
  begin
    helloword();
    helloword();
    helloword();
  end;

*/
create or replace procedure helloword
as
--说明部分
begin
  dbms_output.put_line('HelloWord!');
end;


/*
  创建带参数的存储过程
  eg:给指定员工涨工资,并打印涨前和涨后的薪水
  注意:
       当存储函数后过程带参数时,必须指明该参数是输出参数(out)还是输入参数(in)

*/


create or replace procedure raisesalary(eno in number)
as
--定义变量保存涨前薪水
--定义变量时引用员工表emp中的sal字段的类型为变量类型
  pasl emp.sal%type;
begin
  --得到涨前工资
  select sal into pasl from emp where empno = eno;
  --给指定员工涨工资
  update emp set sal = sal + 100 where empon = eno;
  /* 
     问题:存储过程和函数中是否可以commit和rollback?
           可以(容易出现事务不同步),但是一般不用。
     注意:
         存储过程或函数中出现更新、插入等事务操作时,一般不commit和rollback,
         因为存储过程和函数是作为一个程序的子程序被调用的,事务相关的一般在
         主程序中操作。
  */

  --打印涨前涨后薪水
  dbms_output.put_line('涨前:'||pasl||'涨后:'||(pasl+100))
end;


/******************************* 存储函数 **********************************/


/*
  语法:
     create or replace FUNCTION 函数名(参数列表)
     return 函数返回值类型
     as
     变量定义说明
     begin
       PLSQL子程序
     end;
*/
/*
  创建存储函数
  eg:查询某个员工的年收入
*/
create or replace function queryempincome(eno in number)
return number
as
  --定义变量保存员工薪水和奖金
  pasl emp.sal%type;
  pcomm emp.comm%type;
begin
  --得到月薪和奖金
  select sal,comm into pasl,pcomm from emp where empno = eno;
  --返回年收入
  --nvl(a,b) 预空函数,当a为空时用b
  return sal*12 + nvl(pcomm,0);
end;  


/**************************************输入输出参数*************************************/

/*
  存储过程和函数都可以通过out指定一个或者多个输出参数,可以利用out参数在过程或者函数中实现返回多个值
  注意:
      一般情况下,需要一个返回值,使用存储函数,需要多个返回值,则使用存储函数
  
  eg:
    查询某个员工的姓名,月薪,职位

*/
create or replace procedure queryempinfo(eno in number,
                               pname out varchar2,
                               psal  out number,
                               pjob out varchar2)
as
begin
  select ename,esal,ejob into pname,psal,pjob from emp where empon = eno;
end;


/**************************************java中调用过程或者函数**************************************/


        Connection con = null;
        CallableStatement call = null;
        String sql = "{call queryempinfo(?,?,?,?)}";
        try{
            --//获取连接
            con = JDBCUtil.getConnection();
            --//通过连接创建statement
            call = con.prepareCall(sql);
            --//处理入参in,赋值
            call.setInt(1,111);
            --//处理出参out,声明其类型
            call.registerOutParameter(2, OracleTypes.VARCHAR);
            call.registerOutParameter(3,OracleTypes.NUMBER);
            call.registerOutParameter(4,OracleTypes.VARCHAR);
            --//执行过程
            call.execute();
            --//获取结果
            String name = call.getString(2);
            Float sal = call.getFloat(3);
            String job = call.getString(4);
            --//输出
            System.out.println(name + "\t" + sal + "\t" + job );


        }catch(Exception e){
            e.printStackTrace();
        }finally{
            util.JDBCUtil.release(con,call,null);
        }
/*************************************out参数中使用光标******************************************/
/*
    光标:自定义参数类型
    使用:
    使用光标时,必须声明包结构,包结构包括包头(包声明、光标定义、函数或过程定义)和包体,
    包中可包含多个过程或者函数,类似于java中的接口包含多个方法,包体类似于接口实现

*/
/*包声明*/
create or replace package mypackage as
--自定义类型(使用光标cursor类型)
type empcursor for ref cursor;
  --定义过程或函数,可以多个
  procedure queryEmpList(eno int number,empList out empcursor);
  function getSal(eno int number,sal out number);
end mypackage;
/*包体实现*/
create or replace package body mypackage as
  --定义过程或函数,可以多个
  /*
       queryEmpList过程实现
  */
  procedure queryEmpList(eno int number,empList out empcursor)
  as
  begin
    --打开光标,将sql查询结果存入empLise
    open empList for select * from emp where empno = eno;
  end queryEMpList;
  /*
      getSal函数实现
  */
  function getSal(eno int number,sal out number)
  return number
  as
  psal emp.sal%type;
  begin
    select sal into psal from emp where empno = eno;
    return psal;
  end getSal;
  
end mypackage;
/*****************************************调用包中的过程或函数********************************************/
        String sql = "{call mypackage.queryEmpList(?,?)}";
        Connection con = null;
        CallableStatement call = null;
        ResultSet rs = null;
        try{
            --//获取连接
            con = JDBCUtil.getConnection();
            --//通过连接创建statement
            call = con.prepareCall(sql);
            --//处理入参in,赋值
            call.setInt(1,111);
            --//处理出参out,声明其类型自定义的类型使用的是光标cursor类型
            call.registerOutParameter(2, OracleTypes.CURSOR);
            --//执行过程
            call.execute();
            --//获取结果
            rs = ((OrcaleCallableStatement)call).getCursor(2);
            while(rs.next()){
               --取出员工的职位、姓名、工资
               String job = rs.getString("job");
               Float sal = rs.getFloat("sal");
               String name = rs.getString("name");
               --//输出
               System.out.println(name + "\t" + sal + "\t" + job );
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            util.JDBCUtil.release(con,call,null);
        }

猜你喜欢

转载自blog.csdn.net/tianguodk/article/details/79785972