声明变量和常量并为其赋值

在程序包规范中声明的变量或常量可供有权访问程序包的任何程序使用。在程序包体或子程序中声明的变量或常量则是该程序包或子程序的本地项。在声明常量时,您必须为其赋予一个初始值。

与 SQL 相比,PL/SQL 的一个重大优势是它允许声明和使用变量与常量。

在程序包规范中声明的变量或常量可供有权访问程序包的任何程序使用。在程序包体或子程序中声明的变量或常量则是该程序包或子程序的本地项。

变量用于保存特定数据类型的值。您的程序可以在运行时更改此值。常量用于保存不能更改的值。

变量或常量可以属于任何 PL/SQL 数据类型。在声明变量时,您可以为其赋予一个初始值;如果您未赋予初始价值,则其初始值将为 NULL。在声明常量时,您必须为其赋予一个初始值。要为变量或常量赋予初始值,请使用赋值的运算符 (:=)。

提示: 请将所有不需要更改的值声明为常量。这样做可以优化编译后的代码,同时让您的源代码更加易于维护。

另请参阅: Oracle Database PL/SQL Language Reference,了解有关变量和常量的一般信息

教程:在子程序中声明变量和常量

本教程介绍如何使用 SQL Developer 的“编辑”工具在 EMP_EVAL.CALCULATE_SCORE 函数中声明变量和常量。(本教程也可用作更改程序包体的示例。)

EMP_EVAL.CALCULATE_SCORE 函数在“教程:创建程序包规范”中指定。

在 CALCULATE_SCORE 函数中声明变量和常量的步骤:

  1. 在 "Connections"(连接)框架中,展开 hr_conn

  2. 在方案对象类型的列表中,展开程序包

  3. 在软件包列表中,展开 EMP_EVAL

  4. 在选项列表中,右键单击 EMP_EVAL Body

    此时将显示选项的列表。

  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 属性

This tutorial shows how to use the SQL Developer tool Edit to change the declarations of the variables, constants, and formal parameters of the EMP_EVAL.CALCULATE_SCORE function to use the %TYPE attribute.

EMP_EVAL.CALCULATE_SCORE 函数显示在“教程:声明子程序中的变量和常量”中。

将 CALCULATE_SCORE 中的声明更改为使用 %TYPE 的步骤:

  1. 在 "Connections"(连接)框架中,展开 hr_conn

  2. 在方案对象类型的列表中,展开程序包

  3. 在软件包列表中,展开 EMP_EVAL

  4. 在选项列表中,右键单击 EMP_EVAL Body

  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;