1. 程式人生 > 其它 >oracle 儲存過程呼叫 執行

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