PL/SQL - 过程
在本章中,我们将讨论 PL/SQL 中的过程。子程序 是一个执行特定任务的程序单元/模块。这些子程序组合起来形成更大的程序。这基本上被称为“模块化设计”。子程序可以被另一个子程序或称为调用程序的程序调用。
子程序可以创建于 −
- 模式级别
- 包内部
- PL/SQL 块内部
在模式级别,子程序是一个独立子程序。它使用 CREATE PROCEDURE 或 CREATE FUNCTION 语句创建。它存储在数据库中,并可以使用 DROP PROCEDURE 或 DROP FUNCTION 语句删除。
在包内部创建的子程序是一个打包子程序。它存储在数据库中,只有在用 DROP PACKAGE 语句删除包时才能删除。我们将在‘PL/SQL - 包’章节中讨论包。
PL/SQL 子程序是带有参数集的可调用命名 PL/SQL 块。PL/SQL 提供了两种子程序 −
函数 − 这些子程序返回单个值;主要用于计算并返回一个值。
过程 − 这些子程序不直接返回值;主要用于执行操作。
本章将涵盖 PL/SQL 过程 的重要方面。我们将在下一章讨论 PL/SQL 函数。
PL/SQL 子程序的组成部分
每个 PL/SQL 子程序都有一个名称,并且可能有一个参数列表。与匿名 PL/SQL 块类似,命名块也有以下三个部分 −
| 序号 | 部分 & 描述 |
|---|---|
| 1 | 声明部分 这是可选部分。但是,子程序的声明部分不以 DECLARE 关键字开头。它包含类型、光标、常量、变量、异常和嵌套子程序的声明。这些项是子程序局部的,当子程序执行完成时即不存在。 |
| 2 | 可执行部分 这是必填部分,包含执行指定操作的语句。 |
| 3 | 异常处理 这又是可选部分。它包含处理运行时错误的代码。 |
创建过程
过程使用 CREATE OR REPLACE PROCEDURE 语句创建。CREATE OR REPLACE PROCEDURE 语句的简化语法如下 −
CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
{IS | AS}
BEGIN
< procedure_body >
END procedure_name;
其中,
procedure-name 指定过程的名称。
[OR REPLACE] 选项允许修改现有过程。
可选参数列表包含参数的名称、模式和类型。IN 表示将从外部传入的值,OUT 表示用于将值返回到过程外部的参数。
procedure-body 包含可执行部分。
创建独立过程时,使用 AS 关键字代替 IS 关键字。
示例
以下示例创建一个简单的过程,当执行时在屏幕上显示字符串 'Hello World!'。
CREATE OR REPLACE PROCEDURE greetings
AS
BEGIN
dbms_output.put_line('Hello World!');
END;
/
当在 SQL 提示符下执行上述代码时,将产生以下结果 −
Procedure created.
执行独立过程
独立过程可以通过两种方式调用 −
使用 EXECUTE 关键字
从 PL/SQL 块中调用过程名称
上述名为 'greetings' 的过程可以使用 EXECUTE 关键字如下调用 −
EXECUTE greetings;
上述调用将显示 −
Hello World PL/SQL procedure successfully completed.
过程也可以从另一个 PL/SQL 块中调用 −
BEGIN greetings; END; /
上述调用将显示 −
Hello World PL/SQL procedure successfully completed.
删除独立过程
独立过程使用 DROP PROCEDURE 语句删除。删除过程的语法如下 −
DROP PROCEDURE procedure-name;
您可以使用以下语句删除 greetings 过程 −
DROP PROCEDURE greetings;
PL/SQL 子程序中的参数模式
下表列出了 PL/SQL 子程序中的参数模式 −
| 序号 | 参数模式及描述 |
|---|---|
| 1 | IN IN 参数允许您向子程序传递值。它是只读参数。在子程序内部,IN 参数表现得像一个常量。它不能被赋值。您可以将常量、字面量、已初始化的变量或表达式作为 IN 参数传递。您也可以将其初始化为默认值;但是,在这种情况下,它将从子程序调用中省略。它是参数传递的默认模式。参数按引用传递。 |
| 2 | OUT OUT 参数将值返回给调用程序。在子程序内部,OUT 参数表现得像一个变量。您可以更改其值并在赋值后引用该值。实际参数必须是变量,并且按值传递。 |
| 3 | IN OUT IN OUT 参数向子程序传递初始值,并将更新后的值返回给调用者。它可以被赋值,并且可以读取该值。 对应于 IN OUT 形式参数的实际参数必须是变量,而不是常量或表达式。形式参数必须被赋值。实际参数按值传递。 |
IN 和 OUT 模式示例 1
此程序找出两个值的最小值。此处,过程使用 IN 模式接收两个数字,并使用 OUT 参数返回它们的最小值。
DECLARE
a number;
b number;
c number;
PROCEDURE findMin(x IN number, y IN number, z OUT number) IS
BEGIN
IF x < y THEN
z:= x;
ELSE
z:= y;
END IF;
END;
BEGIN
a:= 23;
b:= 45;
findMin(a, b, c);
dbms_output.put_line(' Minimum of (23, 45) : ' || c);
END;
/
在 SQL 提示符下执行上述代码时,会产生以下结果 −
Minimum of (23, 45) : 23 PL/SQL procedure successfully completed.
IN 和 OUT 模式示例 2
此过程计算传递值的平方。此示例展示了如何使用同一参数接收值并返回另一个结果。
DECLARE
a number;
PROCEDURE squareNum(x IN OUT number) IS
BEGIN
x := x * x;
END;
BEGIN
a:= 23;
squareNum(a);
dbms_output.put_line(' Square of (23): ' || a);
END;
/
在 SQL 提示符下执行上述代码时,会产生以下结果 −
Square of (23): 529 PL/SQL procedure successfully completed.
传递参数的方法
实际参数可以以三种方式传递 −
- 位置表示法
- 命名表示法
- 混合表示法
位置表示法
在位置表示法中,您可以这样调用过程 −
findMin(a, b, c, d);
在位置表示法中,第一个实际参数替换第一个形式参数;第二个实际参数替换第二个形式参数,依此类推。因此,a 替换 x,b 替换 y,c 替换 z,d 替换 m。
命名表示法
在命名表示法中,使用 箭头符号 ( => ) 将实际参数与形式参数关联。过程调用将如下所示 −
findMin(x => a, y => b, z => c, m => d);
混合表示法
在混合表示法中,您可以在过程调用中混合使用两种表示法;但是,位置表示法应先于命名表示法。
以下调用是合法的 −
findMin(a, b, c, m => d);
但是,以下调用不合法:
findMin(x => a, b, c, d);