oracle 儲存過程呼叫 執行
SQL中呼叫儲存過程語句:
call procedure_name();
呼叫時”()”是不可少的,無論是有引數還是無引數。
定義對資料庫過程的呼叫時 無引數過程:{ call procedure_name} 僅有輸入引數的過程:{call procedure_name(?,?...)} 這裡?表示輸入引數,建立儲存過程時用in表示輸入引數
僅有輸出引數的過程:{ Call procedure_name(?,?...)} 這裡的?表示輸出引數,建立儲存過程時用out表示輸入引數
既有輸入引數又有輸出引數的過程 {call procedure_name(?,?...)} 這裡的?有表示輸出引數的,也有表示輸入引數的
下面將會對這4種情況分別舉出例項!!!
引數過程例項
無引數儲存過程:
create or replace procedure stu_proc as
pname varchar2(25);
begin
select sname into pname from student where sno=1;
dbms_output.put_line(pname);
end;
或者
create or replace procedure stu_proc as
pname student.sname%type;
begin
select sname into p_name from student where sno=1;
dbms_output.put_line(pname);
end;
引數過程例項
僅有輸入引數的過程
create or replace procedure stu_proc1(pno in student.sno%type) as
pname varchar2(25);
begin
select sname into pname from student where sno=pno;
dbms_output.put_line(pname);
end;
引數過程例項
僅有輸出引數的儲存過程
create or replace procedure stu_proc2(pname out student.sname%type) as
begin
select sname into pname from student where sno=1;
dbms_output.put_line(pname);
end;
此種儲存過程不能直接用call來呼叫,這種情況的呼叫將在下面oracle函式呼叫中說明
引數過程例項
有輸入\輸出引數的儲存過程:
create or replace procedure stu_proc3
(pno in student.sno%type,pname out student.sname%type) as
begin
select sname into pname from student where sno=pno;
dbms_output.put_line(pname);
end;
此種儲存過程不能直接用call來呼叫,這種情況的呼叫將在下面oracle函式呼叫中說明
Oracle函式呼叫儲存過程
我們已經學習了oracle函式,下面就針對引數的4種情況分別舉出例項說明函式對儲存過程的呼叫
函式呼叫儲存過程例項
對無引數過程的呼叫:
--函式
create or replace function get_pname return varchar2 is
pname varchar2(20);
begin
stu_proc;
select sname into pname from student where sno=1;
return pname;
end;
--呼叫
declare
begin
dbms_output.put_line('在PL/SQL中列印的結果:'||get_pname);
end;
函式呼叫儲存過程例項
對有輸入引數過程的呼叫:
create or replace function get_pname1(pno in number) return varchar2 is
pname varchar2(20);
begin
stu_proc1(pno in student.sno%type)
select sname into pname from student where sno=pno;
return pname;
end;
--呼叫
declare
begin
dbms_output.put_line('在PL/SQL中列印的結果:'||get_pname1(2));
end;
函式呼叫儲存過程例項
對有輸出引數過程的呼叫:
create or replace function get_pname2(pname out varchar2) return varchar2 is
begin
stu_proc2(pname out student.sname%type);
return pname;
end;
--呼叫
declare
pname student.sname%type;
begin
dbms_output.put_line('在PL/SQL中列印的結果:'||get_pname2(pname));
end;
函式呼叫儲存過程例項
對有輸入\輸出引數過程的呼叫:
create or replace function get_pname3(pno in number,pname out varchar2) return varchar2 is
begin
stu_proc3(pno in student.sno%type,pname out student.sname%type);
return pname;
end;
--呼叫
declare
pname student.sname%type;
begin
dbms_output.put_line('在PL/SQL中列印的結果:'||get_pname3(2,pname));
end;
JAVA呼叫資料庫儲存過程
前面我們已經講述了有關oracle資料庫的儲存過程的幾種形式,以及oracle函式對儲存過程的呼叫,下面我將根據上面儲存過程的例項來舉出JAVA對oracle儲存過程的呼叫
JAVA呼叫例項
僅有返回值的過程:
public static void main(String[] args) {
Connection conn=BBConnection.getConnection();
String sql="{call stu_proc2(?)}";
try {
CallableStatement statement=conn.prepareCall(sql);
statement.registerOutParameter(1,Types.VARCHAR);
statement.execute();
String pname=statement.getString(1);
System.out.println(pname);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
JAVA呼叫例項
既有輸入引數又有輸出引數的過程
public static void main(String[] args) {
Connection conn=BBConnection.getConnection();
String sql="{call stu_proc3(?,?)}";
try {
CallableStatement statement=conn.prepareCall(sql);
statement.setInt(1, 1);
statement.registerOutParameter(2,Types.VARCHAR);
statement.execute();
String pname=statement.getString(2);
System.out.println(pname);
} catch (SQLException e) {
e.printStackTrace();
}
}
JAVA呼叫例項
下面將舉出無out引數的呼叫例項
這種引數不適於用在查詢語句上,因為查詢語句需要有返回值才能被JAVA呼叫
返回到 OUT 引數中的值可能會是JDBC NULL。當出現這種情形時,將對 JDBC NULL 值進行轉換以使 getXXX 方法所返回的值為 null、0 或 false,這取決於getXXX 方法型別。對於 ResultSet 物件,要知道0或false是否源於JDBCNULL的唯一方法,是用方法wasNull進行檢測。如果 getXXX 方法讀取的最後一個值是 JDBC NULL,則該方法返回 true,否則返回 flase
JAVA呼叫例項
僅有引數的過程:
public static void main(String[] args) {
Connection conn=BBConnection.getConnection();
String sql="{call stu_proc1(?)}";
try {
CallableStatement statement=conn.prepareCall(sql);
statement.setInt(1, 1);
statement.execute();
System.out.println(statement.execute());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
JAVA呼叫例項
無引數過程:
public static void main(String[] args) {
Connection conn=BBConnection.getConnection();
String sql="{call stu_proc()}";
try {
CallableStatement statement=conn.prepareCall(sql);
statement.execute();
System.out.println(statement.execute());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
通過呼叫資料庫函式呼叫儲存過程
下面將舉一個通過資料庫函式來呼叫儲存過程:
public static void main(String[] args) {
Connection conn=BBConnection.getConnection();
String sql="{?=call get_pname1(?)}";
try {
CallableStatement statement=conn.prepareCall(sql);
statement.registerOutParameter(1, Types.VARCHAR);
statement.setInt(2, 1);
statement.execute();
System.out.println(statement.getString(1));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
?表示函式return的值, get_pname1是資料庫函式名
儲存過程的out和in都是以引數傳進,這就是函式和儲存過程的區別之一
儲存過程的異常處理
為了提高儲存過程的健壯性,避免執行錯誤,當建立儲存過程時應包含異常處理部分。
異常(EXCEPTION)是一種PL/SQL識別符號,包括預定義異常、非預定義異常和自定義異常;
預定義異常是指由PL/SQL提供的系統異常;非預定義異常用於處理與預定義異常無關的Oracle錯誤(如完整性約束等);自定義異常用於處理與Oracle錯誤的其他異常情況。
RAISE_APPLICATION_ERROR用於自定義錯誤訊息,並且訊息號必須在-20000~-20999之間
儲存過程的異常處理例項
Oracle資料庫中提供了一些異常處理的方法,下面通過一個例項來說明
create or replace procedure stu_proc6(pno in student.sno%type,pname out student.sname%type)
is
begin
select sname into pname from student where sno=pno;
EXCEPTION
when NO_DATA_FOUND then
RAISE_APPLICATION_ERROR
(-20011,'ERROR:不存在!');
end;
Oracle提供的異常處理
命名的系統異常 產生原因
ACCESS_INTO_NULL 未定義物件
CASE_NOT_FOUND CASE 中若未包含相應的 WHEN ,並且沒有設定
COLLECTION_IS_NULL 集合元素未初始化
CURSER_ALREADY_OPEN 遊標已經開啟
DUP_VAL_ON_INDEX 唯一索引對應的列上有重複的值
INVALID_CURSOR 在不合法的遊標上進行操作
INVALID_NUMBER 內嵌的 SQL 語句不能將字元轉換為數字
NO_DATA_FOUND 使用 select into 未返回行,或應用索引表未初始化的
TOO_MANY_ROWS 執行 select into 時,結果集超過一行
ZERO_DIVIDE 除數為 0
SUBSCRIPT_BEYOND_COUNT 元素下標超過巢狀表或 VARRAY 的最大值
SUBSCRIPT_OUTSIDE_LIMIT 使用巢狀表或 VARRAY 時,將下標指定為負數
VALUE_ERROR 賦值時,變數長度不足以容納實際資料
LOGIN_DENIED PL/SQL 應用程式連線到 oracle 資料庫時,提供了不正 確的使用者名稱或密碼
NOT_LOGGED_ON PL/SQL 應用程式在沒有連線 oralce 資料庫的情況下訪 問資料
PROGRAM_ERROR PL/SQL 內部問題,可能需要重灌資料字典& pl./SQL系 統包
ROWTYPE_MISMATCH 主遊標變數與 PL/SQL 遊標變數的返回型別不相容
SELF_IS_NULL 使用物件型別時,在 null 物件上呼叫物件方法
STORAGE_ERROR 執行 PL/SQL 時,超出記憶體空間
SYS_INVALID_ID 無效的 ROWID 字串
TIMEOUT_ON_RESOURCE Oracle 在等待資源時超時
儲存過程的異常處理例項
自定義異常處理:
create or replace procedure stu_proc7(pno in student.sno%type,
pon in student.sno%type
)
is
v_raise exception;
v_name student.sname%type;
begin
if pno=101 then
raise v_raise;
end if;
select sname into v_name from student where sno=111111;
exception
when v_raise then
RAISE_APPLICATION_ERROR(-20010,'ERROR:not existed!');
when no_data_found then
RAISE_APPLICATION_ERROR(-20011,'ERROR:不存在!');
end;
儲存過程的事務處理
事務用於確保資料的一致性,由一組相關的DML語句組成,該組DML語句所執行的操作要麼全部確認,要麼全部取消。
當執行事務操作(DML)時,Oracle會在被作用的表上加鎖,以防止其他使用者改變表結構,同時也會在被作用的行上加行鎖,以防止其他事務在相應行上執行DML操作。
當執行事務提交或事務回滾時,Oracle會確認事務變化或回滾事務、結束事務、刪除儲存點、釋放鎖。
儲存過程的事務處理
提交事務(COMMIT)確認事務變化,結束當前事務、刪除儲存點,釋放鎖,使得當前事務中所有未決的資料永久改變。
儲存點(SAVEPOINT)在當前事務中,標記事務的儲存點。
回滾事務(ROLLBACK)回滾整個事務,刪除該事務所定義的所有儲存點,釋放鎖,丟棄所有未決的資料改變。
回滾事務到指定的儲存點(ROLLBACK TO SAVEPOINT)回滾當前事務到指定的儲存點,丟棄該儲存點建立後的任何改變,釋放鎖。
儲存過程的事務處理
當執行DDL、DCL語句,或退出SQL*PLUS時,會自動提交事務;
事務期間應避免與使用者互動;
查詢資料期間,儘量不要啟動事務;
儘可能讓事務持續地越短越好;
在事務中儘可能存取最少的資料量。
事務處理例項
儲存過程事務處理例項:
create or replace procedure stu_proc8
is
begin
insert into student values(102,'sky','m',22,'gong');
savepoint savepoint1;
insert into student values(102,'good','w',20,'wang');
dbms_output.put_line('error');
update student set sno=103 where sname='good';
commit;
exception
when dup_val_on_index then
rollback to savepoint savepoint1;
RAISE_APPLICATION_ERROR(-20010,'ERROR:違反唯一索引約束!');
end;
資料庫函式和儲存過程的包
建立包(package)
函式:
create or replace package 包名 as 函式
注意:as後可加多個函式
儲存過程:
Create or replace package 包名 as 儲存過程
注意:as後可加多個儲存過程
包的呼叫
函式的包呼叫:
call 包名.函式名;
儲存過程的包呼叫:
call 包名.儲存過程名;
THE END