1.存储的子程序(Stored Subprograms)
存储子程序是存储在数据库中的子程序。
一个子程序是一个PL / SQL单元,它由该解决特定问题或执行一系列的相关任务的SQL和PL / SQL语句组成。子程序可以具有参数,其值由调用程序提供。子程序可以是过程,也可以是函数。通常,使用过程来执行操作,使用函数来计算和返回值。
由于存储的子程序存储在数据库中,因此存储的程序可用作许多不同数据库应用程序的构建块。在另一个子程序或匿名块中声明的子程序称为嵌套子程序或本地子程序。不能从声明它的子程序或块外部调用它。一个匿名块是未存储在数据库中的块。
有两种存储的子程序:
- 独立子程序 :在模式级别创建
- 包子程序:在包内创建
独立子程序对于测试程序逻辑很有用,但是当您确定它们可以按预期工作时,Oracle建议您将它们放入程序包中。
2.包(Packages)
一包是一个PL / SQL单元,它由相关的子程序、声明的游标、使用的变量组成。Oracle建议您将子程序放入包中。
Oracle建议您将子程序放入包中的一些原因是:
- 使用包可以在客户端程序隐藏实现细节
- 从包外部调用包子程序时,必须使用包名称来限定它们,以确保从包外部调用它们时,它们的名称始终有效。
注意:Oracle数据库提供了许多PL / SQL包,以扩展数据库功能并提供对SQL功能的PL / SQL访问。既可以在创建应用程序时使用提供的包,也可以在创建自己的存储过程时使用它们。
3.PL / SQL标识符
每个PL / SQL子程序,包,参数,变量,常量,异常和声明的游标都有一个名称,即PL / SQL标识符。
标识符的最小长度为1个字符,最大长度为30个字符。第一个字符必须是字母,但是每个后一个字符可以是字母,数字,美元符号($),下划线(_)或数字符号(#)。
例如,这些是可接受的标识符:
X
t2
phone#
credit_limit
LastName
oracle $$tree
SN##
try_again_
PL / SQL对标识符不区分大小写。例如,PL / SQL认为这些是相同的:
lastname
LastName
LASTNAME
不能使用PL / SQL保留字作为标识符。可以使用PL / SQL关键字作为标识符,但是不建议这样做。
4.PL / SQL数据类型
每个PL / SQL常量,变量,子程序参数和函数返回值都有一个数据类型,该数据类型确定其存储格式,约束,值的有效范围以及可以对其执行的操作。
PL / SQL数据类型可以是SQL数据类型(例如VARCHAR2,NUMBER或DATE),也可以是PL / SQL特有的数据类型(BOOLEAN,RECORD,REF CURSOR)和许多预定义的子类型。PL / SQL允许定义自己的子类型。
子类型是另一种基本数据类型的子集。子类型与其基本类型具有相同的有效操作,但仅是其有效值的子集。子类型可以提高可靠性,提供与ANSI / ISO类型的兼容性,并通过指示常量和变量的预期用途来提高可读性。
预定义的数字子类型PLS_INTEGER特别有用,因为它的操作使用硬件算法,而不是其基本类型使用的库算法。
不能在模式级别(即在表或独立子程序中)使用PL / SQL特有数据类型。因此,要在存储的子程序中使用这些数据类型,必须将它们放在包中。
5.创建和管理独立子程序
5.1子程序的结构
子程序遵循PL / SQL块结构;也就是说,它具有:
-
声明部分(可选):
包含类型,常量,变量,异常,游标和嵌套子程序的声明。这些项目在子程序中是局部的,在子程序完成执行时不再存在。 -
可执行部分(必填):
包含分配值,控制执行和处理数据的语句。 -
异常处理部分(可选):
异常处理部分包含处理异常(运行时错误)的代码。
注释可以出现在PL / SQL代码的任何位置。PL / SQL编译器将忽略它们。在程序中添加注释可提高可读性并有助于理解。
单行注释以双连字符(
--
)开始,并延伸到行的结尾
多行注释以斜线和星号(/*
)开始,以星号和斜线(*/
)结束
过程的结构为:
PROCEDURE name [ ( parameter_list ) ]
{ IS | AS }
[ declarative_part ]
BEGIN -- 可执行部分开始
statement; [ statement; ]...
[ EXCEPTION -- 可执行部分结束,异常处理部分开始]
exception_handler; [ exception_handler; ]... ]
END; /* 异常处理部分如果存在则结束;
否则,可执行部分结束 */
函数的结构类似于过程的结构,不同之处在于它包括一个RETURN子句和至少一个RETURN语句(以及一些可选的子句):
FUNCTION name [ ( parameter_list ) ] RETURN data_type [ clauses ]
{ IS | AS }
[ declarative_part ]
BEGIN -- 可执行部分开始
-- 至少一个语句是RETURN语句
statement; [ statement; ]...
[ EXCEPTION -- 可执行部分结束,异常处理部分开始]
exception_handler; [ exception_handler; ]... ]
END; /* 异常处理部分如果存在则结束;
否则,可执行部分结束*/
以PROCEDURE或FUNCTION开头并在IS或AS之前结束的代码是子程序签名。声明部分,可执行部分和异常处理部分组成子程序主体。
5.2 创建存储过程
创建一个名为ADD_EVALUATION的存储过程,该过程会在EVALUATIONS表中添加一行。
CREATE TABLE EVALUATIONS (
EVALUATION_ID NUMBER(8,0),
EMPLOYEE_ID NUMBER(6,0),
EVALUATION_DATE DATE,
JOB_ID VARCHAR2(10),
MANAGER_ID NUMBER(6,0),
DEPARTMENT_ID NUMBER(4,0),
TOTAL_SCORE NUMBER(3,0)
);
CREATE OR REPLACE PROCEDURE ADD_EVALUATION
(
EVALUATION_ID IN NUMBER
, EMPLOYEE_ID IN NUMBER
, EVALUATION_DATE IN DATE
, JOB_ID IN VARCHAR2
, MANAGER_ID IN NUMBER
, DEPARTMENT_ID IN NUMBER
, TOTAL_SCORE IN NUMBER
) AS
BEGIN
INSERT INTO EVALUATIONS (
evaluation_id,
employee_id,
evaluation_date,
job_id,
manager_id,
department_id,
total_score
)
VALUES (
ADD_EVALUATION.evaluation_id,
ADD_EVALUATION.employee_id,
ADD_EVALUATION.evaluation_date,
ADD_EVALUATION.job_id,
ADD_EVALUATION.manager_id,
ADD_EVALUATION.department_id,
ADD_EVALUATION.total_score
);
END ADD_EVALUATION;
5.3创建存储函数
创建名为CALCULATE_SCORE的存储函数,该函数具有三个参数并返回NUMBER类型的值。
创建存储函数,可用SQL Developer工具的Create Function或DDL语句CREATE FUNCTION。
CREATE OR REPLACE FUNCTION CALCULATE_SCORE
(
CAT IN VARCHAR2
, SCORE IN NUMBER
, WEIGHT IN NUMBER
) RETURN NUMBER AS
BEGIN
RETURN score * weight;
END CALCULATE_SCORE;