在大型數據庫系統中,有兩個很重要做用的功能,那就是存儲過程和觸發器。在數據庫系統中不管是存儲過程仍是觸發器,都是經過SQL 語句和控制流程語句的集合來完成的。相對來講,數據庫系統中的觸發器也是一種存儲過程。存儲過程在數據庫中運算時自動生成各類執行方式,所以,大大提升了對其運行時的執行速度。在大型數據庫系統如Oracle、SQL Server中都不只提供了用戶自定義存儲過程的功能,同時也提供了許多可做爲工具進行調用的系統自帶存儲過程。
所謂存儲過程(Stored Procedure),就是一組用於完成特定數據庫功能的SQL 語句集,該SQL語句集通過編譯後存儲在數據庫系統中。在使用時候,用戶經過指定已經定義的存儲過程名字並給出相應的存儲過程參數來調用並執行它,從而完成一個或一系列的數據庫操做。
因爲J2EE體系通常創建大型的企業級應用系統,而通常都配備大型數據庫系統如Oracle或者SQL Server,在本文《JAVA與Oracle存儲過程》中將介紹JAVA跟Oracle存儲過程之間的相互應用跟相互間的各類調用。
1、JAVA調用Oracle存儲過程
JAVA跟Oracle之間最經常使用的是JAVA調用Oracle的存儲過程,如下簡要說明下JAVA如何對Oracle存儲過程進行調用。
Ⅰ、不帶輸出參數狀況
過程名稱爲pro1,參數個數1個,數據類型爲整形數據
html
import
java.sql.
*
;
public
class
ProcedureNoArgs
{
public static void main(String args[]) throws Exception
{
// 加載Oracle驅動
DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver());
// 得到Oracle數據庫鏈接
Connection conn = DriverManager.getConnection( " jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd " );
// 建立存儲過程的對象
CallableStatement c = conn.divpareCall( " {call pro1(?)} " );
// 給Oracle存儲過程的參數設置值 ,將第一個參數的值設置成188
c.setInt( 1 , 188 );
// 執行Oracle存儲過程
c.execute();
conn.close();
}
}
Ⅱ、帶輸出參數的狀況
過程名稱爲pro2,參數個數2個,數據類型爲整形數據,返回值爲整形類型java
import
java.sql.
*
;
public
class
ProcedureWithArgs
{
public static void main(String args[]) throws Exception
{
//加載Oracle驅動
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
//得到Oracle數據庫鏈接
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd ");
//建立Oracle存儲過程的對象,調用存儲過程
CallableStatement c=conn.divpareCall("{call pro2(?,?)}");
//給Oracle存儲過程的參數設置值 ,將第一個參數的值設置成188
c.setInt(1,188);
//註冊存儲過程的第二個參數
c.registerOutParameter(2,java.sql.Types.INTEGER);
//執行Oracle存儲過程
c.execute();
//獲得存儲過程的輸出參數值並打印出來
System.out.println (c.getInt(2));
conn.close();
}
}
Oracle存儲過程包含三部分:過程聲明,執行過程部分,存儲過程異常。sql
Oracle存儲過程能夠有無參數存儲過程和帶參數存儲過程。
一、無參程序過程語法數據庫
1
create
or
replace
procedure
NoParPro
2
as
;
3
begin
4
;
5
exception //存儲過程異常
6
;
7
end
;
8
2、帶參存儲過程實例
1
create
or
replace
procedure
queryempname(sfindno emp.empno
%
type)
as
2
sName emp.ename
%
type;
3
sjob emp.job
%
type;
4
begin
5
....
7
exception
....
14
end
;
15
3、 帶參數存儲過程含賦值方式
1
create
or
replace
procedure
runbyparmeters (isal
in
emp.sal
%
type,
sname out
varchar
,sjob
in
out
varchar
)
2
as
icount
number
;
3
begin
4
select
count
(
*
)
into
icount
from
emp
where
sal
>
isal
and
job
=
sjob;
5
if
icount
=
1
then
6
....
9
else
10
....
12
end
if
;
13
exception
14
when
too_many_rows
then
15
DBMS_OUTPUT.PUT_LINE(
'
返回值多於1行
'
);
16
when
others
then
17
DBMS_OUTPUT.PUT_LINE(
'
在RUNBYPARMETERS過程當中出錯!
'
);
18
end
;
19
4、在Oracle中對存儲過程的調用
過程調用方式一
1
declare
2
realsal emp.sal
%
type;
3
realname
varchar
(
40
);
4
realjob
varchar
(
40
);
5
begin //存儲過程調用開始
6
realsal:
=
1100
;
7
realname:
=
''
;
8
realjob:
=
'
CLERK
'
;
9
runbyparmeters(realsal,realname,realjob); --
必須按順序
10
DBMS_OUTPUT.PUT_LINE(REALNAME
||
'
'
||
REALJOB);
11
END
; //過程調用結束
12
過程調用方式二
1
declare
2
realsal emp.sal
%
type;
3
realname
varchar
(
40
);
4
realjob
varchar
(
40
);
5
begin //過程調用開始
6
realsal:
=
1100
;
7
realname:
=
''
;
8
realjob:
=
'
CLERK
'
;
9
runbyparmeters(sname
=>
realname,isal
=>
realsal,sjob
=>
realjob); --
指定值對應變量順序可變
10
DBMS_OUTPUT.PUT_LINE(REALNAME
||
'
'
||
REALJOB);
11
END
; //過程調用結束
12
至此,有關ORACLE的基本存儲過程以及對Oracle存儲過程的調用方式介紹完畢。
剛去到新公司幾天,昨天老大讓我想一下,如今有50多個存儲,須要經過輸入的參數不一樣,調用不用的存儲過程。工具
開始的時候,想都沒想直接用了if-then-elsif-then-else-end if,後來被說了,太不專業了,由於有五十多個,因此整個版面看上去,至關的沒有可觀度且至關的不專業。 post
後來,經提點,把這個存儲過程的名字跟參數名存到一個表中,而後根據傳入的參數查找相應的存儲過程再調用存儲過程便可。回家作了下實驗,以下:測試
create table p_proc
(pid
number(2),
pname varchar2(20),
pname_class varchar2(20)); --用於存儲存儲過程和參數名的表並插入四條數據,
insert into p_proc values(1,'A','V1');
insert into p_proc values(2,'B','V2');
insert into p_proc values(3,'C','V3');
insert into p_proc values(4,'D','V4');
四個存儲過程的的情況爲:url
CREATE OR REPLACE PROCEDURE V1(v_para varchar2)
AS
BEGIN
DBMS_OUTPUT.put_line(v_para);
END;
CREATE OR REPLACE PROCEDURE V2(v_para varchar2)
AS
BEGIN
DBMS_OUTPUT.put_line(v_para);
END;
CREATE OR REPLACE PROCEDURE V3(v_para varchar2)
AS
BEGIN
DBMS_OUTPUT.put_line(v_para);
END;
CREATE OR REPLACE PROCEDURE V4(v_para varchar2)
AS
BEGIN
DBMS_OUTPUT.put_line(v_para);
END;
以下調用存儲過程的存儲爲(請忽略一些測試輸出):
CREATE OR REPLACE PROCEDURE PRE1(v_para varchar2)
AS
v_pname_class varchar2(20);
v_message varchar2(30);
v_str_proc varchar2(50);
BEGIN
SELECT pname_class into v_pname_class
FROM P_PROC WHERE PNAME=v_para;
BEGIN
IF SQL%FOUND THEN
v_message := 'aaa';
END IF;
EXCEPTION
WHEN OTHERS THEN
v_pname_class := null;
END;
dbms_output.put_line(v_pname_class||'abc');
v_str_proc := 'BEGIN ' ||v_pname_class || '('''|| v_para || '''); end;'; --構造匿名塊的執行存儲過程
dbms_output.put_line(v_str_proc);
dbms_output.put_line(v_message);
execute immediate v_str_proc; --主要是執行存儲過程
END PRE1;
使用一個匿名塊調用
BEGIN
PRE1('A'); --PRE1('B')/PRE1('C')/PRE1('D');
END;
上面主要的地方我已經加粗和紅色標記了,代碼很簡單,我就不解釋了。
好了,寫完了,今天中秋,明天開始國慶,祝你們雙節嗨皮~~
出處:oracle中經過傳入的參數調用表中存存放的存儲過程名