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