zoukankan      html  css  js  c++  java
  • oracle存储过程

     一,oracle存储过程语法

     
    1.oracle存储过程结构 
    CREATE OR REPLACE PROCEDURE oracle存储过程名字
    (
        参数1 IN NUMBER,
        参数2 IN NUMBER
    ) IS
    变量1 INTEGER :=0;
    变量2 DATE;
    BEGIN
    END oracle存储过程名字
     
    2.无返回值的oracle存储过程
    create or replace procedure xs_proc_no is
    begin
      insert into xuesheng values (3, 'wangwu', 90, 90);
      commit;
    end xs_proc_no;
     
    3.有单个数据值返回的oracle存储过程
    create or replace procedure xs_proc(temp_name in varchar2,
                                        temp_num  out number) is
      num_1 number;
      num_2 number;
    begin
      select yu_wen, shu_xue
        into num_1, num_2
        from xuesheng
       where xing_ming = temp_name;
      --dbms_output.put_line(num_1 + num_2);
      temp_num := num_1 + num_2;
    end;
    其中,以上两种与sql server基本类似,而对于返回数据集时,上述方法则不能满足我们的要求。在Oracle中,一般使用ref cursor来返回数据集。示例代码如下:
     
    4.有返回值的oracle存储过程(列表返回)
    首先,建立我们自己的包。并定义包中的一个自定义ref cursor
    create or replace package mypackage as
      type my_cursor is ref cursor;
    end mypackage;
    在定义了ref cursor后,可以书写我们的程序代码
    create or replace procedure xs_proc_list(shuxue   in number,
                                             p_cursor out mypackage.my_cursor) is
    begin
      open p_cursor for
        select * from xuesheng where shu_xue > shuxue;
    end xs_proc_list;
     
    5.SELECT INTO STATEMENT
      将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条
      记录,否则抛出异常(若没有记录则抛出NO_DATA_FOUND)
      例子: 
      BEGIN
      SELECT name,age into 变量1,变量2 FROM user where xxx;
      EXCEPTION
      WHEN NO_DATA_FOUND THEN
          xxxx;
      END;
      ...
     
    6.IF 判断
      IF V_TEST=1 THEN
        BEGIN 
           do something
        END;
      END IF;
     
    7.WHILE 循环
      WHILE V_TEST=1 LOOP
      BEGIN
     XXXX
      END;
      END LOOP;
     
    8.变量赋值
      V_TEST := 123;
     
    9.用FOR IN 使用cursor
      ...
      IS
      CURSOR cur IS SELECT * FROM xxx;
      BEGIN
     FOR cur_result in cur LOOP
      BEGIN
       V_SUM :=cur_result.列名1+cur_result.列名2
      END;
     END LOOP;
      END;
     
    10.带参数的CURSOR
      CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;
      OPEN C_USER(变量值);
      LOOP
     FETCH C_USER INTO V_NAME;
     EXIT FETCH C_USER%NOTFOUND;
        do something
      END LOOP;
      CLOSE C_USER;
     
    11.用pl/sql developer debug
      连接数据库后建立一个Test WINDOW
      在窗口输入调用SP的代码,F9开始debug,CTRL+N单步调试
     

    二,oracle存储过程的若干问题备忘

     
    1.在oracle中,表别名不能加as,如:
    select a.name from user a;-- 正确
    select a.name from user as a;-- 错误
     应该是防止和oracle存储过程中的关键字as有冲突,才会这样规定吧!
    2.oracle存储过程中select某一字段时,后面必须要跟into,如果select整个记录,利用游标的话就另当别论了。
      select u.name into kn from user u where u.userid=uid and u.fatherid=fid;-- 有into,正确编译
      select u.name from user u where u.userid=uid and u.fatherid=fid;-- 没有into,编译报错,提示:Compilation 
      Error: PLS-00428: an INTO clause is expected in this SELECT statement
     
     
    3.在利用select...into...语法时,必须先确保数据库中有该条记录,否则会报出"no data found"异常。
       可以在该语法前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select...into...
    4.oracle在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错
    select name into kn from user where userid=aid and fatherid=fid;-- 正确运行
    select u.name into kn from user u where u.userid=userid and u.fatherid=fatherid;-- 运行时报错,提示
    ORA-01422:exact fetch returns more than requested number of rows
    5.在oracle存储过程中,关于出现null的问题
    假设有一个表A,定义如下:
    create table user(
    id varchar2(50) primary key not null,
    age number(5) not null,
    fid varchar2(50) not null -- 外键 
    );
    如果在oracle存储过程中,使用如下语句:
    select sum(age) into fage from user where fid='xxxxxx';
    如果user表中不存在fid="xxxxxx"的记录,则fage=null(即使fage定义时设置了默认值,如:fage number(5):=0依然无效,fage还是会变成null),这样以后使用fage时就可能有问题,所以在这里最好先判断一下:
    if fage is null then
        fage:=0;
    end if;
    这样就一切ok了。
     
     
    6.java调用oracle存储过程。其中,关键是使用CallableStatement这个对象,代码如下:
     
    String oracleDriverName = "oracle.jdbc.driver.OracleDriver";
     
            // 以下使用的Test就是Oracle里的表空间
            String oracleUrlToConnect = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
            Connection myConnection = null;
            try {
                Class.forName(oracleDriverName);
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            try {
                myConnection = DriverManager.getConnection(oracleUrlToConnect,
                        "xxxx", "xxxx");//此处为数据库用户名与密码
     
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            try {
                 
                CallableStatement proc=null;
                proc=myConnection.prepareCall("{call xs_proc(?,?)}");
                proc.setString(1, "lisi");
                proc.registerOutParameter(2, Types.NUMERIC);
                proc.execute();
                String teststring=proc.getString(2);
                System.out.println(teststring);
     
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    对于列表返回值的oracle存储过程,在上述代码中做简单修改。如下
    CallableStatement proc=null;
                proc=myConnection.prepareCall("{call getdcsj(?,?,?,?,?)}");
                proc.setString(1, strDate);
    proc.setString(2, jzbh);
                proc.registerOutParameter(3, Types.NUMERIC);
                proc.registerOutParameter(4, OracleTypes.CURSOR);
                proc.registerOutParameter(5, OracleTypes.CURSOR);
                proc.execute();
                ResultSet rs=null;
                int total_number=proc.getInt(3);
                rs=(ResultSet)proc.getObject(4);
    上述oracle存储过程修改完毕
     
    7.Hibernate调用oracle存储过程
            this.userManager.getHibernateTemplate().execute(
                    new HibernateCallback() {
                        public Object doInHibernate(Session session)
                                throws HibernateException, SQLException {
                            CallableStatement cs = session
                                    .connection()
                                    .prepareCall("{call modifyapppnumber_remain(?)}");
                            cs.setString(1, foundationid);
                            cs.execute();
                            return null;
                        }
                    });
  • 相关阅读:
    DevOps与:cloud,IaC,Container,Microservices, Serverless
    2020年devops的7个发展趋势
    bash极简教程
    Jenkins pipeline jenkinsfile的两种写作方式声明式和脚本式
    Jenkins pipeline之声明式的jenkinsfile
    Linux基本开发环境配置git,c++,nodejs,nginx
    Linux centos8 VPS基本配置之SSH
    DevOps常用工具网址
    DevOps技能自查表
    DevOps的工作岗位的要求
  • 原文地址:https://www.cnblogs.com/meimao5211/p/3379412.html
Copyright © 2011-2022 走看看