在本章中,咱们将讨论PL/SQL中的存储过程。 子程序是执行特定任务的程序单元/模块。 这些子程序组合起来造成更大的程序。这种作法被称为“模块化设计”。 子程序能够被称为调用程序的另外一个子程序或程序调用。sql
能够在如下几个地方中建立一个子程序 -shell
在模式(schema)级别中,子程序是一个独立的子程序。它是使用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块同样,命名块也将具备如下三个部分 -code
编号 | 部分 | 描述 |
---|---|---|
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;
其中,table
IN
表示将从外部传递的值,OUT
表示将用于返回过程外的值的参数。AS
关键字而不是IS
关键字来建立存储过程。例子
如下示例演示如何建立一个简单的存储过程,执行时它只显示字符串“Hello World!”
在屏幕上。class
SET SERVEROUTPUT ON SIZE 99999; CREATE OR REPLACE PROCEDURE greetings AS BEGIN dbms_output.put_line('Hello World!'); END; / -- 执行存储过程 exec greetings; -- 或者 EXECUTE greetings;
当使用SQL提示符执行上述代码时,它将产生如下结果 -
独立的存储程序能够经过两种方式调用 -
EXECUTE
关键字能够使用EXECUTE
关键字调用名为“greetings”
的存储过程以下 -
EXECUTE greetings;
上述调用将显示结果为 -
SQL> EXECUTE greetings; Hello World! PL/SQL 过程已成功完成。 SQL>
该过程也能够从另外一个PL/SQL块调用,例如 -
BEGIN greetings; END; /
执行上面示例代码,获得如下结果 -
SQL> BEGIN 2 greetings; 3 END; 4 / Hello World! PL/SQL 过程已成功完成。 SQL>
使用DROP PROCEDURE
语句删除独立存储过程。删除程序的语法是 -
DROP PROCEDURE procedure-name;
能够使用如下语句删除greetings
存储过程程序 -
DROP PROCEDURE greetings;
下表列出了PL/SQL子程序中的参数模式 -
编号 | 参数模式 | 描述 |
---|---|---|
1 | IN |
IN 参数容许将值传递给子程序。它是一个只读参数。在子程序中,IN 参数的做用如常数,它不能被赋值。能够将常量,文字,初始化的变量或表达式做为IN 参数传递。也能够将其初始化为默认值; 然而,在这种状况下,从子程序调用中省略它。 它是参数传递的默认模式。参数经过引用传递。 |
2 | OUT |
OUT 参数返回一个值给调用程序。在子程序中,OUT 参数像变量同样。 能够更改其值并在分配该值后引用该值。实际参数必须是可变的,而且经过值传递。 |
3 | IN OUT |
IN OUT 参数将初始值传递给子程序,并将更新的值返回给调用者。 它能够分配一个值,该值能够被读取。对应于IN OUT 形式参数的实际参数必须是变量,而不是常量或表达式。正式参数必须分配一个值。实际参数(实参)经过值传递。 |
IN和OUT模式 - 示例1
假设如下存储过程须要求出两个值中的最小值。这里,存储过程两个输入的数字使用IN
模式,并使用OUT
模式参数返回最小值。
SET SERVEROUTPUT ON SIZE 99999; 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:= 12; b:= 35; findMin(a, b, c); dbms_output.put_line('两个数:12, 35中的最小值是 : ' || c); END; /
当上述代码在SQL提示符下执行时,它会产生如下结果 -
两个数:12, 35中的最小值是 : 12
IN和OUT模式 - 示例2
此过程计算传递值的值的平方。此示例显示了如何使用相同的参数来接受值,而后返回另外一个结果。
SET SERVEROUTPUT ON SIZE 99999; DECLARE a number; PROCEDURE squareNum(x IN OUT number) IS BEGIN x := x * x; END; BEGIN a:= 11; squareNum(a); dbms_output.put_line(' Square of (23): ' || a); END; /
当上述代码在SQL提示符下执行时,它会产生如下结果 -
实际参数(实参)能够经过三种方式传递 -
位置符号
在位置符号中,能够调用存储过程以下 -
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);