存儲過程

一,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;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章