oracle存储过程

来源:互联网 发布:八国集团中国知乎 编辑:程序博客网 时间:2024/05/17 05:18
1. 返回值的区别,函数有1个返回值,而存储过程是通过参数返回的,可以有多个或者没有2.调用的区别,函数可以在查询语句中直接调用,而存储过程必须单独调用.函数一般情况下是用来计算并返回一个计算结果而存储过程一般是用来完成特定的数据操作(比如修改、插入数据库表或执行某些DDL语句等等)

http://blog.csdn.net/tender001/article/details/8069982
1.oracle存储过程结构 
[sql] view plaincopyprint?
  1. CREATE OR REPLACE PROCEDURE oracle存储过程名字  
  2. (  
  3.     参数1 IN NUMBER,  
  4.     参数2 IN NUMBER  
  5. IS  
  6. 变量1 INTEGER :=0;  
  7. 变量2 DATE;  
  8. BEGIN  
  9. END oracle存储过程名字  
 
2.无返回值的oracle存储过程
[sql] view plaincopyprint?
  1. create or replace procedure xs_proc_no is  
  2. begin  
  3.   insert into xuesheng values (3, 'wangwu', 90, 90);  
  4.   commit;  
  5. end xs_proc_no;  
 
3.有单个数据值返回的oracle存储过程
[sql] view plaincopyprint?
  1. create or replace procedure xs_proc(temp_name in varchar2,  
  2.                                     temp_num  out number) is  
  3.   num_1 number;  
  4.   num_2 number;  
  5. begin  
  6.   select yu_wen, shu_xue  
  7.     into num_1, num_2  
  8.     from xuesheng  
  9.    where xing_ming = temp_name;  
  10.   --dbms_output.put_line(num_1 + num_2);  
  11.   temp_num := num_1 + num_2;  
  12. end;  
其中,以上两种与sql server基本类似,而对于返回数据集时,上述方法则不能满足我们的要求。在Oracle中,一般使用ref cursor来返回数据集。示例代码如下:
 
4.有返回值的oracle存储过程(列表返回)
首先,建立我们自己的包。并定义包中的一个自定义ref cursor
[sql] view plaincopyprint?
  1. create or replace package mypackage as  
  2.   type my_cursor is ref cursor;  
  3. end mypackage;  
在定义了ref cursor后,可以书写我们的程序代码
[sql] view plaincopyprint?
  1. create or replace procedure xs_proc_list(shuxue   in number,  
  2.                                          p_cursor out mypackage.my_cursor) is  
  3. begin  
  4.   open p_cursor for  
  5.     select * from xuesheng where shu_xue > shuxue;  
  6. 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
  .
[sql] view plaincopyprint?
  1. ..  
  2.   IS  
  3.   CURSOR cur IS SELECT * FROM xxx;  
  4.   BEGIN  
  5.  FOR cur_result in cur LOOP  
  6.   BEGIN  
  7.    V_SUM :=cur_result.列名1+cur_result.列名2  
  8.   END;  
  9.  END LOOP;  
  10.   END;  
 
10.带参数的CURSOR
  
[sql] view plaincopyprint?
  1. CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;  
  2.   OPEN C_USER(变量值);  
  3.   LOOP  
  4.  FETCH C_USER INTO V_NAME;  
  5.  EXIT FETCH C_USER%NOTFOUND;  
  6.     do something  
  7.   END LOOP;  
  8.   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这个对象,代码如下:
 
[java] view plaincopyprint?
  1. String oracleDriverName = "oracle.jdbc.driver.OracleDriver";  
  2.    
  3.         // 以下使用的Test就是Oracle里的表空间  
  4.         String oracleUrlToConnect = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";  
  5.         Connection myConnection = null;  
  6.         try {  
  7.             Class.forName(oracleDriverName);  
  8.         } catch (ClassNotFoundException ex) {  
  9.             ex.printStackTrace();  
  10.         }  
  11.         try {  
  12.             myConnection = DriverManager.getConnection(oracleUrlToConnect,  
  13.                     "xxxx""xxxx");//此处为数据库用户名与密码  
  14.    
  15.         } catch (Exception ex) {  
  16.             ex.printStackTrace();  
  17.         }  
  18.         try {  
  19.                
  20.             CallableStatement proc=null;  
  21.             proc=myConnection.prepareCall("{call xs_proc(?,?)}");  
  22.             proc.setString(1"lisi");  
  23.             proc.registerOutParameter(2, Types.NUMERIC);  
  24.             proc.execute();  
  25.             String teststring=proc.getString(2);  
  26.             System.out.println(teststring);  
  27.    
  28.         } catch (Exception ex) {  
  29.             ex.printStackTrace();  
  30.         }  
对于列表返回值的oracle存储过程,在上述代码中做简单修改。如下
[java] view plaincopyprint?
  1. CallableStatement proc=null;  
  2.             proc=myConnection.prepareCall("{call getdcsj(?,?,?,?,?)}");  
  3.             proc.setString(1, strDate);  
  4.    proc.setString(2, jzbh);  
  5.             proc.registerOutParameter(3, Types.NUMERIC);  
  6.             proc.registerOutParameter(4, OracleTypes.CURSOR);  
  7.             proc.registerOutParameter(5, OracleTypes.CURSOR);  
  8.             proc.execute();  
  9.             ResultSet rs=null;  
  10.             int total_number=proc.getInt(3);  
  11.             rs=(ResultSet)proc.getObject(4);  
上述oracle存储过程修改完毕
 
7.Hibernate调用oracle存储过程
       
[java] view plaincopyprint?
  1. this.userManager.getHibernateTemplate().execute(  
  2.                new HibernateCallback() {  
  3.                    public Object doInHibernate(Session session)  
  4.                            throws HibernateException, SQLException {  
  5.                        CallableStatement cs = session  
  6.                                .connection()  
  7.                                .prepareCall("{call modifyapppnumber_remain(?)}");  
  8.                        cs.setString(1, foundationid);  
  9.                        cs.execute();  
  10.                        return null;  
  11.                    }  
  12.                });  
0 0
原创粉丝点击