數據庫之存儲過程


1.存儲過程語法

Oracle存儲過程基本語法存儲過程

  1 CREATE OR REPLACE PROCEDURE 存儲過程名

  2 IS

  3 BEGIN

  4 NULL;

  5 END;

 

行1:

  CREATE OR REPLACE PROCEDURE 是一個SQL語句通知Oracle數據庫去創建一個叫做skeleton存儲過程, 如果存在就覆蓋它;

行2:

  IS關鍵詞表明后面將跟隨一個PL/SQL體。

行3:

  BEGIN關鍵詞表明PL/SQL體的開始。

行4:

  NULL PL/SQL語句表明什么事都不做,這句不能刪去,因為PL/SQL體中至少需要有一句;

行5:

END關鍵詞表明PL/SQL體的結束

 

存儲過程創建語法:

create orreplace procedure 存儲過程名(param1 in type,param2 out type)

as

變量1 類型(值范圍);--vs_msg VARCHAR2(4000);

變量2 類型(值范圍);

 

 

Begin

Select count(*)into 變量1 from 表A where列名=param1;

 

If (判斷條件) then

Select 列名 into 變量2 from 表A where列名=param1;

Dbms_output。Put_line(‘打印信息');

Elsif (判斷條件) then

Dbms_output。Put_line(‘打印信息');

Else

Raise 異常名(NO_DATA_FOUND);

End if;

Exception

When others then

Rollback;

End;

 

 

例子2

create orreplace procedure EMP_PROCEDURE2(

eno number,  --輸入參數,

    name varchar2,

   

)

IS

    emp_null_error EXCEPTION;  --聲明異常變量

    PRAGMA EXCEPTION_INIT(emp_null_error,-1400);--非預定義異常,前提:deptno列非空。插入空值會報錯

    emp_no_deptno EXCEPTION;  --聲明異常變量

PRAGMA EXCEPTION_INIT(emp_no_deptno, -2291);--非預定義異常,

begin

       insert into emp(empno,ename,sal,deptno)values (eno,name,sal,dno);

exception

    when DUP_VAL_oN_INDEX then

        RAISE_APPLICATION_ERROR(-20000,'該雇員已存在');

    when emp_null_error then

        RAISE_APPLICATION_ERROR(-20001,'部門編號不能為空');       

    when emp_no_deptno then

        RAISE_APPLICATION_ERROR(-20002,'不存在該部門編號');                     

end;

 

 

 

EXECUTEEMP_PROCEDURE2(1001,'榮世林',2000,10);

 

 

注意事項:

1, 存儲過程參數不帶取值范圍,in表示傳入,out表示輸出

類型可以使用任意Oracle中的合法類型。

2, 變量帶取值范圍,后面接分號

3, 在判斷語句前最好先用count(*)函數判斷是否存在該條操作記錄

4, 用select 。。。into。。。給變量賦值

5, 在代碼中拋異常用 raise+異常名

 

 

 

 

 

 

2.CallableStatement 執行存儲過程

 

 

概述

如果想要執行存儲過程,我們應該使用 CallableStatement 接口。

CallableStatement 接口繼承自 PreparedStatement 接口。所以 CallableStatement 接口

包含有 Statement 接口和 PreparedStatement 接口定義的全部方法,但是並不是所有的方法我

們都要使用,主要使用的方法有這樣幾個:

2.1常用方法

 

 

返回類型

方法簽名

說明

boolean

execute()

執行 SQL 語句,如果第一個結果是 ResultSet 對

象,則返回 true;如果第一個結果是更新計數或者沒

有結果,則返回 false

void

registerOutParameter

(int parameterIndex,

int sqlType)

按順序位置 parameterIndex 將 OUT 參數注冊為

JDBC 類型 sqlType,sqlType 為 Types 類中的常量

Type

getType(int

parameterIndex)

根據參數的序號獲取指定的 JDBC 參數的值。第一

個參數是 1,第二個參數是 2,依此類推

 

 

 

我們可以使用 execute()方法來執行存儲過程。CallableStatement 為所有的數據庫提供了

一種統一的標准形式調用存儲過程。所以,你將會看到我們使用 execute()調用存儲過程的語

法與在 Oracle 中會所有不同。

為了獲得存儲過程或函數的返回值,我們需要使用registerOutParameter()方法將返回的

參數注冊為 JDBC 的類型。 registerOutParameter()方法的第一個參數是參數的序號,第一個

為 1,第二個為 2,以此類推。第二個參數需要一個 int 值,用來標記 JDBC 的類型,我們可以

使用 java.sql.Types 類中的常量來設置這個參數。比如 VARCHAR、DOUBLE 等類型。如果類型不

夠用,也可以從具體數據庫的驅動中尋找合適的類型常量。如果存儲過程或函數有返回值,這

個方法是必須要調用的,否則無法得到返回值,甚至會發生異常。

CallableStatement 接口中定義了很多 get 方法,用於獲取存儲過程返回的值,根據值的

類型不同,你可以使用不同 get 方法,比如 getInt()、getString()、getDouble()等等。

我們看一下使用 CallableStatement 接口執行存儲過程和函數的語法格式。

存儲過程:{call<procedure-name>[(<arg1>,<arg2>, ...)]}

函數:{?= call<procedure-name>[(<arg1>,<arg2>, ...)]}

如果要調用存儲過程,則使用第一種語法,就是開頭不帶問號的語法,call 后面是過程名,

如果沒有參數,可以省略小括號。

如果要調用函數,則使用第二種語法,開頭帶有一個問號加等號,實際上這個問號就是一

個占位符,這個問號總是調用函數的第一個占位符。其它部分與過程的語法相同。

這樣說起來可能比較抽象,我們通過代碼來學習一下。

2.2執行存儲過程

(1) 執行不帶參但是有返回值的存儲過程

存儲過程代碼如下:

create or replaceprocedure getNewsCount(v_totalCount out number) as

begin

select count(*) intov_totalCount from news_detail;

end;

 

該 存 儲 過 程 為 查 詢 新 聞 明 細 表 (news_detail) 中新 聞 的 總 記 錄 數 , 並 將 結 果 存 儲 在

v_totalCount 中返回。執行該存儲過程的代碼如下:

//獲取新聞總數量(執行存儲過程)

public intgetTotalCountProc(){

int totalCount=0;

CallableStatementproc=null;

Stringsql="{call getNewsCount(?)}";

getConnection();

try {

proc=conn.prepareCall(sql);

proc.registerOutParameter(1,Types.INTEGER);

proc.execute();

totalCount=proc.getInt(1);

} catch (SQLExceptione) {

e.printStackTrace();

}

return totalCount;

}

(2) 執行帶參帶返回值的存儲過程

存儲過程代碼如下:

create or replaceprocedure getNewsCount(v_categoryId in number,v_title   in varchar2,v_totalCount out number) as

begin

if (v_categoryId = 0)then

select count(*) intov_totalCount from news_detail

where title like'%'||v_title||'%';

else

select count(*) intov_totalCount from news_detail

where categoryId =v_categoryId

and title like'%'||v_title||'%';

end if;

end;

該存儲過程為根據新聞類別 ID(categoryId)以及新聞標題(title)查詢新聞明細表

(news_detail)中新聞的總記錄數,並將結果存儲在 v_totalCount 中返回。其中,新聞類別以

及新聞標題分別以輸入參數的形式傳入存儲過程。執行該存儲過程的代碼如下:

//根據新聞類別 ID 以及新聞標題獲取新聞總記錄數

public intgetTotalCount(int categoryId, String title) {

int iCount = 0;

CallableStatementproc = null;

try {

String sql ="{call getNewsCount(?,?,?)}";

getConnection();

proc =conn.prepareCall(sql);

proc.setInt(1,categoryId);

proc.setString(2,title);

proc.registerOutParameter(3,Types.INTEGER);

proc.execute();

iCount =proc.getInt(3);

} catch (Exception e){

e.printStackTrace();

}finally{

if (proc != null){

try {

proc.close();

} catch (SQLExceptione) {

e.printStackTrace();

}

}

closeResource();

}

return iCount;

}

(3) 執行返回值為游標的存儲過程

Employees 雇員表(name 雇員姓名;gender 雇員性別;borndate 雇員生日)

存儲過程代碼如下:

create or replaceprocedure find_emp3(emp_cursor out sys_refcursor) is

begin

open emp_cursor forselect name,gender,borndate from employees;

end find_emp3;

該存儲過程為查詢所有雇員姓名、性別、生日的存儲過程,結果以游標的形式返回。執行

該存儲過程的代碼如下:

String sql ="{call find_emp3(?)}";

Connection con =null;

CallableStatementcstmt = null;

ResultSet rs = null;

try {

Class.forName("oracle.jdbc.OracleDriver");

con = DriverManager 個.getConnection(

"jdbc:oracle:thin:@localhost:1521:orcl","pbdevj","pwd1234");

cstmt =con.prepareCall(sql);

cstmt.registerOutParameter(1,oracle.jdbc.OracleTypes.CURSOR);

cstmt.execute();

rs =(ResultSet)cstmt.getObject(1);

while (rs.next()) {

//省略

}

} catch { //省略 } finally { //省略 }

(4) 執行函數

函數代碼如下:

create or replacefunction find_emp2(emp_no number) return varchar2 is

empname varchar2(20);

 

 

 

begin

select name intoempname from employees where id=emp_no;

return empname;

exception

when no_data_foundthen

return '雇員編號未找到';

end find_emp2;

該函數功能為根據雇員 id 返回姓名。執行該函數的代碼如下:

String sql ="{?=call find_emp2(?)}";

Connection con =null;

CallableStatementcstmt = null;

try {

Class.forName("oracle.jdbc.OracleDriver");

con =DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:orcl","pbdevj","pwd1234");

cstmt =con.prepareCall(sql);

cstmt.setInt(2, 1);

cstmt.registerOutParameter(1,Types.VARCHAR);

cstmt.execute();

System.out.println(cstmt.getString(1));

} catch { //省略 } finally { //省略 }

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM