• Oracle存储过程和自定义函数笔记


    学习地址:https://www.imooc.com/learn/370

    存储过程和存储函数定义:指存储在数据库中供所有用户程序调用的子程序叫做存储过程
    、存储函数。

    相同点:完成特定功能的程序。
    区别:是否用return语句返回值。

    语法
    create [or replace] procedure 过程名(参数列表)
    as
    plsql程序体


    create or replace procedure sayhelloworld
    as
    --说明部分

    begin
    dbms_output.put_line('Hello World');
    end;


    调用存储过程
    1.exec sayhelloworld();
    2.begin
    sayhelloworld();
    sayhelloworld();
    end;

    1 exec 存储过程名();2 begin 存储过程名();end /


    创建带参数的存储过程
    -- 给指定的员工涨100块钱的工资,并且打印涨前后涨后的薪水 eno:员工号
    create or replace procedure raisesalary(eno in number) -- in 这是一个输入参数
    as
    -- 定义一个变量保存涨前的薪水
    psal emp.sal%type;
    begin
    -- 得到员工涨前的薪水
    select sal into psal from emp where empno=eno;
    -- 给该员工涨100块钱
    update emp set sal=sal+100 where empno=eno;
    -- 一般,这里不需要 commit ! 也不需要 rollback
    -- 注意:一般不在存储过程或者存储函数中,commit 和 rollback
    -- 打印
    dbms_output.put_line('涨前:'||psal||',涨后:'||(psal+100));
    end;
    /
    -- 调用:
    begin
    raisesalary(7839);
    raisesalary(7566);
    end;
    /

    一般不在存储过程中提交或者回滚,大多时间是在调用一次或者多次的时候提交或者回滚
    ,这样会防止出现意外情况。


    创建存储函数的语法

    示例:根据员工号,查询员工年收入。

    create or replace function queryempincom(eno in numbr)

    return number

    as

    --定义变量保存员工的薪水和奖金

    psal emp.sal%type;

    pcomm emp.comm%type;

    begin

    --得到该员工的月薪和奖金
    select sal,comm into pasl,pcomm from emp where empno=eno;

    --直接返回年收入
    return psal*12+nvl(pcomm,0);

    end;


    存储过程和存储函数都可以通过Out指定一个或多个输出参数。我们可以利用out参数,在
    过程和函数中实现返回多个值。


    存储过程可以通过out参数返回值。

    什么时候用存储过程、存储函数?


    一般原则:如果只有一个返回值,用存储函数;否则,用存储过程。


    示例:
    create or replace procedure queryempinfor(eno in number,pename out varchar2,
    psal out number,pjob out varchar2)
    as
    begin
    -- 得到该员工的姓名、月薪和职位
    select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
    end;

    使用JDBC连接数据库

    public class JDBCUtile{
      private static String driver="orable.jdbc.OracleDriver";
      private static String url="jdbc:oracle:thin:@192.168.56.101:1521:orcl";
      private static String user="scott";
      private static String password="tiger";
      // 注册数据库的驱动
      static{
          try{
             Class.forName(driver);
             // --> DriverManager.registerDriver(driver);
          }catch(ClassNotFoundException e){
             throw new ExceptionInInitializerError(e);
          }
      }  // 获取数据库连接
      public static Connection getConnection(){
          try{ 
             return DriverManager.getConnection(url,user,password);
          }catch(SQLException e){e.printStackTrace(); }
             return null;
      }
    
    // 释放数据库的资源
      public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs != null){try{ rs.close();}catch(SQLException e){e.printStackTrace();}finally{rs=null;}}
        if(st != null){try{st.close();}catch(SQLException e){e.printStackTrace();}finally{st=null;}}
        if(conn != null){try{conn.close();}catch(SQLException e){e.printStackTrace();}finally{conn=null;}}
        }
    }

    在应用程序中访问存储过程和存储函数

    使用CallachleStatement接口

    public void testProcedure(){
    //{call <procedure-name>[(<arg1>,<arg2>,...)]}
    String sql="call queryempinform(?,?,?,?)";
    Connection conn=null;
    CallableStatement call=null;
    try{
    // 得到一个连接
    conn=JDBCUtils.getConnection();
    // 通过连接创建出statement
    call=conn.prepareCall(sql);
    // 对于in参数,需赋值,对于out参数,需要申明
    call.setInt(1, 7839); // 设置第一个?为 7839
    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(Exception e){
    e.printStackTrace();
    }finally{
    JDBCUtils.release(conn,call,null);
    }
    }

     在out参数中使用光标:

    包头:
    CREATE OR REPLACE PACKAGE MYPACKAGE AS 
        type empcursor is ref cursor;
        procedure queryEmpList(dno in number,empList out empcursor);
    END MYPACKAGE;
    包体(需要实现包头中声明的所有方法,包括存储函数、存储方法):
    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;  
    -- 使用desc查看程序包的结构
     desc MYPACKAGE

    所有存储函数的功能都可以有存储过程来代替,为什么在oracle数据库中依然保留存储函数?
    原因:数据库版本升级所造成,版本升级最基本的要求就是要向前向下兼容,在oracle数据库最早的版本中是有存储过程和存储函数的区别。如果新版本不支持存储函数,那么老的数据库中若存在存储函数就可能运行出错。

  • 相关阅读:
    MySQL插入数据获得自动增长的ID
    C#解决“System.Threading.ThreadStateException:“在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式。请确保您的 Main 函数带有 STAThreadAttribute 标记。 只有将调试程序附加到该进程才会引发此异常”的异常
    C# 关闭当前窗体的时候打开另一个窗口
    C# WinForm中关闭指定的窗体
    MySQL 8.0 版本修改字符编码
    微信支付API v3接口使用应用篇
    Linux Tomcat安装篇(daemon运行,开机自启动)
    Linux nginx安装篇
    SpringCloud系列之Nacos+Dubbo+Seata应用篇
    SpringCloud系列之Nacos+Dubbo应用篇
  • 原文地址:https://www.cnblogs.com/jiliunyongjin/p/8408918.html
Copyright © 2020-2023  润新知