1. 程式人生 > >在PL/SQL中呼叫儲存過程--oracle

在PL/SQL中呼叫儲存過程--oracle

在oracle10中寫好了儲存過程,程式碼如下:

CREATE OR REPLACE Procedure Proc_Insert
(
       sName     in     varchar2,
       sAge      in     int,
       sExeTime  in     varchar2
)
is
 
begin
       Insert into T_TEST(C_ID, C_NAME, C_AGE, C_INTIME, C_EXETIME)
       values(T_TEST_CID.nextval,sName,sAge, sysdate, to_date(sExeTime, 'yyyy-mm-dd'));
end Proc_Insert;
 

為了在PL/SQL中呼叫這個儲存過程,採用瞭如下的程式碼:

begin
Proc_Insert('hello6',25,'2005-12-24');
commit;
end;

 

另外增加了一個儲存過程,但是sExeTime是date型別,那麼呼叫的時候,就必須先把字串轉換成date型別,否則將會呼叫失敗。

儲存過程:

CREATE OR REPLACE Procedure Proc_Insert2
(
       sName     in     varchar2,
       sAge      in     int,
       sExeTime  in     date
)
is
 
begin
       Insert into T_TEST(C_ID, C_NAME, C_AGE, C_INTIME, C_EXETIME)
       values(T_TEST_CID.nextval,sName,sAge, sysdate, sExeTime);
end Proc_Insert2;
  
呼叫的程式碼:
 

begin
Proc_Insert2('hellowhat', 26, to_date('2010-10-20', 'yyyy-mm-dd'));
commit;
end;
呼叫儲存過程
    儲存過程建立完成後,只要通過授權,使用者就可以在SQLPLUS 、ORACLE開發工具或第三方開發工具中來呼叫執行。ORACLE 使用EXECUTE 語句來實現對儲存過程的呼叫:
    EXEC[UTE]  Procedure_name( parameter1, parameter2…);
 
例:查詢指定員工記錄;
 
CREATE OR REPLACE PROCEDURE QueryEmp
(v_empno IN emp.empno%TYPE,
     v_ename OUT emp.ename%TYPE,
     v_sal OUT emp.sal%TYPE)
AS
BEGIN
     SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno=v_empno;
     DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'的員工已經查到!');
EXCEPTION
     WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('你需要的資料不存在!');
      WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('發生其它錯誤!');
END QueryEmp;
 
呼叫方法:
 DECLARE
    v1 emp.ename%TYPE;
    v2 emp.sal%TYPE;
 BEGIN
   QueryEmp(7788, v1, v2);
   DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
   DBMS_OUTPUT.PUT_LINE('工資:'||v2);
   QueryEmp(7902, v1, v2);
   DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
   DBMS_OUTPUT.PUT_LINE('工資:'||v2);
   QueryEmp(8899, v1, v2);
   DBMS_OUTPUT.PUT_LINE('姓名:'||v1);
   DBMS_OUTPUT.PUT_LINE('工資:'||v2);
END;
 
例.計算指定部門的工資總和,並統計其中的職工數量。
 
CREATE OR REPLACE PROCEDURE proc_demo
(Dept_no NUMBER DEFAULT 10,
       Sal_sum OUT NUMBER,
       Emp_count OUT NUMBER)
IS
BEGIN
       SELECT SUM(sal), COUNT(*) INTO sal_sum, emp_count
FROM emp WHERE deptno=dept_no;
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('你需要的資料不存在!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('發生其它錯誤!');
END proc_demo;
 
呼叫方法:
DECLARE
V_num NUMBER;
V_sum NUMBER(8, 2);
BEGIN
       Proc_demo(30, v_sum, v_num);
DBMS_OUTPUT.PUT_LINE('30號部門工資總和:'||v_sum||’,人數:’||v_num);
       Proc_demo(sal_sum => v_sum, emp_count => v_num);
DBMS_OUTPUT.PUT_LINE('10號部門工資總和:'||v_sum||’,人數:’||v_num);
END;
 
       在PL/SQL 程式中還可以在塊內建立本地函式和過程,這些函式和過程不儲存在資料庫中,但可以在建立它們的PL/SQL 程式中被重複呼叫。本地函式和過程在PL/SQL 塊的宣告部分定義,它們的語法格式與儲存函式和過程相同,但不能使用CREATE OR REPLACE 關鍵字。
 
例:建立本地過程,用於計算指定部門的工資總和,並統計其中的職工數量;
 
DECLARE
V_num NUMBER;
V_sum NUMBER(8, 2);
PROCEDURE proc_demo
              (Dept_no NUMBER DEFAULT 10,
              Sal_sum OUT NUMBER,
              Emp_count OUT NUMBER)
IS
BEGIN
              SELECT SUM(sal), COUNT(*) INTO sal_sum, emp_count
FROM emp WHERE deptno=dept_no;
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('你需要的資料不存在!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('發生其它錯誤!');
END proc_demo;
BEGIN
       Proc_demo(30, v_sum, v_num);
DBMS_OUTPUT.PUT_LINE('30號部門工資總和:'||v_sum||’,人數:’||v_num);
       Proc_demo(sal_sum => v_sum, emp_count => v_num);
DBMS_OUTPUT.PUT_LINE('10號部門工資總和:'||v_sum||’,人數:’||v_num);
END;

儲存過程
1 什麼是儲存過程?
 用於在資料庫中完成特定的操作或者任務。是一個PLSQL程式塊,可以永久的儲存在資料庫中以供其他程式呼叫。
2 儲存過程的引數模式

儲存過程的引數特性:
 IN型別的引數 OUT型別的引數 IN-OUT型別的引數
值被 傳遞給子程式 返回給呼叫環境 傳遞給子程式
返回給呼叫環境
引數形式 常量 未初始化的變數 初始化的變數
使用時 預設型別 必須明確指定 必須明確指定

3 無引數儲存過程的使用:
CREATE  OR  REPLACE  PROCEDURE  過程名  [(parameter,...)]
IS
定義變數
Begin
Plsql程式
End;
例:建立一個儲存過程,用於向資料庫中插入一條記錄。
第一步:建立
CREATE  OR  REPLACE  PROCEDURE  pro_1
IS
Begin
  insert into person values (11,'aa','aav');
End;
第二步:在sql*plus中執行該過程
exec pro_1;
第三步:通過JDBC使用儲存過程。
 private Connection conn = null;
 private ResultSet rs = null;
 private CallableStatement state = null;
 //呼叫一個無引數的儲存過程
 public void testPro()
 {
  conn = Tools.getConnection();
  try {
   state = conn.prepareCall("{call pro_1}");
   state.execute();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

4 帶有IN型別引數的儲存過程的使用。
例:建立一個儲存過程,用於向資料庫中插入一條記錄。
第一步:建立
CREATE  OR  REPLACE  PROCEDURE  pro_2(id number,name varchar2,email varchar2)
IS
Begin
  insert into person values (id,name,email);
End;
第二步:在sql*plus中執行該過程
exec pro_2(12,'aaa','aaa');
第三步:通過JDBC使用儲存過程。
 //使用一個帶有 IN 型別引數的儲存過程
 public void testPro_in(int id,String name,String email)
 {
  conn = Tools.getConnection();
  try {
   state = conn.prepareCall("{call pro_2(?,?,?)}");
   state.setLong(1, id);
   state.setString(2, name);
   state.setString(3, email);
   state.execute();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
5 帶有out型別引數的儲存過程的使用。
例:建立一個儲存過程,用於返回資料庫中的Person表的總行數。
第一步:建立
CREATE  OR  REPLACE  PROCEDURE  pro_3(num out number)
IS
mynum number;
Begin
  select count(*) into mynum from person;
  num := mynum;
End;
或者
CREATE  OR  REPLACE  PROCEDURE  pro_3(num out number)
IS
Begin
  select count(*) into num from person;
End;
第二步:在sql*plus中執行該過程
declare
a number;
begin
  pro_3(a);
  dbms_output.put_line(a);
end;
第三步:通過JDBC使用儲存過程。
public void testPro_out()
 {
  conn = Tools.getConnection();
  try {
   state = conn.prepareCall("{call pro_3(?)}");
   state.registerOutParameter(1, Types.NUMERIC);
   state.execute();
   int num = state.getInt(1);
   System.out.println(num);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
6 帶有in-out型別引數的儲存過程的使用。
建立:
CREATE  OR  REPLACE  PROCEDURE  pro_4(num in out number)
IS
a number := 100;
Begin
  num := a*num;
End;
在sql*plus中執行該過程
declare
  a number := 12;
begin
  pro_4(a);
  dbms_output.put_line(a);
end;

練習:
已知有一員工表,請編寫一個儲存過程,可以通過部門ID得到該部門員工的平