zoukankan      html  css  js  c++  java
  • 存储过程,存储函数(Oracle)

    存储过程和存储函数
    指存储在数据库中供所有用户程序调用的子程序叫存储过程、存储函数。
    存储过程和存储函数的区别?
    存储函数:可以通过return 语句返回函数值。
    存储过程:不能
    除此之外我们可以认为他们是完全一样的。
     
    存储过程
    1、创建存储过程
    用create procedure命令简历存储过程。
    语法:
    create [or replace] procedure 过程名(参数列表)
    as
        PLSQL子程序体;
     
    打印hello word
    --打印hello world
    create or replace procedure sayhelloworld
    as 
      --说明部分
    begin 
      dbms_output.put_line('hello world');
    end;
    /

    编译后:

    2、调用存储过程方法:
    1、exec 过程名
    2、begin
                过程名;
                过程名;
          end;
           /
     
    测试调用存储过程
    --连接数据库
    C:WINDOWSsystem32>sqlplus scott/tiger@192.168.56.101:1521/orcl
    SQL>--调用方式一
    SQL> set serveroutput on
    SQL> exec sayhelloworld;
    hello world
    
    PL/SQL 过程已成功完成。
    
    SQL> --调用方式二:
    SQL> begin
      2      sayhelloworld();
      3      sayhelloworld();
      4  end;
      5  /
    hello world
    hello world
    
    PL/SQL 过程已成功完成。

    带参数的存储过程:

    --给指定员工薪水涨100,并且打印涨前和涨后的薪水
    create or replace procedure raiseSalary(eno in number) --in为输入参数
    as 
      --说明部分
      psal emp.sal%type;
    
    begin
      --得到涨前的薪水
      select sal into psal from emp where empno=eno;
    
      update emp set sal=sal+100 where empno=eno;
    
      --要不要commit?
      --为保证在同一事务中,commit由谁调用谁提交
      dbms_output.put_line('涨前:'||psal||'  涨后:'||(psal+100));
    end;
    /

    测试:

    存储函数
    函数(function)为一命名的存储程序,可带参数,并返回一计算值。函数和过程的结构类似,但必须有一个return子句,用于返回函数值。函数说明要指定函数名、结果值的类型,以及参数类型等。
    存储函数语法:
    create[or replace] functiion 函数名(参数列表) 
    return函数值类型
    as
        PLSQL子程序体;
     
    查询员工年收入
    --查询某个员工的年收入
    create or replace function queryempincome(eno in number)
    return number
    as
      --月薪和奖金
      psal   emp.sal%type;
      pcomm  emp.comm%type;
    begin
      select sal,comm into psal,pcomm from emp where empno=eno;
      --返回年收入
      return psal*12+nvl(pcomm,0);
    end;
    /

    测试:

    过程和函数中的in 和out
    一般来讲,过程和函数的区别在于函数可以有一个返回值;而过程没有返回值。
    但过程和函数都可以通过out指定一个或多个输出参数,我们可以利用out参数,在过程和函数中实现返回多个值。
    什么时候用存储过程/存储函数?
    原则(不是必须的):
        如果只有一个返回值,用存储函数;否则,就用存储过程。
     
    存储过程
    create or replace procedure queryEmpInfo(eno in number,
                                             pname out varchar2,
                                             psal  out number,
                                             pjob  out varchar2)
    as 
    begin
      select ename,sal,empjob into pname,psal,pjob from emp where empno=eno;
    end;

    测试

    使用java程序调用存储过程

    /*
         * 存储过程
         * create or replace procedure queryEmpInfo(eno in number,
         *                                     pename out varchar2,
         *                                     psal out number,
         *                                     pjob out varchar2)
         */
        @Test
        public void testProcedure() {
           // {call <procedure-name>[(<arg1>,<arg2>, ...)]}
           String sql = "{call queryEmpInfo(?,?,?,?)}";
           CallableStatement call = null;
           Connection connection = JDBCUtils.getConnection();
           try {
               call = connection.prepareCall(sql);
              
               //对于in参数,赋值
               call.setInt(1, 7839);
              
               //对于out参数,声明
               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 (SQLException e) {
               e.printStackTrace();
           }finally{
               JDBCUtils.release(connection, call, null);
           }
        }

    使用java程序调用存储函数

    /*
         * 存储函数
         * create or replace function queryEmpIncome(eno in number) 
           return number
         */
        @Test
        public void testFunction() {
           // {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
           String sql = "{?=call queryEmpIncome(?)}";
           Connection conn = null;
           CallableStatement call = null;
           try {
               conn = JDBCUtils.getConnection();
               call = conn.prepareCall(sql);
     
               //对于out参数,赋值
               call.registerOutParameter(1, OracleTypes.NUMBER);
              
               //对于in参数,赋值
               call.setInt(2, 7839);
              
               //执行
               call.execute();
              
               //取出数据
               double income = call.getDouble(1);
               System.out.println(income);
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               JDBCUtils.release(conn, call, null);
           }
        }
    在out参数中使用光标
    问题:查询某个部门中所有员工的所有信息
    1、申明包结构
    CREATE OR REPLACE 
    PACKAGE MYPACKAGE AS 
    
      type empcursor is ref cursor;
      --创建存储过程,输出参数为自定义类型
      procedure queryEmpList(dno in number,empList out empcursor);
    
    END MYPACKAGE;

    2、创建包体(实现)

    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;
    使用java调用带包的存储过程
    public void testCursor() {
           // {call <procedure-name>[(<arg1>,<arg2>, ...)]}
          
           String sql = "{call MYPACKAGE.queryEmpList(?,?)}";
           Connection conn = null;
           CallableStatement call = null;
           ResultSet rs = null;
           try {
               conn = JDBCUtils.getConnection();
               call = conn.prepareCall(sql);
     
               //对于in参数,赋值ֵ
               call.setInt(1, 20);
     
               //对于out参数,赋值
               call.registerOutParameter(2, OracleTypes.CURSOR);
     
               //执行
               call.execute();
     
               // 取出结果
               rs = ((OracleCallableStatement)call).getCursor(2);
               while(rs.next()){
                  String name = rs.getString("ename");
                  double sal = rs.getDouble("sal");
                  System.out.println(name+"	"+sal);
               }
           } catch (Exception e) {
               e.printStackTrace();
           } finally {
               JDBCUtils.release(conn, call, rs);
           }
        }

    此案例光标没有关闭,原因:当resultSet关闭的时候 光标就close了

  • 相关阅读:
    sublime打开txt文件乱码的问题
    while循环小例
    mongoDB内置文档定义
    WebStorm 10.0.3注册码
    angularjs之ng-mode获取lobject类型里的键值
    前端打印console
    js去掉数组的空字符串
    js数组去重的三种方式的比较
    js数据类型之判断
    Bootstrap中的datetimepicker浅谈
  • 原文地址:https://www.cnblogs.com/dooor/p/5599351.html
Copyright © 2011-2022 走看看