Oracle存儲過程及參數理解 參數默認值 參數順序

Oracle存儲過程及參數理解 (2010-11-12 11:23:34) 


轉自:http://blog.sina.com.cn/s/blog_45daee4a0100n9ar.html


一、過程 (存儲過程)
    過程是一個能執行某個特定操作的子程序。使用CREATE OR REPLACE創建或者替換保存在數據庫中的一個子程序。


示例1:聲明存儲過程,該過程返回dept錶行數
DECLARE
  PROCEDURE getDeptCount
  AS
    deptCount INT;
  BEGIN
    SELECT COUNT(*) INTO deptCount FROM DEPT;
    DBMS_OUTPUT.PUT_LINE('DEPT表的共有記錄數:'||deptCount);
  END getDeptCount;
BEGIN
  getDeptCount[()];
END;
注意:此存儲過程getDeptCount只在塊運行時有效。


示例2:創建不帶參數的存儲過程,該過程返回dept錶行數
CREATE OR REPLACE PROCEDURE getDeptCount
AS | IS
deptCount int;
BEGIN
  SELECT COUNT(*) INTO deptCount FROM dept;
  DBMS_OUTPUT.PUT_LINE('dept表共有'||deptCount||'行記錄');
END [getDeptCount];
    當我們創建的存儲過程沒有參數時,在存儲過程名字後面不能有括號。在AS或者IS後至BEGIN之前是聲明部分,存儲過程中的聲明不使用DECLARE關鍵字。同匿名PL/SQL塊一樣,EXCEPTION和聲明部分都是可選的。
    當我們創建的過程帶有錯誤時,我們可以通過SELECT * FROM USER_ERRORS查看,或者使用SHOW ERRORS [ PROCEDURE Proc_Name]查看。
    使用以下代碼可以執行存儲過程:
BEGIN
    getDeptCount;
END;
    以上存儲過程還可以通過以下代碼來簡化調用:
EXEC getDeptCount[;]   
CALL  getDeptCount();
注意:
並不是所有的存儲過程都可以用這種方式來調用
定義無參存儲過程時,存儲過程名後不能加()
在塊中或是通過EXEC調用存儲過程時可以省略()
通過CALL調用無參存儲過程必須加上()


示例3:創建帶有輸入參數的存儲過程,該過程通過員工編號打印工資額
CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(eNo NUMBER)  --參數的數據類型不能指定長度
AS
salary emp.sal%TYPE;
BEGIN
  SELECT SAL INTO salary  FROM EMP WHERE EMPNO=eNo;
  DBMS_OUTPUT.PUT_LINE(eNo||'號員工的工資爲'||salary);
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('沒有找到該編號的員工');
END;
    當定義的存儲過程含有參數時,參數的數據類型不能指定長度。參數還有輸入和輸出之分,本例中沒有指定,默認情況爲輸入參數,也可顯示的指定某個參數是輸入參數,如(eNo IN NUMBER)。同示例1不同,該例中加入了異常處理。同示例1類似可以使用下面的兩種方式調用存儲過程:
BEGIN
  getSalaryByEmpNo(7788);
END;
或者
EXEC getSalaryByEmpNo(7788);  或者
CALL getSalaryByEmpNo(7788);
但是如果傳給一個存儲過程的參數是變量時,必須使用BEGIN  END塊,如下:
DECLARE
no emp.empNo%TYPE;
BEGIN
   no:=7788;
   getSalaryByEmpNo(no);
END;
如果某個包中含有常量,也可以通過如下的方式調用:
EXEC getSalaryByEmpNo(ConstantPackage.no);
但這種方式不能再使用CALL調用。


示例4:創建含有輸入和輸出參數的存儲過程,該過程通過員工編號查找工資額,工資額以輸出參數返回
 CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(eNo IN NUMBER,salary OUT NUMBER)
 AS
 BEGIN
   SELECT SAL INTO salary  FROM EMP WHERE EMPNO=eNo;
 EXCEPTION
   WHEN NO_DATA_FOUND THEN
     DBMS_OUTPUT.PUT_LINE('沒有找到該編號的員工');
 END;
當過程中含有輸出參數時,調用時必須通過BEGIN  END塊,不能通過EXEC或CALL調用。如:
DECLARE
salary NUMBER(7,2);
BEGIN
  getSalaryByEmpNo(7788,salary);
  DBMS_OUTPUT.PUT_LINE(salary);
END;


示例5:創建參數類型既是輸入參數也是輸出參數的過程
CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(noSalary IN OUT NUMBER)
 AS
 BEGIN
   SELECT SAL INTO noSalary  FROM EMP WHERE EMPNO=noSalary;
 EXCEPTION
   WHEN NO_DATA_FOUND THEN
     DBMS_OUTPUT.PUT_LINE('沒有找到該編號的員工');
 END;
調用如下:
DECLARE
no NUMBER(7,2);
BEGIN
  no:=7788;
   getSalaryByEmpNo(no);
   DBMS_OUTPUT.PUT_LINE(no);
END;


示例6:創建帶有默認值的過程
CREATE OR REPLACE PROCEDURE addEmp
(
  empNo NUMBER,
  eName VARCHAR2,
  job   VARCHAR2 :='CLERK',
  mgr   NUMBER,
  hiredate DATE  DEFAULT SYSDATE,
  sal  NUMBER    DEFAULT 1000,
  comm  NUMBER   DEFAULT 0,
  deptNo NUMBER  DEFAULT 30
)
AS
BEGIN
  INSERT INTO emp VALUES(empNo,eName,job,mgr,hiredate,sal,comm,deptNo);
END;
調用如下:
EXEC addEmp(7776,'zhangsan','CODER',7788,'06-1月-2000',2000,0,10);  --沒有使用默認值
EXEC addEmp(7777,'lisi','CODER',7788,'06-1月-2000',2000,NULL,10);  --可以使用NULL值
EXEC addEmp(7778,'wangwu',mgr=>7788);  --使用默認值
EXEC addEmp(mgr=>7788,empNo=>7779,eName=>'sunliu');  --更改參數順序


示例7:使用NOCOPY編譯提示
    當參數是大型數據結構時,如集合、記錄和對象實例,把它們的內容全部拷貝給形參會降低執行速度,消耗大量內存。爲了防止這樣的情況發生,我們可以使用 NOCOPY提示來讓編譯器按引用傳遞方式給IN OUT模式的參數。
DECLARE
TYPE DeptList IS TABLE OF VARCHAR2(10);
dList  DeptList:=DeptList('CORESUN','CORESUN','CORESUN','CORESUN');
PROCEDURE My_Proc(d IN OUT NOCOPY DeptList)
AS...
注意:NOCOPY只是一個提示,而不是指令。即使有時候我們使用了NOCOPY,但編譯器有可能仍然會進行值拷貝。通常情況下NOCOPY是可以成功的。


二、維護過程
1、刪除存儲過程
    DROP PROCEDURE Proc_Name;
2、查看過程狀態
    SELECT object_name,status  FROM USER_OBJECTS WHERE object_type='PROCEDURE';
3、重新編譯過程
    ALTER PROCEDURE Proc_Name COMPILE;
4、查看過程代碼
    SELECT * FROM USER_SOURCE WHERE TYPE='PROCEDURE';
 
三、參數的理解
-- 輸出參數不可以修改 解決的方法有兩種
   --1 把參數改成 輸入參數  
   --2 就是參數改成 可輸入輸出的參數;
調用過程的 三個方式
       1 就是使用call
             在只用call方式調用函數的時候,必須加要括號,有參數,還要加參數值


             這個方式在命令窗口,調用過程,將不會出現輸入的數據.
        2 就是使用exec 命令,進行命令調用過程, 使用命令,就必須在命令行裏面輸入
          過程名,這個命令窗口中,可加可不加() ,如果有參數的,就一定要加,還有參數值,參數值的類型要與
          變量類型相同.
        3 在語句塊中進行調用過程,這個方式和命令模式類似,他們都是可要可不要(),
        -- 在2 和 3 中的 沒有括號的情況是,過程沒有參數 ,如果有,就必須要有()
       
                             
   輸出參數的特點
        1 一個過程中,如果有輸出參數(OUT 參數),在調用過程的使用,也要傳入一個參數, 這個參數可以不用在調用的地方
        進行賦值,就直接傳入一個聲明好的一個變量,用來接受存儲過程中的輸出參數的值(OUT 參數)
        2 輸入參數 值不可以改變在過程中,
       
           注意: 在存儲過程中,他的參數類型不可以設置它的大小 ;    
               例如;
                           CREATE OR REPLACE PROCEDURE hello(
                               p_name IN VARCHAR2(12),
                                  p_age OUT NUMBER(10,2)
                                )
                               IS
                              BEGIN           
        如果有輸出參數就必須有有一個參數進行接收 ;
       
     CREATE OR REPLACE PROCEDURE hello(
            p_name IN VARCHAR2,
            p_age OUT emp.sal%TYPE
     )
     IS
     BEGIN
       SELECT emp.sal + 3131 INTO p_age FROM emp WHERE empno = 7788 ;
                       
            dbms_output.put_line( p_age);
     END ;
     --------- 塊中調用方法
     DECLARE
         v_nanme varchar2(12);
         v_age NUMBER (12,2);
     BEGIN
          hello (v_nanme,v_age);
            dbms_output.put_line(v_age);
     END ;
    
     -- 在這個過程中 傳入的v_age 就是接受 存儲過程輸出參數的值 ; 類似於Java的中的返回值


     -- 理解 in out 參數
    
     CREATE OR REPLACE PROCEDURE hello1 (
            p_name IN OUT emp.ename%TYPE
     )
     IS
    
     BEGIN
          -- SELECT emp.ename INTO p_name FROM emp ;
              p_name:='a;sk , ' || p_name ;
           END ;
    --------------------------------------------------------------------------
      DECLARE
         v_nanme varchar2(12);
     BEGIN       
         v_nanme:='12312';
          hello1(v_nanme);
            dbms_output.put_line(v_nanme);
     END ;
    
    
SELECT emp.sal FROM emp WHERE emp.empno = 7788 ;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章