Oracle數據庫之PL/SQL過程與函數


Oracle數據庫之PL/SQL過程與函數

PL/SQL塊分為匿名塊與命名塊,命名塊又包含子程序、包和觸發器。

過程和函數統稱為PL/SQL子程序,我們可以將商業邏輯、企業規則寫成過程或函數保存到數據庫中,以便共享。

過程和函數均存儲在數據庫中,並通過參數與其調用者交換信息。過程和函數的唯一區別是函數總向調用者返回數據,而過程不返回數據。

1. 存儲過程概念

存儲過程(Stored Procedure)是在大型數據庫系統中,一組為了完成特定功能的SQL語句集,存儲在數據庫中。經過第一次編譯后再次調用不需要再次編譯,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。

存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。

2. 創建過程

語法:

CREATE [ OR REPLACE ] PROCEDURE [ schema. ] procedure_name
   [ ( parameter_declaration [, parameter_declaration ]... ) ]
   [ invoker_rights_clause ]
   { IS | AS }
   { [ declare_section ] body | call_spec | EXTERNAL} ;

說明:

procedure_name:過程名稱。

parameter_declaration:參數聲明,格式如下:

parameter_name [ [ IN ] datatype [ { := | DEFAULT } expression ]
          | { OUT | IN OUT } [ NOCOPY ] datatype 

IN:輸入參數。

OUT:輸出參數。

IN OUT:輸入輸出參數。

invoker_rights_clause:這個過程使用誰的權限運行,格式:

AUTHID { CURRENT_USER | DEFINER }

declare_section:聲明部分。

body:過程塊主體,執行部分。

一般只有在確認procedure_name過程是新過程或是要更新的過程時,才使用OR REPALCE關鍵字,否則容易刪除有用的過程。

示例1:

CREATE PROCEDURE remove_emp (employee_id NUMBER) AS
   tot_emps NUMBER;
   BEGIN
      DELETE FROM employees
      WHERE employees.employee_id = remove_emp.employee_id;
      tot_emps := tot_emps - 1;
   END;

示例2:

CREATE OR REPLACE PROCEDURE insert_emp(
   v_empno     in employees.employee_id%TYPE,
   v_firstname in employees.first_name%TYPE,
   v_lastname  in employees.last_name%TYPE,
   v_deptno    in employees.department_id%TYPE
   )
AS
   empno_remaining EXCEPTION;
   PRAGMA EXCEPTION_INIT(empno_remaining, -1);
BEGIN
   INSERT INTO EMPLOYEES(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, HIRE_DATE,DEPARTMENT_ID)
   VALUES(v_empno, v_firstname,v_lastname, sysdate, v_deptno);
   DBMS_OUTPUT.PUT_LINE('插入成功!');
EXCEPTION
   WHEN empno_remaining THEN
      DBMS_OUTPUT.PUT_LINE('違反數據完整性約束!');
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;

3. 使用過程參數

當建立過程時,既可以指定過程參數,也可以不提供任何參數。

過程參數包括輸入參數、輸出參數和輸入輸出參數,其中輸入參數(IN)用於接收調用環境的輸入數據,輸出參數(OUT)用於將輸出數據傳遞到調用環境,而輸入輸出參數(IN OUT)不僅要接收輸入數據,而且還要輸出數據到調用環境。

3.1 帶有輸入參數的過程

通過使用輸入參數,可以將應用程序數據傳遞到過程。當定義過程參數時,默認參數模式是輸入參數,另外可以使用IN關鍵字顯式定義輸入參數。

示例:

CREATE OR REPLACE PROCEDURE insert_emp(
    empno employee.empno%TYPE,
    ename employee.ename%TYPE,
    job employee.job%TYPE,
    sal employee.sal%TYPE,
    comm IN employee.comm%TYPE,
    deptno IN employee.deptno%TYPE
    )
IS
BEGIN
    INSERT INTO employee VALUES(empno, ename, job, sal, comm, depno);
END;

3.2 帶有輸出參數的過程

通過在過程中使用輸出參數,可以將數據或消息傳遞到調用環境和應用程序。當定義輸出參數時,需要指定參數模式OUT。

示例:

CREATE OR REPLACE PROCEDURE update_sal(
    eno NUMBER,
    salary NUMBER,
    name out VARCHAR2) 
IS
BEGIN
    UPDATE employee SET sal=salary WHERE empno=eno
    RETURNING ename INTO name;
END;

3.3 帶有輸入輸出參數的過程

通過在過程中使用輸入輸出參數,可以在調用過程時輸入數據到過程,在調用結束后輸出數據到調用環境和應用程序。當定義輸入輸出參數時,需要指定參數模式為IN OUT。

示例:

CREATE OR REPLACE PROCEDURE divide(
    num1 IN OUT NUMBER,
    num2 IN OUT NUMBER) 
IS
    v1 NUMBER;
    v2 NUMBER;
BEGIN
    v1 := trunc(num1 / num2);
    v2 := mod(num1,num2);
    num1 := v1;
    num2 := v2;
END; 

4. 調用過程

當在SQL*PLUS中調用過程時,需要使用CALL或者EXECUTE命令,而在PL/SQL塊中過程可以直接引用。

ORACLE使用EXECUTE語句來調用存儲過程語法:

EXEC[UTE] procedure_name(parameter1, parameter2, …);

示例1:

-- 調用刪除員工的過程
EXEC remove_emp(1);

-- 調用插入員工的過程
EXECUTE insert_emp(1, 'tommy', 'lin', 2);

示例2:

DECLARE
    v_name employee.ename%type;
BEGIN
    update_sal(&eno,&salary,v_name);
    dbms_output.put_line('姓名:'||v_name);
END;

5. 函數介紹

函數是一段獨立的PL/SQL程序代碼,它執行某個特定的、明確的任務。通常,函數將處理從程序的調用部分傳遞給它的信息,然后返回單個值。信息通過稱為參數的特殊標識符傳遞給函數,然后通過RETURN語句返回。

6. 創建函數

語法:

CREATE [ OR REPLACE ] FUNCTION [ schema. ] function_name
  [ ( parameter_declaration [, parameter_declaration]... ) 
  ]
  RETURN datatype
  [ { invoker_rights_clause
    | DETERMINISTIC
    | parallel_enable_clause
    | RESULT_CACHE  [ relies_on_clause ]
    }...
  ]
  { { AGGREGATE | PIPELINED }  USING [ schema. ] implementation_type
  | [ PIPELINED ] { IS | AS } { [ declare_section ] body 
                              | call_spec
                              | EXTERNAL
                              }
  } ;

示例1:

CREATE FUNCTION get_bal(acc_no IN NUMBER) 
   RETURN NUMBER 
   IS
     acc_bal NUMBER(11,2);
   BEGIN 
      SELECT order_total INTO acc_bal FROM orders 
      WHERE customer_id = acc_no; 
      RETURN(acc_bal); 
    END;

函數參數也有輸入、輸出、輸入輸出三種模式:IN、OUT、IN OUT是形參的模式。若省略,則為IN模式。

和過程一樣,IN模式的形參只能將實參傳遞給形參,進入函數內部,但只能讀不能寫,函數返回時實參的值不變。

OUT模式的形參會忽略調用時的實參值(或說該形參的初始值總是NULL),但在函數內部可以被讀或寫,函數返回時形參的值會賦予給實參。

IN OUT具有前兩種模式的特性,即調用時,實參的值總是傳遞給形參,結束時,形參的值傳遞給實參。

調用時,對於IN模式的實參可以是常量或變量,但對於OUT和IN OUT模式的實參必須是變量。

示例2:

CREATE OR REPLACE FUNCTION get_salary(
  dept_no IN NUMBER DEFAULT 1,
  emp_count OUT NUMBER)
  RETURN NUMBER
IS
  V_sum NUMBER;
BEGIN
  SELECT SUM(SALARY), count(*) INTO V_sum, emp_count FROM EMPLOYEES
  WHERE DEPARTMENT_ID=dept_no;
  RETURN v_sum;
EXCEPTION
   WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('數據不存在');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('其它異常:');
      DBMS_OUTPUT.PUT_LINE('錯誤號:' || SQLCODE||',錯誤消息:'||SQLERRM);
END get_salary;

7. 函數調用

語法:

function_name([[parameter_name1 =>] value1[, [parameter_name2 =>] value2, ...]]);

示例1:

DECLARE
  v_num NUMBER;
  v_sum NUMBER;
BEGIN
  v_sum := get_salary(27, v_num);
  DBMS_OUTPUT.PUT_LINE('部門27的工資總和:'||v_sum||',人數為:'||v_num);
END;

示例2:

DECLARE
  v_num NUMBER;
  v_sum NUMBER;
BEGIN
  v_sum := get_salary(dept_no => 27, emp_count => v_num);
  DBMS_OUTPUT.PUT_LINE('部門27的工資總和:'||v_sum||',人數為:'||v_num);
END;

示例3:

DECLARE
  v_num NUMBER;
  v_sum NUMBER;
BEGIN
  v_sum := get_salary(emp_count => v_num);
  DBMS_OUTPUT.PUT_LINE('部門27的工資總和:'||v_sum||',人數為:'||v_num);
END;

8. 刪除過程或函數

刪除過程語法:

DROP PROCEDURE [schema.]procudure_name;

刪除函數語法:

DROP FUNCTION [schema.]function_name;

9. 過程與函數比較

過程 函數
作為PL/SQL語句執行 作為表達式的一部分執行
在規范中不包含RETURN子句 必須在規范中包含RETURN子句
不返回任何值 必須返回單個值
可以RETURN語句,但是與函數不同,它不能用於返回值 必須包含至少一條RETURN語句

過程與函數的相同功能有:

  1. 都使用IN模式的參數傳入數據、OUT模式的參數返回數據。
  2. 輸入參數都可以接受默認值,都可以傳值或傳引導。
  3. 調用時的實際參數都可以使用位置表示法、名稱表示法或組合方法。
  4. 都有聲明部分、執行部分和異常處理部分。
  5. 其管理過程都有創建、編譯、授權、刪除、顯示依賴關系等。

 


免責聲明!

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



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