宣告並指派變數和常數的值

在套件規格中宣告的變數或常數,可供任何可存取套件的程式使用。在套裝程式主體或子程式中宣告之變數或常數是該套裝程式或子程式的區域。宣告常數時,您必須指派初始值給常數。

PL/SQL 勝於 SQL 的一大優勢是 PL/SQL 可讓您宣告及使用變數和常數。

在套件規格中宣告的變數或常數,可供任何可存取套件的程式使用。在套裝程式主體或子程式中宣告之變數或常數是該套裝程式或子程式的區域。

變數會保存特定資料類型的值。程式可以在執行時期變更值。常數會保留無法變更的值。

變數或常數都可以具有任何的 PL/SQL 資料類型。宣告變數時,您可以將它指派為起始值;如果沒有,它的起始值為空值。宣告常數時,您必須指派初始值給常數。若要將起始值指派給變數或常數,請使用指派運算子 (:=)。

秘訣:宣告未變更為常數的所有值。這個做法可將已編譯的程式碼最佳化,並且讓您的原始程式碼變得容易維護。

另請參閱:Oracle Database PL/SQL Language Reference,瞭解變數和常數的一般資訊

教學課程:在子程式中宣告變數和常數

本教學課程示範如何使用 SQL Developer 工具「編輯」,宣告 EMP_EVAL.CALCULATE_SCORE 函數中的變數與常數。(此教學課程也是變更套裝程式主體的範例。)

EMP_EVAL.CALCULATE_SCORE 函數是在「教學課程:建立套裝程式規格」中指定。

宣告 CALCULATE_SCORE 函數中變數與常數的步驟:

  1. 在「連線」框架中,展開 hr_conn

  2. 在綱要物件類型清單中,展開套裝程式

  3. 在薪資配套清單中,展開 EMP_EVAL

  4. 在選項清單中,以滑鼠右鍵按一下 EMP_EVAL 主體

    將會顯示選項清單。

  5. 在選項清單中,選取編輯

    便會顯示「EMP_EVAL 主體」窗格,其中顯示套裝程式主體的程式碼:

     CREATE OR REPLACE
     PACKAGE BODY EMP_EVAL AS
    
       PROCEDURE eval_department ( dept_id IN NUMBER ) AS
    
       BEGIN
    
         -- TODO implementation required for PROCEDURE EMP_EVAL.eval_department
         NULL;
       END eval_department;
    
       FUNCTION calculate_score ( evaluation_id IN NUMBER
                               , performance_id IN NUMBER)
                               RETURN NUMBER AS
       BEGIN
    
         -- TODO implementation required for FUNCTION EMP_EVAL.calculate_score
         RETURN NULL;
       END calculate_score;
    
     END EMP_EVAL;
    
  6. RETURN NUMBER ASBEGIN 之間,新增這些變數與常數宣告:

     n_score       NUMBER(1,0);                -- variable
     n_weight      NUMBER;                     -- variable
     max_score     CONSTANT NUMBER(1,0) := 9;  -- constant, initial value 9
    
     max_weight    CONSTANT NUMBER(8,8) := 1;  -- constant, initial value 1
    
     The title of the EMP_EVAL Bodypane changes to italic font, indicating that the code is not saved in the database.
    
  7. 從「檔案」功能表中選取儲存

    Oracle Database 會編譯並儲存變更的套裝程式主體。EMP_EVAL 主體窗格的標題已不再是斜體字。

另請參閱:

確定變數、常數和參數之資料類型的正確性

請以 %TYPE 屬性宣告變數、常數及參數,以確保其資料類型正確。

在「教學課程:在子程式中宣告變數與常數」之後,EMP_EVAL.CALCULATE_SCORE 函式的代碼為:

FUNCTION calculate_score ( evaluation_id IN NUMBER
                          , performance_id IN NUMBER )
                          RETURN NUMBER AS
  n_score       NUMBER(1,0);                -- variable
  n_weight      NUMBER;                     -- variable
  max_score     CONSTANT NUMBER(1,0) := 9;  -- constant, initial value 9
  max_weight    CONSTANT NUMBER(8,8) := 1;  -- constant, initial value 1
  BEGIN
    -- TODO implementation required for FUNCTION EMP_EVAL.calculate_score
    RETURN NULL;
  END calculate_score;

函數的變數、常數和參數代表 SCORES 和 PERFORMANCE_PARTS 表格的值 (在「建立表格」中建立):

因此,每個變數、常數和參數都具有與其對應資料欄相同的資料類型。

如果資料欄的資料類型變更,您想要將變數、常數和參數的資料型態變更為相同的資料類型;否則,CALCULATE_SCORE 函數就會變成無效。

若要確保變數、常數與參數的資料型態一律符合欄的資料型態,請使用 %TYPE 屬性來宣告這些變數。%TYPE 屬性提供表格資料欄或其他變數的資料類型,以確保正確的資料類型指派。

另請參閱:

教學課程:將宣告變更為使用 %TYPE 屬性

本教學課程說明如何使用 SQL Developer 工具「編輯」,變更 EMP_EVAL.CALCULATE_SCORE 函數之變數、常數及正式參數的宣告,以使用 %TYPE 屬性。

EMP_EVAL.CALCULATE_SCORE 函數會顯示在教學課程:宣告子程式中的變數和常數中。

將 CALCULATE_SCORE 中的宣告變更為使用 %TYPE 的步驟:

  1. 在「連線」框架中,展開 hr_conn

  2. 在綱要物件類型清單中,展開套裝程式

  3. 在薪資配套清單中,展開 EMP_EVAL

  4. 在選項清單中,以滑鼠右鍵按一下 EMP_EVAL 主體

  5. 在選項清單中,選取編輯

    EMP_EVAL Bodypane 會出現,顯示套件主體的代碼:

     CREATE OR REPLACE
     PACKAGE BODY emp_eval AS
    
       PROCEDURE eval_department ( dept_id IN NUMBER ) AS
       BEGIN
    
         -- TODO implementation required for PROCEDURE EMP_EVAL.eval_department
         NULL;
       END eval_department;
    
       FUNCTION calculate_score ( evaluation_id IN NUMBER
                               , performance_id IN NUMBER )
                               RETURN NUMBER AS
       n_score       NUMBER(1,0);                -- variable
       n_weight      NUMBER;                     -- variable
       max_score     CONSTANT NUMBER(1,0) := 9;  -- constant, initial value 9
    
       max_weight    CONSTANT NUMBER(8,8) := 1;  -- constant, initial value 1
    
       BEGIN
    
         -- TODO implementation required for FUNCTION EMP_EVAL.calculate_score
         RETURN NULL;
       END calculate_score;
    
     END emp_eval;
    
  6. 在函數的程式碼中,進行下列變更:

     FUNCTION calculate_score ( evaluation_id IN SCORES.EVALUATION_ID%TYPE
                               , performance_id IN SCORES.PERFORMANCE_ID%TYPE)
                               RETURN NUMBER AS
     n_score       SCORES.SCORE%TYPE;
     n_weight      PERFORMANCE_PARTS.WEIGHT%TYPE;
     max_score     CONSTANT SCORES.SCORE%TYPE := 9;
     max_weight    CONSTANT PERFORMANCE_PARTS.WEIGHT%TYPE := 1;
    
  7. EMP_EVAL 上按一下滑鼠右鍵。

  8. 在選項清單中,選取編輯

    EMP_EVAL 窗格開啟,顯示建立套裝程式的 CREATE PACKAGE 敘述句:

     CREATE OR REPLACE PACKAGE EMP_EVAL AS
    
     PROCEDURE eval_department(dept_id IN NUMBER);
     FUNCTION calculate_score(evaluation_id IN NUMBER
                             , performance_id IN NUMBER)
                               RETURN NUMBER;
    
     END EMP_EVAL;
    
  9. 在函數的程式碼中,進行下列變更:

     FUNCTION calculate_score(evaluation_id IN scores.evaluation_id%TYPE
                             , performance_id IN scores.performance_id%TYPE)
    
  10. EMP_EVAL 上按一下滑鼠右鍵。

  11. 在選項清單中,選取編譯

  12. EMP_EVAL 主體上按一下滑鼠右鍵。

  13. 在選項清單中,選取編譯

指派變數值

您可以使用下列方式將值指定給變數:

另請參閱:

使用指派運算子指派變數值

使用指派運算子 (:=),您可以將表示式的值指派給子程式之宣告式或可執行部份中的變數。

在子程式的宣告部分中,您可以在宣告變數時,為變數指派起始值。語法如下:

variable_name data_type := expression;

在子程式的宣告部分中,您可以使用指派敘述句指派變數值。語法如下:

variable_name := expression;

範例 5-1 顯示要對 EMP_EVAL.CALCULATE_SCORE 函數進行的變更,以新增變數 running_total,並使用它作為函數的傳回值。指派運算子會同時出現在函數的宣告和可執行部分。(run_total 的資料類型必須為 NUMBER,而不是 SCORES.SCORE%TYPE 或 PERFORMANCE_PARTS.WEIGHT%TYPE,因為它包含兩個 NUMBER 值且具有不同精確度與縮放比例的乘積。)

另請參閱:

範例 5-1 使用指派運算子將值指派給變數

FUNCTION calculate_score(evaluation_id IN SCORES.EVALUATION_ID%TYPE
                         , performance_id IN SCORES.PERFORMANCE_ID%TYPE)
                         RETURN NUMBER AS
  n_score       SCORES.SCORE%TYPE;
  n_weight      PERFORMANCE_PARTS.WEIGHT%TYPE;
  running_total NUMBER := 0;
  max_score     CONSTANT SCORES.SCORE%TYPE := 9;
  max_weight    CONSTANT PERFORMANCE_PARTS.WEIGHT%TYPE:= 1;
BEGIN
  running_total := max_score * max_weight;
  RETURN running_total;
END calculate_score;

使用 SELECT INTO 敘述句指派變數值

若要在子程式設計或套裝程式中使用表格值,您必須使用 SELECT INTO 敘述句將它們指派給變數。範例 5-2 顯示對 EMP_EVAL.CALCULATE_SCORE 函數所做的變更,讓函數從表格值計算 running_total。

範例 5-3 中的 ADD_EVAL 程序使用 EMPLOYEES 表格中對應列的值,將一列插入 EVALUATIONS 表格中。將 ADD_EVAL 程序新增至 EMP_EVAL 套裝程式的主體,但不會新增至規格。因為它不在規格中,所以 ADD_EVAL 是套件的本機元件,只能由套件中的其他子程式呼叫,而非從套件外部叫用。

另請參閱:Oracle Database PL/SQL Language Reference,瞭解有關 SELECT INTO 敘述句的詳細資訊

範例 5-2 使用 SELECT INTO 將表格值指派給變數

FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
                         , performance_id IN scores.performance_id%TYPE )
                         RETURN NUMBER AS

  n_score       scores.score%TYPE;
  n_weight      performance_parts.weight%TYPE;
  running_total NUMBER := 0;
  max_score     CONSTANT scores.score%TYPE := 9;
  max_weight    CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
  SELECT s.score INTO n_score
  FROM SCORES s
  WHERE evaluation_id = s.evaluation_id
  AND performance_id = s.performance_id;

  SELECT p.weight INTO n_weight
  FROM PERFORMANCE_PARTS p
  WHERE performance_id = p.performance_id;

  running_total := n_score * n_weight;
  RETURN running_total;
END calculate_score;

範例 5-3 使用其他表格中的值插入表格資料列

PROCEDURE add_eval ( employee_id IN EMPLOYEES.EMPLOYEE_ID%TYPE
                   , today IN DATE )
AS
  job_id         EMPLOYEES.JOB_ID%TYPE;
  manager_id     EMPLOYEES.MANAGER_ID%TYPE;
  department_id  EMPLOYEES.DEPARTMENT_ID%TYPE;
BEGIN
  INSERT INTO EVALUATIONS (
    evaluation_id,
    employee_id,
    evaluation_date,
    job_id,
    manager_id,
    department_id,
    total_score
  )
  SELECT
    evaluations_sequence.NEXTVAL,   -- evaluation_id
    add_eval.employee_id,      -- employee_id
    add_eval.today,            -- evaluation_date
    e.job_id,                  -- job_id
    e.manager_id,              -- manager_id
    e.department_id,           -- department_id
    0                          -- total_score
  FROM employees e;

  IF SQL%ROWCOUNT = 0 THEN
    RAISE NO_DATA_FOUND;
  END IF;
END add_eval;