Plsql 简明教程

PL/SQL - Quick Guide

PL/SQL - Overview

PL/SQL 编程语言是由 Oracle 公司在 20 世纪 80 年代末作为 SQL 和 Oracle 关系数据库的程序扩展语言开发的。以下是关于 PL/SQL 的一些重要事实 -

The PL/SQL programming language was developed by Oracle Corporation in the late 1980s as procedural extension language for SQL and the Oracle relational database. Following are certain notable facts about PL/SQL −

  1. PL/SQL is a completely portable, high-performance transaction-processing language.

  2. PL/SQL provides a built-in, interpreted and OS independent programming environment.

  3. PL/SQL can also directly be called from the command-line SQL*Plus interface.

  4. Direct call can also be made from external programming language calls to database.

  5. PL/SQL’s general syntax is based on that of ADA and Pascal programming language.

  6. Apart from Oracle, PL/SQL is available in TimesTen in-memory database and IBM DB2.

Features of PL/SQL

PL/SQL 具有以下特性 -

PL/SQL has the following features −

  1. PL/SQL is tightly integrated with SQL.

  2. It offers extensive error checking.

  3. It offers numerous data types.

  4. It offers a variety of programming structures.

  5. It supports structured programming through functions and procedures.

  6. It supports object-oriented programming.

  7. It supports the development of web applications and server pages.

Advantages of PL/SQL

PL/SQL 具有以下优点 -

PL/SQL has the following advantages −

  1. SQL is the standard database language and PL/SQL is strongly integrated with SQL. PL/SQL supports both static and dynamic SQL. Static SQL supports DML operations and transaction control from PL/SQL block. In Dynamic SQL, SQL allows embedding DDL statements in PL/SQL blocks.

  2. PL/SQL allows sending an entire block of statements to the database at one time. This reduces network traffic and provides high performance for the applications.

  3. PL/SQL gives high productivity to programmers as it can query, transform, and update data in a database.

  4. PL/SQL saves time on design and debugging by strong features, such as exception handling, encapsulation, data hiding, and object-oriented data types.

  5. Applications written in PL/SQL are fully portable.

  6. PL/SQL provides high security level.

  7. PL/SQL provides access to predefined SQL packages.

  8. PL/SQL provides support for Object-Oriented Programming.

  9. PL/SQL provides support for developing Web Applications and Server Pages.

PL/SQL - Environment Setup

在本章中,我们将讨论 PL/SQL 的环境设置。PL/SQL 不是一个独立的编程语言;它是 Oracle 编程环境中的一个工具。 SQL Plus* 是一个交互式工具,它允许你在命令提示符处键入 SQL 和 PL/SQL 语句。然后将这些命令发送到数据库进行处理。一旦这些语句 được xử lý,结果将被发送回并在屏幕上显示。

In this chapter, we will discuss the Environment Setup of PL/SQL. PL/SQL is not a standalone programming language; it is a tool within the Oracle programming environment. SQL Plus* is an interactive tool that allows you to type SQL and PL/SQL statements at the command prompt. These commands are then sent to the database for processing. Once the statements are processed, the results are sent back and displayed on screen.

要运行 PL/SQL 程序,你应该在你的机器上安装了 Oracle RDBMS Server。这将负责执行 SQL 命令。Oracle RDBMS 的最新版本是 11g。你可以从以下链接下载 Oracle 11g 的试用版 -

To run PL/SQL programs, you should have the Oracle RDBMS Server installed in your machine. This will take care of the execution of the SQL commands. The most recent version of Oracle RDBMS is 11g. You can download a trial version of Oracle 11g from the following link −

你将不得不根据你的操作系统下载 32 位或 64 位版本的安装程序。通常有两个文件。我们下载了 64 位版本。你还可以对你的操作系统使用类似的步骤,无论它是 Linux 还是 Solaris。

You will have to download either the 32-bit or the 64-bit version of the installation as per your operating system. Usually there are two files. We have downloaded the 64-bit version. You will also use similar steps on your operating system, does not matter if it is Linux or Solaris.

  1. win64_11gR2_database_1of2.zip

  2. win64_11gR2_database_2of2.zip

在下载以上两个文件后,你需要将它们解压到一个目录 database 中,并在该目录下你会找到以下子目录 -

After downloading the above two files, you will need to unzip them in a single directory database and under that you will find the following sub-directories −

oracle sub directories

Step 1

现在让我们使用安装文件启动 Oracle Database Installer。以下是第一个屏幕。你可以提供你的电子邮件 ID,并选中复选框,如以下屏幕截图所示。单击 Next 按钮。

Let us now launch the Oracle Database Installer using the setup file. Following is the first screen. You can provide your email ID and check the checkbox as shown in the following screenshot. Click the Next button.

oracle install step1

Step 2

系统将把你定向到以下屏幕;取消选中复选框,然后单击 Continue 按钮继续。

You will be directed to the following screen; uncheck the checkbox and click the Continue button to proceed.

oracle install error1

Step 3

使用单选按钮仅选择第一个选项 Create and Configure Database ,然后单击 Next 按钮继续。

Just select the first option Create and Configure Database using the radio button and click the Next button to proceed.

oracle install step2

Step 4

我们假设你正在安装 Oracle 以用于基本的学习目的,并且你正在你的 PC 或笔记本电脑上安装它。因此,选择 Desktop Class 选项,然后单击 Next 按钮继续。

We assume you are installing Oracle for the basic purpose of learning and that you are installing it on your PC or Laptop. Thus, select the Desktop Class option and click the Next button to proceed.

oracle install step3

Step 5

提供一个安装 Oracle 服务器的位置。只需修改 Oracle Base ,其他位置将自动设置。你還需要提供一个密码;此密码将由系统 DBA 使用。一旦你提供了所需的信息,单击 Next 按钮继续。

Provide a location, where you will install the Oracle Server. Just modify the Oracle Base and the other locations will set automatically. You will also have to provide a password; this will be used by the system DBA. Once you provide the required information, click the Next button to proceed.

oracle install step4

Step 6

再次单击 Next 按钮继续。

Again, click the Next button to proceed.

oracle install step5

Step 7

单击 Finish 按钮继续;这将启动实际的服务器安装。

Click the Finish button to proceed; this will start the actual server installation.

oracle install step6

Step 8

这将会花些片刻时间,直到 Oracle 开始执行必需的配置。

This will take a few moments, until Oracle starts performing the required configuration.

oracle install step7

Step 9

在此,Oracle 安装将复制必需的配置文件。这应该需要片刻时间−

Here, Oracle installation will copy the required configuration files. This should take a moment −

oracle install configuration1

Step 10

复制数据库文件后,您将看到以下对话框。只需单击 OK 按钮并退出。

Once the database files are copied, you will have the following dialogue box. Just click the OK button and come out.

oracle install configuration2

Step 11

安装后,您将看到以下最终窗口。

Upon installation, you will have the following final window.

oracle install step8

Final Step

现在是验证您的安装的时候了。在命令提示符处,如果您使用的是 Windows,请使用以下命令:−

It is now time to verify your installation. At the command prompt, use the following command if you are using Windows −

sqlplus "/ as sysdba"

您应该拥有用于编写 PL/SQL 命令和脚本的 SQL 提示符 −

You should have the SQL prompt where you will write your PL/SQL commands and scripts −

plsql command prompt

Text Editor

从命令提示符运行大型程序可能会导致无意中丢失部分工作。始终建议使用命令文件。要使用命令文件−

Running large programs from the command prompt may land you in inadvertently losing some of the work. It is always recommended to use the command files. To use the command files −

  1. Type your code in a text editor, like Notepad, Notepad+, or EditPlus, etc.

  2. Save the file with the .sql extension in the home directory.

  3. Launch the SQL*Plus command prompt from the directory where you created your PL/SQL file.

  4. Type @file_name at the SQL*Plus command prompt to execute your program.

如果您不使用文件执行 PL/SQL 脚本,则只需复制 PL/SQL 代码并右键单击显示 SQL 提示符的黑色窗口;使用 paste 选项将完整代码粘贴到命令提示符中。最后,如果尚未执行代码,只需按 Enter 即可执行代码。

If you are not using a file to execute the PL/SQL scripts, then simply copy your PL/SQL code and right-click on the black window that displays the SQL prompt; use the paste option to paste the complete code at the command prompt. Finally, just press Enter to execute the code, if it is not already executed.

PL/SQL - Basic Syntax

在本章中,我们将讨论 PL/SQL 的基本语法,这是一种 block-structured 语言;这意味着 PL/SQL 程序被划分为逻辑代码块并编写在这些逻辑代码块中。每个块包含三个子部分:−

In this chapter, we will discuss the Basic Syntax of PL/SQL which is a block-structured language; this means that the PL/SQL programs are divided and written in logical blocks of code. Each block consists of three sub-parts −

S.No

Sections & Description

1

Declarations This section starts with the keyword DECLARE. It is an optional section and defines all variables, cursors, subprograms, and other elements to be used in the program.

2

Executable Commands This section is enclosed between the keywords BEGIN and END and it is a mandatory section. It consists of the executable PL/SQL statements of the program. It should have at least one executable line of code, which may be just a NULL command to indicate that nothing should be executed.

3

Exception Handling This section starts with the keyword EXCEPTION. This optional section contains exception(s) that handle errors in the program.

每个 PL/SQL 语句都以分号 (;) 结尾。PL/SQL 块可以使用 BEGINEND 嵌套在其他 PL/SQL 块内。以下是 PL/SQL 块的基本结构:−

Every PL/SQL statement ends with a semicolon (;). PL/SQL blocks can be nested within other PL/SQL blocks using BEGIN and END. Following is the basic structure of a PL/SQL block −

DECLARE
   <declarations section>
BEGIN
   <executable command(s)>
EXCEPTION
   <exception handling>
END;

The 'Hello World' Example

DECLARE
   message  varchar2(20):= 'Hello, World!';
BEGIN
   dbms_output.put_line(message);
END;
/

end; 行表示 PL/SQL 块的结束。要在 SQL 命令行中运行代码,您可能需要在代码最后一行之后的第一个空白行的开头键入 /。在 SQL 提示符处执行以上代码时,它产生以下结果:−

The end; line signals the end of the PL/SQL block. To run the code from the SQL command line, you may need to type / at the beginning of the first blank line after the last line of the code. When the above code is executed at the SQL prompt, it produces the following result −

Hello World

PL/SQL procedure successfully completed.

The PL/SQL Identifiers

PL/SQL 标识符是常量、变量、异常、过程、游标和保留字。标识符由一个字母(后面可以跟更多字母、数字、美元符号、下划线和数字符号)组成,并且不应超过 30 个字符。

PL/SQL identifiers are constants, variables, exceptions, procedures, cursors, and reserved words. The identifiers consist of a letter optionally followed by more letters, numerals, dollar signs, underscores, and number signs and should not exceed 30 characters.

默认情况下, identifiers are not case-sensitive 。因此,你可以使用 integer 或者 INTEGER 来表示数值。你不能将保留关键字用作标识符。

By default, identifiers are not case-sensitive. So you can use integer or INTEGER to represent a numeric value. You cannot use a reserved keyword as an identifier.

The PL/SQL Delimiters

分隔符是具有特殊含义的符号。以下是 PL/SQL 中的分隔符列表:

A delimiter is a symbol with a special meaning. Following is the list of delimiters in PL/SQL −

Delimiter

Description

+, -, *, /

Addition, subtraction/negation, multiplication, division

%

Attribute indicator

'

Character string delimiter

.

Component selector

(,)

Expression or list delimiter

:

Host variable indicator

,

Item separator

"

Quoted identifier delimiter

=

Relational operator

@

Remote access indicator

;

Statement terminator

:=

Assignment operator

Association operator

*

*

Concatenation operator

**

Exponentiation operator

<<, >>

Label delimiter (begin and end)

/, /

Multi-line comment delimiter (begin and end)

--

Single-line comment indicator

..

Range operator

<, >, ⇐, >=

Relational operators

<>, '=, ~=, ^=

Different versions of NOT EQUAL

The PL/SQL Comments

程序注释是可以包括在你所编写的 PL/SQL 代码中的解释性语句,并且有助于其他人阅读其源代码。所有编程语言都允许某种形式的注释。

Program comments are explanatory statements that can be included in the PL/SQL code that you write and helps anyone reading its source code. All programming languages allow some form of comments.

PL/SQL 支持单行和多行注释。PL/SQL 编译器会忽略出现在任何注释中的所有字符。PL/SQL 单行注释以分隔符 (双连字符) 开始,多行注释则由 /* 和 */ 括住。

The PL/SQL supports single-line and multi-line comments. All characters available inside any comment are ignored by the PL/SQL compiler. The PL/SQL single-line comments start with the delimiter — (double hyphen) and multi-line comments are enclosed by /* and */.

DECLARE
   -- variable declaration
   message  varchar2(20):= 'Hello, World!';
BEGIN
   /*
   *  PL/SQL executable statement(s)
   */
   dbms_output.put_line(message);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Hello World

PL/SQL procedure successfully completed.

PL/SQL Program Units

PL/SQL 单元是以下任一项:

A PL/SQL unit is any one of the following −

  1. PL/SQL block

  2. Function

  3. Package

  4. Package body

  5. Procedure

  6. Trigger

  7. Type

  8. Type body

下文章节将讨论这些单元中的每个单元。

Each of these units will be discussed in the following chapters.

PL/SQL - Data Types

本章中,我们将讨论 PL/SQL 中的数据类型。PL/SQL 变量、常量和参数必须具有有效的数据类型,该数据类型指定了存储格式、约束和有效范围。本章中,我们将重点介绍 SCALARLOB 数据类型。其他两个数据类型将在其他章节中介绍。

In this chapter, we will discuss the Data Types in PL/SQL. The PL/SQL variables, constants and parameters must have a valid data type, which specifies a storage format, constraints, and a valid range of values. We will focus on the SCALAR and the LOB data types in this chapter. The other two data types will be covered in other chapters.

S.No

Category & Description

1

Scalar Single values with no internal components, such as a NUMBER, DATE, or BOOLEAN.

2

Large Object (LOB) Pointers to large objects that are stored separately from other data items, such as text, graphic images, video clips, and sound waveforms.

3

Composite Data items that have internal components that can be accessed individually. For example, collections and records.

4

Reference Pointers to other data items.

PL/SQL Scalar Data Types and Subtypes

PL/SQL 标量数据类型和子类型属于以下类别 −

PL/SQL Scalar Data Types and Subtypes come under the following categories −

S.No

Date Type & Description

1

Numeric Numeric values on which arithmetic operations are performed.

2

Character Alphanumeric values that represent single characters or strings of characters.

3

Boolean Logical values on which logical operations are performed.

4

Datetime Dates and times.

PL/SQL 提供数据类型的子类型。例如,数据类型 NUMBER 具有名为 INTEGER 的子类型。在将 PL/SQL 代码嵌入到其他程序(例如 Java 程序)时,可以在 PL/SQL 程序中使用子类型来使数据类型与其他程序中的数据类型兼容。

PL/SQL provides subtypes of data types. For example, the data type NUMBER has a subtype called INTEGER. You can use the subtypes in your PL/SQL program to make the data types compatible with data types in other programs while embedding the PL/SQL code in another program, such as a Java program.

PL/SQL Numeric Data Types and Subtypes

下表列出了 PL/SQL 预定义的数值数据类型及其子类型 −

Following table lists out the PL/SQL pre-defined numeric data types and their sub-types −

S.No

Data Type & Description

1

PLS_INTEGER Signed integer in range -2,147,483,648 through 2,147,483,647, represented in 32 bits

2

BINARY_INTEGER Signed integer in range -2,147,483,648 through 2,147,483,647, represented in 32 bits

3

BINARY_FLOAT Single-precision IEEE 754-format floating-point number

4

BINARY_DOUBLE Double-precision IEEE 754-format floating-point number

5

NUMBER(prec, scale) Fixed-point or floating-point number with absolute value in range 1E-130 to (but not including) 1.0E126. A NUMBER variable can also represent 0

6

DEC(prec, scale) ANSI specific fixed-point type with maximum precision of 38 decimal digits

7

DECIMAL(prec, scale) IBM specific fixed-point type with maximum precision of 38 decimal digits

8

NUMERIC(pre, secale) Floating type with maximum precision of 38 decimal digits

9

DOUBLE PRECISION ANSI specific floating-point type with maximum precision of 126 binary digits (approximately 38 decimal digits)

10

FLOAT ANSI and IBM specific floating-point type with maximum precision of 126 binary digits (approximately 38 decimal digits)

11

INT ANSI specific integer type with maximum precision of 38 decimal digits

12

INTEGER ANSI and IBM specific integer type with maximum precision of 38 decimal digits

13

SMALLINT ANSI and IBM specific integer type with maximum precision of 38 decimal digits

14

REAL Floating-point type with maximum precision of 63 binary digits (approximately 18 decimal digits)

以下是一个有效的声明 −

Following is a valid declaration −

DECLARE
   num1 INTEGER;
   num2 REAL;
   num3 DOUBLE PRECISION;
BEGIN
   null;
END;
/

编译并执行上述代码后,将产生以下结果 −

When the above code is compiled and executed, it produces the following result −

PL/SQL procedure successfully completed

PL/SQL Character Data Types and Subtypes

以下是 PL/SQL 预定义字符数据类型及其子类型 −

Following is the detail of PL/SQL pre-defined character data types and their sub-types −

S.No

Data Type & Description

1

CHAR Fixed-length character string with maximum size of 32,767 bytes

2

VARCHAR2 Variable-length character string with maximum size of 32,767 bytes

3

RAW Variable-length binary or byte string with maximum size of 32,767 bytes, not interpreted by PL/SQL

4

NCHAR Fixed-length national character string with maximum size of 32,767 bytes

5

NVARCHAR2 Variable-length national character string with maximum size of 32,767 bytes

6

LONG Variable-length character string with maximum size of 32,760 bytes

7

LONG RAW Variable-length binary or byte string with maximum size of 32,760 bytes, not interpreted by PL/SQL

8

ROWID Physical row identifier, the address of a row in an ordinary table

9

UROWID Universal row identifier (physical, logical, or foreign row identifier)

PL/SQL Boolean Data Types

BOOLEAN 数据类型存储在逻辑运算中使用的逻辑值。逻辑值为布尔值 TRUEFALSE 以及值 NULL

The BOOLEAN data type stores logical values that are used in logical operations. The logical values are the Boolean values TRUE and FALSE and the value NULL.

然而,SQL 没有等同于 BOOLEAN 的数据类型。因此,布尔值不能在 − 中使用

However, SQL has no data type equivalent to BOOLEAN. Therefore, Boolean values cannot be used in −

  1. SQL statements

  2. Built-in SQL functions (such as TO_CHAR)

  3. PL/SQL functions invoked from SQL statements

PL/SQL Datetime and Interval Types

DATE 数据类型用于存储固定长度日期时间,其中包括自午夜以来的时间(以秒为单位)。有效的日期范围是从公元前 4712 年 1 月 1 日到公元 9999 年 12 月 31 日。

The DATE datatype is used to store fixed-length datetimes, which include the time of day in seconds since midnight. Valid dates range from January 1, 4712 BC to December 31, 9999 AD.

默认日期格式由 Oracle 初始化参数 NLS_DATE_FORMAT 设置。例如,默认可能为“DD-MON-YY”,其中包括一个用于表示当月日期的两位数字、月份名称的缩写以及该年的最后两位数字。例如,01-OCT-12。

The default date format is set by the Oracle initialization parameter NLS_DATE_FORMAT. For example, the default might be 'DD-MON-YY', which includes a two-digit number for the day of the month, an abbreviation of the month name, and the last two digits of the year. For example, 01-OCT-12.

每个 DATE 包含世纪、年、月、日、小时、分钟和秒。下表显示了每个字段的有效值 −

Each DATE includes the century, year, month, day, hour, minute, and second. The following table shows the valid values for each field −

Field Name

Valid Datetime Values

Valid Interval Values

YEAR

-4712 to 9999 (excluding year 0)

Any nonzero integer

MONTH

01 to 12

0 to 11

DAY

01 to 31 (limited by the values of MONTH and YEAR, according to the rules of the calendar for the locale)

Any nonzero integer

HOUR

00 to 23

0 to 23

MINUTE

00 to 59

0 to 59

SECOND

00 to 59.9(n), where 9(n) is the precision of time fractional seconds

0 to 59.9(n), where 9(n) is the precision of interval fractional seconds

TIMEZONE_HOUR

-12 to 14 (range accommodates daylight savings time changes)

Not applicable

TIMEZONE_MINUTE

00 to 59

Not applicable

TIMEZONE_REGION

Found in the dynamic performance view V$TIMEZONE_NAMES

Not applicable

TIMEZONE_ABBR

Found in the dynamic performance view V$TIMEZONE_NAMES

Not applicable

PL/SQL Large Object (LOB) Data Types

大型对象 (LOB) 数据类型是指大型数据项,例如文本、图形图像、视频剪辑和声音波形。LOB 数据类型允许高效、随机、分块访问这些数据。以下是预定义的 PL/SQL LOB 数据类型 −

Large Object (LOB) data types refer to large data items such as text, graphic images, video clips, and sound waveforms. LOB data types allow efficient, random, piecewise access to this data. Following are the predefined PL/SQL LOB data types −

Data Type

Description

Size

BFILE

Used to store large binary objects in operating system files outside the database.

System-dependent. Cannot exceed 4 gigabytes (GB).

BLOB

Used to store large binary objects in the database.

8 to 128 terabytes (TB)

CLOB

Used to store large blocks of character data in the database.

8 to 128 TB

NCLOB

Used to store large blocks of NCHAR data in the database.

8 to 128 TB

PL/SQL User-Defined Subtypes

子类型是其他数据类型的子集,后者称为其基础类型。子类型具有与其基础类型相同有效的操作,但其有效值仅为其子集。

A subtype is a subset of another data type, which is called its base type. A subtype has the same valid operations as its base type, but only a subset of its valid values.

PL/SQL 在包 STANDARD 中预定义了几个子类型。例如,PL/SQL 预定义了子类型 CHARACTERINTEGER ,如下所示:

PL/SQL predefines several subtypes in package STANDARD. For example, PL/SQL predefines the subtypes CHARACTER and INTEGER as follows −

SUBTYPE CHARACTER IS CHAR;
SUBTYPE INTEGER IS NUMBER(38,0);

您可以定义和使用您自己的子类型。下述程序说明了如何定义和使用用户定义的子类型:

You can define and use your own subtypes. The following program illustrates defining and using a user-defined subtype −

DECLARE
   SUBTYPE name IS char(20);
   SUBTYPE message IS varchar2(100);
   salutation name;
   greetings message;
BEGIN
   salutation := 'Reader ';
   greetings := 'Welcome to the World of PL/SQL';
   dbms_output.put_line('Hello ' || salutation || greetings);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Hello Reader Welcome to the World of PL/SQL

PL/SQL procedure successfully completed.

NULLs in PL/SQL

PL/SQL NULL 值表示 missingunknown data ,它们不是整数、字符或任何其他特定数据类型。请注意, NULL 与空数据字符串或空字符值 '\0' 不同。可以赋值 NULL,但它不能与任何内容相等,包括它自身。

PL/SQL NULL values represent missing or unknown data and they are not an integer, a character, or any other specific data type. Note that NULL is not the same as an empty data string or the null character value '\0'. A null can be assigned but it cannot be equated with anything, including itself.

PL/SQL - Variables

在本章中,我们将讨论 Pl/SQL 中的变量。变量不过是赋予存储区域的一个名称,存储区域可以被我们的程序操作。PL/SQL 中的每个变量都有一个特定的数据类型,此数据类型确定变量内存的大小和布局;可存储在此内存中的值的范围;以及可应用于变量的操作集。

In this chapter, we will discuss Variables in Pl/SQL. A variable is nothing but a name given to a storage area that our programs can manipulate. Each variable in PL/SQL has a specific data type, which determines the size and the layout of the variable’s memory; the range of values that can be stored within that memory and the set of operations that can be applied to the variable.

PL/SQL 变量的名称由一个字母组成(可以后跟更多的字母、数字、美元符号、下划线和数字符号),且不应超过 30 个字符。默认情况下,变量名称不区分大小写。你不能使用保留的 PL/SQL 关键字作为变量名称。

The name of a PL/SQL variable consists of a letter optionally followed by more letters, numerals, dollar signs, underscores, and number signs and should not exceed 30 characters. By default, variable names are not case-sensitive. You cannot use a reserved PL/SQL keyword as a variable name.

PL/SQL 编程语言允许定义各种类型的变量,例如日期时间数据类型、记录、集合等,我们将在后续的章节中介绍这些内容。对于本章,我们只研究基本变量类型。

PL/SQL programming language allows to define various types of variables, such as date time data types, records, collections, etc. which we will cover in subsequent chapters. For this chapter, let us study only basic variable types.

Variable Declaration in PL/SQL

PL/SQL 变量必须在声明部分中声明,或在包中声明为全局变量。当你声明变量时,PL/SQL 将为变量的值分配内存,并且存储位置由变量名称识别。

PL/SQL variables must be declared in the declaration section or in a package as a global variable. When you declare a variable, PL/SQL allocates memory for the variable’s value and the storage location is identified by the variable name.

声明变量的语法为:

The syntax for declaring a variable is −

variable_name [CONSTANT] datatype [NOT NULL] [:= | DEFAULT initial_value]

其中,variable_name 是 PL/SQL 中的有效标识符,datatype 必须是有效的 PL/SQL 数据类型或任何用户定义的数据类型,我们已经在上一章中讨论过了。下面显示了一些有效的变量声明及其定义:

Where, variable_name is a valid identifier in PL/SQL, datatype must be a valid PL/SQL data type or any user defined data type which we already have discussed in the last chapter. Some valid variable declarations along with their definition are shown below −

sales number(10, 2);
pi CONSTANT double precision := 3.1415;
name varchar2(25);
address varchar2(100);

当你在数据类型中提供大小、范围或精度限制时,这被称为 constrained declaration 。受限声明需要的内存比不受限声明少。例如:

When you provide a size, scale or precision limit with the data type, it is called a constrained declaration. Constrained declarations require less memory than unconstrained declarations. For example −

sales number(10, 2);
name varchar2(25);
address varchar2(100);

Initializing Variables in PL/SQL

每当你声明一个变量时,PL/SQL 都会为其分配默认值 NULL。如果你想使用非 NULL 值初始化变量,你可以在声明期间使用以下任意一种方法来执行此操作:

Whenever you declare a variable, PL/SQL assigns it a default value of NULL. If you want to initialize a variable with a value other than the NULL value, you can do so during the declaration, using either of the following −

  1. The DEFAULT keyword

  2. The assignment operator

例如 -

For example −

counter binary_integer := 0;
greetings varchar2(20) DEFAULT 'Have a Good Day';

你还可以使用 NOT NULL 约束指定变量不应该具有 NULL 值。如果你使用 NOT NULL 约束,你必须明确针对该变量指定一个初始值。

You can also specify that a variable should not have a NULL value using the NOT NULL constraint. If you use the NOT NULL constraint, you must explicitly assign an initial value for that variable.

正确初始化变量是一种良好的编程实践,否则,程序有时会产生意外结果。试用以下示例,它使用了各种类型的变量:

It is a good programming practice to initialize variables properly otherwise, sometimes programs would produce unexpected results. Try the following example which makes use of various types of variables −

DECLARE
   a integer := 10;
   b integer := 20;
   c integer;
   f real;
BEGIN
   c := a + b;
   dbms_output.put_line('Value of c: ' || c);
   f := 70.0/3.0;
   dbms_output.put_line('Value of f: ' || f);
END;
/

执行上述代码后,将生成以下结果 −

When the above code is executed, it produces the following result −

Value of c: 30
Value of f: 23.333333333333333333

PL/SQL procedure successfully completed.

Variable Scope in PL/SQL

PL/SQL 允许块的嵌套,即每个程序块都可以包含另一个内部块。如果一个变量在内部块中声明,则外部块无法访问该变量。但是,如果一个变量在外部块中声明且可访问,则所有嵌套内部块也可以访问该变量。有两种类型的变量作用域 -

PL/SQL allows the nesting of blocks, i.e., each program block may contain another inner block. If a variable is declared within an inner block, it is not accessible to the outer block. However, if a variable is declared and accessible to an outer block, it is also accessible to all nested inner blocks. There are two types of variable scope −

  1. Local variables − Variables declared in an inner block and not accessible to outer blocks.

  2. Global variables − Variables declared in the outermost block or a package.

下面示例以简单形式说明了 LocalGlobal 变量的用法 −

Following example shows the usage of Local and Global variables in its simple form −

DECLARE
   -- Global variables
   num1 number := 95;
   num2 number := 85;
BEGIN
   dbms_output.put_line('Outer Variable num1: ' || num1);
   dbms_output.put_line('Outer Variable num2: ' || num2);
   DECLARE
      -- Local variables
      num1 number := 195;
      num2 number := 185;
   BEGIN
      dbms_output.put_line('Inner Variable num1: ' || num1);
      dbms_output.put_line('Inner Variable num2: ' || num2);
   END;
END;
/

执行上述代码后,将生成以下结果 −

When the above code is executed, it produces the following result −

Outer Variable num1: 95
Outer Variable num2: 85
Inner Variable num1: 195
Inner Variable num2: 185

PL/SQL procedure successfully completed.

Assigning SQL Query Results to PL/SQL Variables

可以使用 SQL 的 SELECT INTO 语句为 PL/SQL 变量赋值。 SELECT list 中的每个项目都必须在 INTO list 中有一个相应的类型兼容变量。以下示例说明了这个概念。让我们创建一个名为 CUSTOMERS 的表 −

You can use the SELECT INTO statement of SQL to assign values to PL/SQL variables. For each item in the SELECT list, there must be a corresponding, type-compatible variable in the INTO list. The following example illustrates the concept. Let us create a table named CUSTOMERS −

( For SQL statements, please refer to the SQL tutorial )

(For SQL statements, please refer to the SQL tutorial)

CREATE TABLE CUSTOMERS(
   ID   INT NOT NULL,
   NAME VARCHAR (20) NOT NULL,
   AGE INT NOT NULL,
   ADDRESS CHAR (25),
   SALARY   DECIMAL (18, 2),
   PRIMARY KEY (ID)
);

Table Created

现在让我们在表中插入一些值 −

Let us now insert some values in the table −

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (3, 'kaushik', 23, 'Kota', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (6, 'Komal', 22, 'MP', 4500.00 );

以下程序使用 SQL 的 SELECT INTO clause 将上述表中的值分配给 PL/SQL 变量 −

The following program assigns values from the above table to PL/SQL variables using the SELECT INTO clause of SQL −

DECLARE
   c_id customers.id%type := 1;
   c_name  customers.name%type;
   c_addr customers.address%type;
   c_sal  customers.salary%type;
BEGIN
   SELECT name, address, salary INTO c_name, c_addr, c_sal
   FROM customers
   WHERE id = c_id;
   dbms_output.put_line
   ('Customer ' ||c_name || ' from ' || c_addr || ' earns ' || c_sal);
END;
/

执行上述代码后,将生成以下结果 −

When the above code is executed, it produces the following result −

Customer Ramesh from Ahmedabad earns 2000

PL/SQL procedure completed successfully

PL/SQL - Constants and Literals

在本章中,我们将讨论 PL/SQL 中的 constantsliterals 。常量保存的值一旦声明,就不会在程序中更改。常量声明指定其名称、数据类型和值,并为其分配存储。声明还可以施加 NOT NULL constraint

In this chapter, we will discuss constants and literals in PL/SQL. A constant holds a value that once declared, does not change in the program. A constant declaration specifies its name, data type, and value, and allocates storage for it. The declaration can also impose the NOT NULL constraint.

Declaring a Constant

常量使用 CONSTANT 关键字声明。它需要一个初始值,并且不允许更改该值。例如 −

A constant is declared using the CONSTANT keyword. It requires an initial value and does not allow that value to be changed. For example −

PI CONSTANT NUMBER := 3.141592654;
DECLARE
   -- constant declaration
   pi constant number := 3.141592654;
   -- other declarations
   radius number(5,2);
   dia number(5,2);
   circumference number(7, 2);
   area number (10, 2);
BEGIN
   -- processing
   radius := 9.5;
   dia := radius * 2;
   circumference := 2.0 * pi * radius;
   area := pi * radius * radius;
   -- output
   dbms_output.put_line('Radius: ' || radius);
   dbms_output.put_line('Diameter: ' || dia);
   dbms_output.put_line('Circumference: ' || circumference);
   dbms_output.put_line('Area: ' || area);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Radius: 9.5
Diameter: 19
Circumference: 59.69
Area: 283.53

Pl/SQL procedure successfully completed.

The PL/SQL Literals

文字是一个明确的数字、字符、字符串或布尔值,而不是由标识符表示。例如,TRUE、786、NULL、'tutorialspoint' 都是布尔、数字或字符串类型的文字。在 PL/SQL 中,文字区分大小写。PL/SQL 支持以下类型的文字 −

A literal is an explicit numeric, character, string, or Boolean value not represented by an identifier. For example, TRUE, 786, NULL, 'tutorialspoint' are all literals of type Boolean, number, or string. PL/SQL, literals are case-sensitive. PL/SQL supports the following kinds of literals −

  1. Numeric Literals

  2. Character Literals

  3. String Literals

  4. BOOLEAN Literals

  5. Date and Time Literals

下表提供以上所有类文字值的示例。

The following table provides examples from all these categories of literal values.

S.No

Literal Type & Example

1

Numeric Literals 050 78 -14 0 +32767 6.6667 0.0 -12.0 3.14159 +7800.00 6E5 1.0E-8 3.14159e0 -1E38 -9.5e-3

2

Character Literals 'A' '%' '9' ' ' 'z' '('

3

String Literals 'Hello, world!' 'Tutorials Point' '19-NOV-12'

4

BOOLEAN Literals TRUE, FALSE, and NULL.

5

Date and Time Literals DATE '1978-12-25'; TIMESTAMP '2012-10-29 12:01:01';

要在字符串文字中嵌入单引号,请像以下程序所示将两个单引号并排放置 −

To embed single quotes within a string literal, place two single quotes next to each other as shown in the following program −

DECLARE
   message  varchar2(30):= 'That''s tutorialspoint.com!';
BEGIN
   dbms_output.put_line(message);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

That's tutorialspoint.com!

PL/SQL procedure successfully completed.

PL/SQL - Operators

在本章中,我们将讨论 PL/SQL 中的操作符。操作符是一个符号,告诉编译器执行特定的数学或逻辑操作。PL/SQL 语言中内置了丰富的操作符,并提供了以下类型的操作符 −

In this chapter, we will discuss operators in PL/SQL. An operator is a symbol that tells the compiler to perform specific mathematical or logical manipulation. PL/SQL language is rich in built-in operators and provides the following types of operators −

  1. Arithmetic operators

  2. Relational operators

  3. Comparison operators

  4. Logical operators

  5. String operators

在这里,我们将逐个了解算术、关系、比较和逻辑操作符。字符串操作符将在本章节后面讨论 − PL/SQL - Strings

Here, we will understand the arithmetic, relational, comparison and logical operators one by one. The String operators will be discussed in a later chapter − PL/SQL - Strings.

Arithmetic Operators

以下表格显示了 PL/SQL 支持的所有算术运算符。我们假设 variable A 含 10, variable B 含 5,则 −

Following table shows all the arithmetic operators supported by PL/SQL. Let us assume variable A holds 10 and variable B holds 5, then −

Operator

Description

Example

+

Adds two operands

A + B will give 15

-

Subtracts second operand from the first

A - B will give 5

*

Multiplies both operands

A * B will give 50

/

Divides numerator by de-numerator

A / B will give 2

**

Exponentiation operator, raises one operand to the power of other

A ** B will give 100000

Relational Operators

关系运算符比较两个表达式或值并返回布尔结果。以下表格显示了 PL/SQL 支持的所有关系运算符。我们假设 variable A 含 10, variable B 含 20,则 −

Relational operators compare two expressions or values and return a Boolean result. Following table shows all the relational operators supported by PL/SQL. Let us assume variable A holds 10 and variable B holds 20, then −

Operator

Description

Example

=

Checks if the values of two operands are equal or not, if yes then condition becomes true.

(A = B) is not true.

!= <> ~=

Checks if the values of two operands are equal or not, if values are not equal then condition becomes true.

(A != B) is true.

>

Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true.

(A > B) is not true.

<

Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true.

(A < B) is true.

>=

Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true.

(A >= B) is not true.

Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true.

(A ⇐ B) is true

Comparison Operators

比较运算符用于将一个表达式与另一个表达式进行比较。结果始终为 TRUE, FALSENULL

Comparison operators are used for comparing one expression to another. The result is always either TRUE, FALSE or NULL.

Operator

Description

Example

LIKE

The LIKE operator compares a character, string, or CLOB value to a pattern and returns TRUE if the value matches the pattern and FALSE if it does not.

If 'Zara Ali' like 'Z% A_i' returns a Boolean true, whereas, 'Nuha Ali' like 'Z% A_i' returns a Boolean false.

BETWEEN

The BETWEEN operator tests whether a value lies in a specified range. x BETWEEN a AND b means that x >= a and x ⇐ b.

If x = 10 then, x between 5 and 20 returns true, x between 5 and 10 returns true, but x between 11 and 20 returns false.

IN

The IN operator tests set membership. x IN (set) means that x is equal to any member of set.

If x = 'm' then, x in ('a', 'b', 'c') returns Boolean false but x in ('m', 'n', 'o') returns Boolean true.

IS NULL

The IS NULL operator returns the BOOLEAN value TRUE if its operand is NULL or FALSE if it is not NULL. Comparisons involving NULL values always yield NULL.

If x = 'm', then 'x is null' returns Boolean false.

Logical Operators

下表显示 PL/SQL 支持的逻辑运算符。所有这些运算符都针对布尔操作数工作,并产生布尔结果。让我们假设 variable A 为真, variable B 为假,那么 −

Following table shows the Logical operators supported by PL/SQL. All these operators work on Boolean operands and produce Boolean results. Let us assume variable A holds true and variable B holds false, then −

Operator

Description

Examples

and

Called the logical AND operator. If both the operands are true then condition becomes true.

(A and B) is false.

or

Called the logical OR Operator. If any of the two operands is true then condition becomes true.

(A or B) is true.

not

Called the logical NOT Operator. Used to reverse the logical state of its operand. If a condition is true then Logical NOT operator will make it false.

not (A and B) is true.

PL/SQL Operator Precedence

运算符优先级确定表达式中项的分组。这会影响表达式的求值方式。某些运算符比其他运算符具有更高的优先级;例如,乘法运算符的优先级高于加法运算符。

Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.

例如, x = 7 + 3 * 2 ;在这里, x 被赋值为 13 ,而不是 20,因为运算符 * 的优先级高于 +,因此它首先与 3*2 相乘,然后再加到 7 中。

For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

此处,优先级最高的运算符显示在表顶部,优先级最低的运算符显示在表底部。在表达式中,将首先评估优先级较高的运算符。

Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

运算符的优先级如下:=、<、>、⇐、>=、<>、!=、~=、^=、IS NULL、LIKE、BETWEEN、IN。

The precedence of operators goes as follows: =, <, >, ⇐, >=, <>, !=, ~=, ^=, IS NULL, LIKE, BETWEEN, IN.

Operator

Operation

**

exponentiation

+, -

identity, negation

*, /

multiplication, division

+, -,

addition, subtraction, concatenation

comparison

NOT

logical negation

AND

conjunction

OR

inclusion

PL/SQL - Conditions

在本章中,我们将讨论 PL/SQL 中的条件。决策结构要求程序员指定一个或多个条件,以便由程序对其进行求值或测试,如果确定条件为真,则执行一条或多条语句,并且如果确定条件为假,则可以选择执行其他语句。

In this chapter, we will discuss conditions in PL/SQL. Decision-making structures require that the programmer specify one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.

以下是大多数编程语言中常见的条件(即决策制定)结构的通用形式 −

Following is the general form of a typical conditional (i.e., decision making) structure found in most of the programming languages −

decision making

PL/SQL 编程语言提供了以下类型的决策语句。单击以下链接查看其详细信息。

PL/SQL programming language provides following types of decision-making statements. Click the following links to check their detail.

S.No

Statement & Description

1

IF - THEN statementThe IF statement associates a condition with a sequence of statements enclosed by the keywords THEN and END IF. If the condition is true, the statements get executed and if the condition is false or NULL then the IF statement does nothing.

2

IF-THEN-ELSE statementIF statement adds the keyword ELSE followed by an alternative sequence of statement. If the condition is false or NULL, then only the alternative sequence of statements get executed. It ensures that either of the sequence of statements is executed.

3

IF-THEN-ELSIF statementIt allows you to choose between several alternatives.

4

Case statementLike the IF statement, the CASE statement selects one sequence of statements to execute. However, to select the sequence, the CASE statement uses a selector rather than multiple Boolean expressions. A selector is an expression whose value is used to select one of several alternatives.

5

Searched CASE statementThe searched CASE statement has no selector, and it’s WHEN clauses contain search conditions that yield Boolean values.

6

nested IF-THEN-ELSEYou can use one IF-THEN or IF-THEN-ELSIF statement inside another IF-THEN or IF-THEN-ELSIF statement(s).

PL/SQL - Loops

在本章中,我们将讨论 PL/SQL 中的循环。在很多情况下,需要多次执行代码块。通常,语句按顺序执行:函数中的第一个语句最先执行,然后是第二个,依此类推。

In this chapter, we will discuss Loops in PL/SQL. There may be a situation when you need to execute a block of code several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

编程语言提供了各种控制结构,允许执行更复杂的路径。

Programming languages provide various control structures that allow for more complicated execution paths.

循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 −

A loop statement allows us to execute a statement or group of statements multiple times and following is the general form of a loop statement in most of the programming languages −

loop architecture

PL/SQL 提供以下类型的循环来处理循环要求。点击以下链接查看其详细信息。

PL/SQL provides the following types of loop to handle the looping requirements. Click the following links to check their detail.

S.No

Loop Type & Description

1

PL/SQL Basic LOOPIn this loop structure, sequence of statements is enclosed between the LOOP and the END LOOP statements. At each iteration, the sequence of statements is executed and then control resumes at the top of the loop.

2

PL/SQL WHILE LOOPRepeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body.

3

PL/SQL FOR LOOPExecute a sequence of statements multiple times and abbreviates the code that manages the loop variable.

4

Nested loops in PL/SQLYou can use one or more loop inside any another basic loop, while, or for loop.

Labeling a PL/SQL Loop

可以标记 PL/SQL 循环。该标签应由双尖括号(<< 和 >>)括起来,并出现在 LOOP 语句的开头。标签名称也可以出现在 LOOP 语句的末尾。您可以在 EXIT 语句中使用该标签退出循环。

PL/SQL loops can be labeled. The label should be enclosed by double angle brackets (<< and >>) and appear at the beginning of the LOOP statement. The label name can also appear at the end of the LOOP statement. You may use the label in the EXIT statement to exit from the loop.

以下程序说明了这个概念 −

The following program illustrates the concept −

DECLARE
   i number(1);
   j number(1);
BEGIN
   << outer_loop >>
   FOR i IN 1..3 LOOP
      << inner_loop >>
      FOR j IN 1..3 LOOP
         dbms_output.put_line('i is: '|| i || ' and j is: ' || j);
      END loop inner_loop;
   END loop outer_loop;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

i is: 1 and j is: 1
i is: 1 and j is: 2
i is: 1 and j is: 3
i is: 2 and j is: 1
i is: 2 and j is: 2
i is: 2 and j is: 3
i is: 3 and j is: 1
i is: 3 and j is: 2
i is: 3 and j is: 3

PL/SQL procedure successfully completed.

The Loop Control Statements

循环控制语句改变了它在正常序列中的执行。当执行退出一个作用域时,在该作用域中创建的所有自动对象会被销毁。

Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.

PL/SQL 支持以下控制语句。标记循环还有助于控制循环外部。点击以下链接查看其详细信息。

PL/SQL supports the following control statements. Labeling loops also help in taking the control outside a loop. Click the following links to check their details.

S.No

Control Statement & Description

1

EXIT statementThe Exit statement completes the loop and control passes to the statement immediately after the END LOOP.

2

CONTINUE statementCauses the loop to skip the remainder of its body and immediately retest its condition prior to reiterating.

3

GOTO statementTransfers control to the labeled statement. Though it is not advised to use the GOTO statement in your program.

PL/SQL - Strings

PL/SQL 中的字符串实际上是一系列字符,可选择指定大小。这些字符可以是数字、字母、空格、特殊字符或它们的组合。PL/SQL 提供了三种字符串——

The string in PL/SQL is actually a sequence of characters with an optional size specification. The characters could be numeric, letters, blank, special characters or a combination of all. PL/SQL offers three kinds of strings −

  1. Fixed-length strings − In such strings, programmers specify the length while declaring the string. The string is right-padded with spaces to the length so specified.

  2. Variable-length strings − In such strings, a maximum length up to 32,767, for the string is specified and no padding takes place.

  3. Character large objects (CLOBs) − These are variable-length strings that can be up to 128 terabytes.

PL/SQL 字符串可以是变量或文本。字符串文本用引号括起来。例如,

PL/SQL strings could be either variables or literals. A string literal is enclosed within quotation marks. For example,

'This is a string literal.' Or 'hello world'

要在一串文字中包含一个单引号,您需要将两个单引号放在一起。例如,

To include a single quote inside a string literal, you need to type two single quotes next to one another. For example,

'this isn''t what it looks like'

Declaring String Variables

Oracle 数据库提供了多种字符串数据类型,例如 CHAR、NCHAR、VARCHAR2、NVARCHAR2、CLOB 和 NCLOB。前缀为 'N' 的数据类型是 'national character set' 数据类型,用于存储 Unicode 字符数据。

Oracle database provides numerous string datatypes, such as CHAR, NCHAR, VARCHAR2, NVARCHAR2, CLOB, and NCLOB. The datatypes prefixed with an 'N' are 'national character set' datatypes, that store Unicode character data.

如果您需要声明一个可变长度字符串,您必须提供该字符串的最大长度。例如,VARCHAR2 数据类型。以下示例说明如何声明并使用一些字符串变量——

If you need to declare a variable-length string, you must provide the maximum length of that string. For example, the VARCHAR2 data type. The following example illustrates declaring and using some string variables −

DECLARE
   name varchar2(20);
   company varchar2(30);
   introduction clob;
   choice char(1);
BEGIN
   name := 'John Smith';
   company := 'Infotech';
   introduction := ' Hello! I''m John Smith from Infotech.';
   choice := 'y';
   IF choice = 'y' THEN
      dbms_output.put_line(name);
      dbms_output.put_line(company);
      dbms_output.put_line(introduction);
   END IF;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

John Smith
Infotech
Hello! I'm John Smith from Infotech.

PL/SQL procedure successfully completed

若要声明定长字符串,请使用 CHAR 数据类型。在此处,您不必为定长变量指定最大长度。如果您省略长度约束,Oracle Database 会自动使用所需的最小长度。下列两个声明是相同的 −

To declare a fixed-length string, use the CHAR datatype. Here you do not have to specify a maximum length for a fixed-length variable. If you leave off the length constraint, Oracle Database automatically uses a maximum length required. The following two declarations are identical −

red_flag CHAR(1) := 'Y';
 red_flag CHAR   := 'Y';

PL/SQL String Functions and Operators

PL/SQL 提供连接符运算符 (||) ,用于连接两个字符串。下表提供了 PL/SQL 提供的字符串函数 −

PL/SQL offers the concatenation operator (||) for joining two strings. The following table provides the string functions provided by PL/SQL −

S.No

Function & Purpose

1

ASCII(x); Returns the ASCII value of the character x.

2

CHR(x); Returns the character with the ASCII value of x.

3

CONCAT(x, y); Concatenates the strings x and y and returns the appended string.

4

INITCAP(x); Converts the initial letter of each word in x to uppercase and returns that string.

5

INSTR(x, find_string [, start] [, occurrence]); Searches for find_string in x and returns the position at which it occurs.

6

INSTRB(x); Returns the location of a string within another string, but returns the value in bytes.

7

LENGTH(x); Returns the number of characters in x.

8

LENGTHB(x); Returns the length of a character string in bytes for single byte character set.

9

LOWER(x); Converts the letters in x to lowercase and returns that string.

10

LPAD(x, width [, pad_string]) ; Pads x with spaces to the left, to bring the total length of the string up to width characters.

11

LTRIM(x [, trim_string]); Trims characters from the left of x.

12

NANVL(x, value); Returns value if x matches the NaN special value (not a number), otherwise x is returned.

13

NLS_INITCAP(x); Same as the INITCAP function except that it can use a different sort method as specified by NLSSORT.

14

NLS_LOWER(x) ; Same as the LOWER function except that it can use a different sort method as specified by NLSSORT.

15

NLS_UPPER(x); Same as the UPPER function except that it can use a different sort method as specified by NLSSORT.

16

NLSSORT(x); Changes the method of sorting the characters. Must be specified before any NLS function; otherwise, the default sort will be used.

17

NVL(x, value); Returns value if x is null; otherwise, x is returned.

18

NVL2(x, value1, value2); Returns value1 if x is not null; if x is null, value2 is returned.

19

REPLACE(x, search_string, replace_string); Searches x for search_string and replaces it with replace_string.

20

RPAD(x, width [, pad_string]); Pads x to the right.

21

RTRIM(x [, trim_string]); Trims x from the right.

22

SOUNDEX(x) ; Returns a string containing the phonetic representation of x.

23

SUBSTR(x, start [, length]); Returns a substring of x that begins at the position specified by start. An optional length for the substring may be supplied.

24

SUBSTRB(x); Same as SUBSTR except that the parameters are expressed in bytes instead of characters for the single-byte character systems.

25

TRIM([trim_char FROM) x); Trims characters from the left and right of x.

26

UPPER(x); Converts the letters in x to uppercase and returns that string.

现在让我们通过几个示例来理解这个概念 -

Let us now work out on a few examples to understand the concept −

Example 1

DECLARE
   greetings varchar2(11) := 'hello world';
BEGIN
   dbms_output.put_line(UPPER(greetings));

   dbms_output.put_line(LOWER(greetings));

   dbms_output.put_line(INITCAP(greetings));

   /* retrieve the first character in the string */
   dbms_output.put_line ( SUBSTR (greetings, 1, 1));

   /* retrieve the last character in the string */
   dbms_output.put_line ( SUBSTR (greetings, -1, 1));

   /* retrieve five characters,
      starting from the seventh position. */
   dbms_output.put_line ( SUBSTR (greetings, 7, 5));

   /* retrieve the remainder of the string,
      starting from the second position. */
   dbms_output.put_line ( SUBSTR (greetings, 2));

   /* find the location of the first "e" */
   dbms_output.put_line ( INSTR (greetings, 'e'));
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

HELLO WORLD
hello world
Hello World
h
d
World
ello World
2

PL/SQL procedure successfully completed.

Example 2

DECLARE
   greetings varchar2(30) := '......Hello World.....';
BEGIN
   dbms_output.put_line(RTRIM(greetings,'.'));
   dbms_output.put_line(LTRIM(greetings, '.'));
   dbms_output.put_line(TRIM( '.' from greetings));
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

......Hello World
Hello World.....
Hello World

PL/SQL procedure successfully completed.

PL/SQL - Arrays

在本章中,我们将讨论 PL/SQL 中的数组。PL/SQL 编程语言提供了一个称为 VARRAY 的数据结构,它可以存储相同类型元素的固定大小顺序集合。varray 用于存储有序数据集合,但是往往最好将数组视为相同类型变量的集合。

In this chapter, we will discuss arrays in PL/SQL. The PL/SQL programming language provides a data structure called the VARRAY, which can store a fixed-size sequential collection of elements of the same type. A varray is used to store an ordered collection of data, however it is often better to think of an array as a collection of variables of the same type.

所有 varray 均由连续的内存位置组成。最低地址对应于第一个元素,最高地址对应于最后一个元素。

All varrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.

varrays

数组是集合类型数据的一部分,它代表可变大小的数组。我们将在后面一章中学习其他集合类型 'PL/SQL Collections'

An array is a part of collection type data and it stands for variable-size arrays. We will study other collection types in a later chapter 'PL/SQL Collections'.

varray 中的每个元素都有一个与之关联的索引。它还具有可以动态更改的最大大小。

Each element in a varray has an index associated with it. It also has a maximum size that can be changed dynamically.

Creating a Varray Type

Varray 类型由 CREATE TYPE 语句创建。你必须指定 varray 中存储的最大大小和元素类型。

A varray type is created with the CREATE TYPE statement. You must specify the maximum size and the type of elements stored in the varray.

在模式级别创建 VARRAY 类型的基本句法是 −

The basic syntax for creating a VARRAY type at the schema level is −

CREATE OR REPLACE TYPE varray_type_name IS VARRAY(n) of <element_type>

其中,

Where,

  1. varray_type_name is a valid attribute name,

  2. n is the number of elements (maximum) in the varray,

  3. element_type is the data type of the elements of the array.

可以使用 ALTER TYPE 语句更改 varray 的最大大小。

Maximum size of a varray can be changed using the ALTER TYPE statement.

例如,

For example,

CREATE Or REPLACE TYPE namearray AS VARRAY(3) OF VARCHAR2(10);
/

Type created.

在 PL/SQL 块中创建 VARRAY 类型的基本语法是 −

The basic syntax for creating a VARRAY type within a PL/SQL block is −

TYPE varray_type_name IS VARRAY(n) of <element_type>

例如 -

For example −

TYPE namearray IS VARRAY(5) OF VARCHAR2(10);
Type grades IS VARRAY(5) OF INTEGER;

现在让我们通过几个示例来理解这个概念 -

Let us now work out on a few examples to understand the concept −

Example 1

以下程序说明了 varray 的使用 −

The following program illustrates the use of varrays −

DECLARE
   type namesarray IS VARRAY(5) OF VARCHAR2(10);
   type grades IS VARRAY(5) OF INTEGER;
   names namesarray;
   marks grades;
   total integer;
BEGIN
   names := namesarray('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
   marks:= grades(98, 97, 78, 87, 92);
   total := names.count;
   dbms_output.put_line('Total '|| total || ' Students');
   FOR i in 1 .. total LOOP
      dbms_output.put_line('Student: ' || names(i) || '
      Marks: ' || marks(i));
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Total 5 Students
Student: Kavita  Marks: 98
Student: Pritam  Marks: 97
Student: Ayan  Marks: 78
Student: Rishav  Marks: 87
Student: Aziz  Marks: 92

PL/SQL procedure successfully completed.

Please note

Please note

  1. In Oracle environment, the starting index for varrays is always 1.

  2. You can initialize the varray elements using the constructor method of the varray type, which has the same name as the varray.

  3. Varrays are one-dimensional arrays.

  4. A varray is automatically NULL when it is declared and must be initialized before its elements can be referenced.

Example 2

varray 的元素也可以是数据库表的任何 %ROWTYPE 或数据库表字段的任何 %TYPE。以下示例对该概念进行了说明。

Elements of a varray could also be a %ROWTYPE of any database table or %TYPE of any database table field. The following example illustrates the concept.

我们将使用存储在数据库中的 CUSTOMERS 表,如下所示 −

We will use the CUSTOMERS table stored in our database as −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+

下面的示例使用 cursor ,你将在另一章中详细学习它。

Following example makes the use of cursor, which you will study in detail in a separate chapter.

DECLARE
   CURSOR c_customers is
   SELECT  name FROM customers;
   type c_list is varray (6) of customers.name%type;
   name_list c_list := c_list();
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter + 1;
      name_list.extend;
      name_list(counter)  := n.name;
      dbms_output.put_line('Customer('||counter ||'):'||name_list(counter));
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed.

PL/SQL - Procedures

在本章中,我们将讨论 PL/SQL 中的过程。 subprogram 是执行特定任务的程序单元/模块。这些子程序组合在一起形成更大的程序。这基本上被称为“模块化设计”。可以通过称为 calling program 的另一个子程序或程序来调用子程序。

In this chapter, we will discuss Procedures in PL/SQL. A subprogram is a program unit/module that performs a particular task. These subprograms are combined to form larger programs. This is basically called the 'Modular design'. A subprogram can be invoked by another subprogram or program which is called the calling program.

可以创建子程序 −

A subprogram can be created −

  1. At the schema level

  2. Inside a package

  3. Inside a PL/SQL block

在模式级别,子程序是 standalone subprogram 。它使用 CREATE PROCEDURE 或 CREATE FUNCTION 语句创建。它存储在数据库中,可以使用 DROP PROCEDURE 或 DROP FUNCTION 语句进行删除。

At the schema level, subprogram is a standalone subprogram. It is created with the CREATE PROCEDURE or the CREATE FUNCTION statement. It is stored in the database and can be deleted with the DROP PROCEDURE or DROP FUNCTION statement.

在包内创建的子程序是 packaged subprogram 。它存储在数据库中,并且仅当包使用 DROP PACKAGE 语句删除时才能删除。我们将在 'PL/SQL - Packages' 章中讨论包。

A subprogram created inside a package is a packaged subprogram. It is stored in the database and can be deleted only when the package is deleted with the DROP PACKAGE statement. We will discuss packages in the chapter 'PL/SQL - Packages'.

PL/SQL 子程序是带有一组参数的命名的 PL/SQL 块,可以使用这些参数对其进行调用。PL/SQL 提供两种子程序 −

PL/SQL subprograms are named PL/SQL blocks that can be invoked with a set of parameters. PL/SQL provides two kinds of subprograms −

  1. Functions − These subprograms return a single value; mainly used to compute and return a value.

  2. Procedures − These subprograms do not return a value directly; mainly used to perform an action.

本章将介绍 PL/SQL procedure 的重要方面。我们将在下一章讨论 PL/SQL function

This chapter is going to cover important aspects of a PL/SQL procedure. We will discuss PL/SQL function in the next chapter.

Parts of a PL/SQL Subprogram

每个 PL/SQL 子程序都有一个名称,还可以有一个参数列表。与匿名 PL/SQL 块一样,命名的块还将具有以下三部分 −

Each PL/SQL subprogram has a name, and may also have a parameter list. Like anonymous PL/SQL blocks, the named blocks will also have the following three parts −

S.No

Parts & Description

1

Declarative Part It is an optional part. However, the declarative part for a subprogram does not start with the DECLARE keyword. It contains declarations of types, cursors, constants, variables, exceptions, and nested subprograms. These items are local to the subprogram and cease to exist when the subprogram completes execution.

2

Executable Part This is a mandatory part and contains statements that perform the designated action.

3

Exception-handling This is again an optional part. It contains the code that handles run-time errors.

Creating a Procedure

使用 CREATE OR REPLACE PROCEDURE 语句来创建过程。CREATE OR REPLACE PROCEDURE 语句的简化语法如下 −

A procedure is created with the CREATE OR REPLACE PROCEDURE statement. The simplified syntax for the CREATE OR REPLACE PROCEDURE statement is as follows −

CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
{IS | AS}
BEGIN
  < procedure_body >
END procedure_name;

其中,

Where,

  1. procedure-name specifies the name of the procedure.

  2. [OR REPLACE] option allows the modification of an existing procedure.

  3. The optional parameter list contains name, mode and types of the parameters. IN represents the value that will be passed from outside and OUT represents the parameter that will be used to return a value outside of the procedure.

  4. procedure-body contains the executable part.

  5. The AS keyword is used instead of the IS keyword for creating a standalone procedure.

Example

以下示例创建了一个简单过程,在执行时,会在屏幕上显示字符串“Hello World!”。

The following example creates a simple procedure that displays the string 'Hello World!' on the screen when executed.

CREATE OR REPLACE PROCEDURE greetings
AS
BEGIN
   dbms_output.put_line('Hello World!');
END;
/

当使用 SQL 提示执行以上代码时,它将会生成以下结果 −

When the above code is executed using the SQL prompt, it will produce the following result −

Procedure created.

Executing a Standalone Procedure

独立过程可以通过两种方式来调用 −

A standalone procedure can be called in two ways −

  1. Using the EXECUTE keyword

  2. Calling the name of the procedure from a PL/SQL block

通过 EXECUTE 关键字可以调用名为 'greetings' 的上述过程,如下所示 −

The above procedure named 'greetings' can be called with the EXECUTE keyword as −

EXECUTE greetings;

上述调用将显示 −

The above call will display −

Hello World

PL/SQL procedure successfully completed.

这个过程也可从另一个 PL/SQL 块调用 -

The procedure can also be called from another PL/SQL block −

BEGIN
   greetings;
END;
/

上述调用将显示 −

The above call will display −

Hello World

PL/SQL procedure successfully completed.

Deleting a Standalone Procedure

使用 DROP PROCEDURE 语句删除独立过程。语法用于删除过程是 -

A standalone procedure is deleted with the DROP PROCEDURE statement. Syntax for deleting a procedure is −

DROP PROCEDURE procedure-name;

你可以使用以下语句来删除 greetings 过程 -

You can drop the greetings procedure by using the following statement −

DROP PROCEDURE greetings;

Parameter Modes in PL/SQL Subprograms

在 PL/SQL 子程序中输出参数模式列表 -

The following table lists out the parameter modes in PL/SQL subprograms −

S.No

Parameter Mode & Description

1

IN An IN parameter lets you pass a value to the subprogram. It is a read-only parameter. Inside the subprogram, an IN parameter acts like a constant. It cannot be assigned a value. You can pass a constant, literal, initialized variable, or expression as an IN parameter. You can also initialize it to a default value; however, in that case, it is omitted from the subprogram call. It is the default mode of parameter passing. Parameters are passed by reference.

2

OUT An OUT parameter returns a value to the calling program. Inside the subprogram, an OUT parameter acts like a variable. You can change its value and reference the value after assigning it. The actual parameter must be variable and it is passed by value.

3

IN OUT An IN OUT parameter passes an initial value to a subprogram and returns an updated value to the caller. It can be assigned a value and the value can be read. The actual parameter corresponding to an IN OUT formal parameter must be a variable, not a constant or an expression. Formal parameter must be assigned a value. Actual parameter is passed by value.

IN & OUT Mode Example 1

此程序查找两个值的最小值。此处,过程使用 IN 模式采用两个数字,并使用 OUT 参数返回它们的最小值。

This program finds the minimum of two values. Here, the procedure takes two numbers using the IN mode and returns their minimum using the OUT parameters.

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 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Minimum of (23, 45) : 23

PL/SQL procedure successfully completed.

IN & OUT Mode Example 2

此过程计算传递值值的平方。这个例子显示了我们如何可以使用相同参数来接受一个值,然后返回另一个结果。

This procedure computes the square of value of a passed value. This example shows how we can use the same parameter to accept a value and then return another result.

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 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Square of (23): 529

PL/SQL procedure successfully completed.

Methods for Passing Parameters

实际参数可以通过三种方式传递 -

Actual parameters can be passed in three ways −

  1. Positional notation

  2. Named notation

  3. Mixed notation

Positional Notation

在位置符号中,你可以调用过程为 -

In positional notation, you can call the procedure as −

findMin(a, b, c, d);

在位置符号中,第一个实际参数替换了第一个形式参数;第二个实际参数替换了第二个形式参数,以此类推。因此, a 替换为 x, b 替换为 y, c 替换为 z 替换 d 替换为 m

In positional notation, the first actual parameter is substituted for the first formal parameter; the second actual parameter is substituted for the second formal parameter, and so on. So, a is substituted for x, b is substituted for y, c is substituted for z and d is substituted for m.

Named Notation

在已命名符号中,实际参数与形式参数使用 arrow symbol ( ⇒ ) 关联。过程调用将像以下示例 -

In named notation, the actual parameter is associated with the formal parameter using the arrow symbol ( ⇒ ). The procedure call will be like the following −

findMin(x => a, y => b, z => c, m => d);

Mixed Notation

在混合符号中,你可以在过程调用中混合这两种符号;但位置符号应先于已命名符号。

In mixed notation, you can mix both notations in procedure call; however, the positional notation should precede the named notation.

以下调用是合法的 -

The following call is legal −

findMin(a, b, c, m => d);

然而,这是不合法的:

However, this is not legal:

findMin(x => a, b, c, d);

PL/SQL - Functions

在本章中,我们将讨论 PL/SQL 中的函数。函数与过程相同,只是函数会返回值。因此,前一章的所有讨论也适用于函数。

In this chapter, we will discuss the functions in PL/SQL. A function is same as a procedure except that it returns a value. Therefore, all the discussions of the previous chapter are true for functions too.

Creating a Function

使用 CREATE FUNCTION 语句创建独立函数。 CREATE OR REPLACE PROCEDURE 语句的简化语法如下:

A standalone function is created using the CREATE FUNCTION statement. The simplified syntax for the CREATE OR REPLACE PROCEDURE statement is as follows −

CREATE [OR REPLACE] FUNCTION function_name
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
RETURN return_datatype
{IS | AS}
BEGIN
   < function_body >
END [function_name];

其中,

Where,

  1. function-name specifies the name of the function.

  2. [OR REPLACE] option allows the modification of an existing function.

  3. The optional parameter list contains name, mode and types of the parameters. IN represents the value that will be passed from outside and OUT represents the parameter that will be used to return a value outside of the procedure.

  4. The function must contain a return statement.

  5. The RETURN clause specifies the data type you are going to return from the function.

  6. function-body contains the executable part.

  7. The AS keyword is used instead of the IS keyword for creating a standalone function.

Example

以下示例说明如何创建和调用独立函数。此函数返回 customers 表中 CUSTOMER 的总数。

The following example illustrates how to create and call a standalone function. This function returns the total number of CUSTOMERS in the customers table.

我们将使用我们创建在 PL/SQL Variables 一章中的 CUSTOMERS 表 −

We will use the CUSTOMERS table, which we had created in the PL/SQL Variables chapter −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
CREATE OR REPLACE FUNCTION totalCustomers
RETURN number IS
   total number(2) := 0;
BEGIN
   SELECT count(*) into total
   FROM customers;

   RETURN total;
END;
/

当使用 SQL 提示执行以上代码时,它将会生成以下结果 −

When the above code is executed using the SQL prompt, it will produce the following result −

Function created.

Calling a Function

在创建函数时,你需要提供函数将要完成的功能的定义。要使用函数,你必须调用此函数执行已定义的任务。当程序调用函数时,对此被调用函数实施程序控制。

While creating a function, you give a definition of what the function has to do. To use a function, you will have to call that function to perform the defined task. When a program calls a function, the program control is transferred to the called function.

一个被调用的函数执行定义的任务,当它的返回语句执行或 last end statement 达到时,它将程序控制权返回给主程序。

A called function performs the defined task and when its return statement is executed or when the last end statement is reached, it returns the program control back to the main program.

要调用函数,你只需传回所需参数和函数名字,如果函数返回一个值,那么你便可以储存返回的值。下列程序从匿名代码组调用了函数 totalCustomers

To call a function, you simply need to pass the required parameters along with the function name and if the function returns a value, then you can store the returned value. Following program calls the function totalCustomers from an anonymous block −

DECLARE
   c number(2);
BEGIN
   c := totalCustomers();
   dbms_output.put_line('Total no. of Customers: ' || c);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Total no. of Customers: 6

PL/SQL procedure successfully completed.

Example

以下的例子显示如何用 PL/SQL 函数宣布、定义和启动一个简单的 PL/SQL 函数,它能计算并返回两个值中的最大值。

The following example demonstrates Declaring, Defining, and Invoking a Simple PL/SQL Function that computes and returns the maximum of two values.

DECLARE
   a number;
   b number;
   c number;
FUNCTION findMax(x IN number, y IN number)
RETURN number
IS
    z number;
BEGIN
   IF x > y THEN
      z:= x;
   ELSE
      Z:= y;
   END IF;
   RETURN z;
END;
BEGIN
   a:= 23;
   b:= 45;
   c := findMax(a, b);
   dbms_output.put_line(' Maximum of (23,45): ' || c);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Maximum of (23,45): 45

PL/SQL procedure successfully completed.

PL/SQL Recursive Functions

我们已经看到,一个程序或子程序可能会调用另一个子程序。当一个子程序调用它自己,它称之为递归调用并且此过程称为 recursion

We have seen that a program or subprogram may call another subprogram. When a subprogram calls itself, it is referred to as a recursive call and the process is known as recursion.

为了说明这个概念,让我们计算一个数字的阶乘。一个数字 n 的阶乘被定义为 −

To illustrate the concept, let us calculate the factorial of a number. Factorial of a number n is defined as −

n! = n*(n-1)!
   = n*(n-1)*(n-2)!
      ...
   = n*(n-1)*(n-2)*(n-3)... 1

以下的程序通过递归地调用它自己来计算一个给定数字的阶乘 −

The following program calculates the factorial of a given number by calling itself recursively −

DECLARE
   num number;
   factorial number;

FUNCTION fact(x number)
RETURN number
IS
   f number;
BEGIN
   IF x=0 THEN
      f := 1;
   ELSE
      f := x * fact(x-1);
   END IF;
RETURN f;
END;

BEGIN
   num:= 6;
   factorial := fact(num);
   dbms_output.put_line(' Factorial '|| num || ' is ' || factorial);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Factorial 6 is 720

PL/SQL procedure successfully completed.

PL/SQL - Cursors

在本章中,我们将讨论 PL/SQL 中的游标。Oracle 创建一个名为上下文的内存区域以处理 SQL 语句,该上下文中包含处理该语句所需的所有信息;例如,已处理的行数等。

In this chapter, we will discuss the cursors in PL/SQL. Oracle creates a memory area, known as the context area, for processing an SQL statement, which contains all the information needed for processing the statement; for example, the number of rows processed, etc.

cursor 是此上下文区域的一个指针。PL/SQL 通过游标控制上下文区域。游标保存 SQL 语句返回的行(一个或多个)。游标保存的行集称为 active set

A cursor is a pointer to this context area. PL/SQL controls the context area through a cursor. A cursor holds the rows (one or more) returned by a SQL statement. The set of rows the cursor holds is referred to as the active set.

您可以为游标命名,以便在程序中引用它来获取和处理 SQL 语句返回的行,每次一行。有两种类型的游标:

You can name a cursor so that it could be referred to in a program to fetch and process the rows returned by the SQL statement, one at a time. There are two types of cursors −

  1. Implicit cursors

  2. Explicit cursors

Implicit Cursors

当为语句没有显式游标时,在执行 SQL 语句时,Oracle 始终自动创建隐式游标。程序员无法控制隐式游标及其信息。

Implicit cursors are automatically created by Oracle whenever an SQL statement is executed, when there is no explicit cursor for the statement. Programmers cannot control the implicit cursors and the information in it.

每当发出 DML 语句(INSERT、UPDATE 和 DELETE)时,都会有一个隐式游标与该语句相关联。对于 INSERT 操作,游标保存需要插入的数据。对于 UPDATE 和 DELETE 操作,游标标识将受到影响的行。

Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit cursor is associated with this statement. For INSERT operations, the cursor holds the data that needs to be inserted. For UPDATE and DELETE operations, the cursor identifies the rows that would be affected.

在 PL/SQL 中,您可以将最近的隐式游标称为 SQL cursor ,它始终具有 %FOUND, %ISOPEN, %NOTFOUND%ROWCOUNT 等属性。SQL 游标有 %BULK_ROWCOUNT%BULK_EXCEPTIONS 等附加属性,设计用于与 FORALL 语句一起使用。下表提供了最常用属性的说明−

In PL/SQL, you can refer to the most recent implicit cursor as the SQL cursor, which always has attributes such as %FOUND, %ISOPEN, %NOTFOUND, and %ROWCOUNT. The SQL cursor has additional attributes, %BULK_ROWCOUNT and %BULK_EXCEPTIONS, designed for use with the FORALL statement. The following table provides the description of the most used attributes −

S.No

Attribute & Description

1

%FOUND Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or more rows or a SELECT INTO statement returned one or more rows. Otherwise, it returns FALSE.

2

%NOTFOUND The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it returns FALSE.

3

%ISOPEN Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor automatically after executing its associated SQL statement.

4

%ROWCOUNT Returns the number of rows affected by an INSERT, UPDATE, or DELETE statement, or returned by a SELECT INTO statement.

任何 SQL 游标属性将被访问为 sql%attribute_name ,如下例所示。

Any SQL cursor attribute will be accessed as sql%attribute_name as shown below in the example.

Example

我们将使用我们在前几章创建和使用的 CUSTOMERS 表。

We will be using the CUSTOMERS table we had created and used in the previous chapters.

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+

以下程序将更新该表,并将每个客户的工资增加 500,并使用 SQL%ROWCOUNT 属性来确定受影响的行数−

The following program will update the table and increase the salary of each customer by 500 and use the SQL%ROWCOUNT attribute to determine the number of rows affected −

DECLARE
   total_rows number(2);
BEGIN
   UPDATE customers
   SET salary = salary + 500;
   IF sql%notfound THEN
      dbms_output.put_line('no customers selected');
   ELSIF sql%found THEN
      total_rows := sql%rowcount;
      dbms_output.put_line( total_rows || ' customers selected ');
   END IF;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

6 customers selected

PL/SQL procedure successfully completed.

如果您查看 customers 表中的记录,您会发现这些行已更新−

If you check the records in customers table, you will find that the rows have been updated −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2500.00 |
|  2 | Khilan   |  25 | Delhi     |  2000.00 |
|  3 | kaushik  |  23 | Kota      |  2500.00 |
|  4 | Chaitali |  25 | Mumbai    |  7000.00 |
|  5 | Hardik   |  27 | Bhopal    |  9000.00 |
|  6 | Komal    |  22 | MP        |  5000.00 |
+----+----------+-----+-----------+----------+

Explicit Cursors

显式游标是程序员定义的游标,用于对 context area 获得更多控制。应在 PL/SQL Block 的声明部分中定义显式游标。它创建在返回多行的 SELECT 语句上。

Explicit cursors are programmer-defined cursors for gaining more control over the context area. An explicit cursor should be defined in the declaration section of the PL/SQL Block. It is created on a SELECT Statement which returns more than one row.

创建显式游标的语法如下−

The syntax for creating an explicit cursor is −

CURSOR cursor_name IS select_statement;

使用显式游标包括以下步骤−

Working with an explicit cursor includes the following steps −

  1. Declaring the cursor for initializing the memory

  2. Opening the cursor for allocating the memory

  3. Fetching the cursor for retrieving the data

  4. Closing the cursor to release the allocated memory

Declaring the Cursor

声明游标使用名称和关联的 SELECT 语句定义游标。例如−

Declaring the cursor defines the cursor with a name and the associated SELECT statement. For example −

CURSOR c_customers IS
   SELECT id, name, address FROM customers;

Opening the Cursor

打开游标为游标分配内存,并使其准备好从 SQL 语句中检索返回的行。例如,我们将打开上面定义的游标,如下所示−

Opening the cursor allocates the memory for the cursor and makes it ready for fetching the rows returned by the SQL statement into it. For example, we will open the above defined cursor as follows −

OPEN c_customers;

Fetching the Cursor

获取游标包括一次访问一行。例如,我们将从已打开的游标获取行,如下所示 -

Fetching the cursor involves accessing one row at a time. For example, we will fetch rows from the above-opened cursor as follows −

FETCH c_customers INTO c_id, c_name, c_addr;

Closing the Cursor

关闭游标意味着释放分配的内存。例如,我们将关闭已打开的游标,如下所示 -

Closing the cursor means releasing the allocated memory. For example, we will close the above-opened cursor as follows −

CLOSE c_customers;

Example

以下是说明显式游标概念的完整示例;

Following is a complete example to illustrate the concepts of explicit cursors &minua;

DECLARE
   c_id customers.id%type;
   c_name customer.name%type;
   c_addr customers.address%type;
   CURSOR c_customers is
      SELECT id, name, address FROM customers;
BEGIN
   OPEN c_customers;
   LOOP
   FETCH c_customers into c_id, c_name, c_addr;
      EXIT WHEN c_customers%notfound;
      dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
   END LOOP;
   CLOSE c_customers;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

1 Ramesh Ahmedabad
2 Khilan Delhi
3 kaushik Kota
4 Chaitali Mumbai
5 Hardik Bhopal
6 Komal MP

PL/SQL procedure successfully completed.

PL/SQL - Records

在本章中,我们将讨论 PL/SQL 中的记录。 record 是可以容纳不同种类数据项目的数据结构。记录由不同的字段组成,类似于数据库表中的行。

In this chapter, we will discuss Records in PL/SQL. A record is a data structure that can hold data items of different kinds. Records consist of different fields, similar to a row of a database table.

例如,您希望跟踪库中的书籍。您可能想要跟踪每本书的以下属性,例如书名、作者、主题、书本编号。包含各个项目字段的记录可以将书本作为一个逻辑单元进行处理,并允许您更好地组织和呈现其信息。

For example, you want to keep track of your books in a library. You might want to track the following attributes about each book, such as Title, Author, Subject, Book ID. A record containing a field for each of these items allows treating a BOOK as a logical unit and allows you to organize and represent its information in a better way.

PL/SQL 可以处理以下类型的记录:

PL/SQL can handle the following types of records −

  1. Table-based

  2. Cursor-based records

  3. User-defined records

Table-Based Records

%ROWTYPE 属性使编程人员可以创建 table-basedcursorbased 记录。

The %ROWTYPE attribute enables a programmer to create table-based and cursorbased records.

以下示例说明了 table-based 记录的概念。我们将使用上几章中创建和使用的 CUSTOMERS 表:

The following example illustrates the concept of table-based records. We will be using the CUSTOMERS table we had created and used in the previous chapters −

DECLARE
   customer_rec customers%rowtype;
BEGIN
   SELECT * into customer_rec
   FROM customers
   WHERE id = 5;
   dbms_output.put_line('Customer ID: ' || customer_rec.id);
   dbms_output.put_line('Customer Name: ' || customer_rec.name);
   dbms_output.put_line('Customer Address: ' || customer_rec.address);
   dbms_output.put_line('Customer Salary: ' || customer_rec.salary);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Customer ID: 5
Customer Name: Hardik
Customer Address: Bhopal
Customer Salary: 9000

PL/SQL procedure successfully completed.

Cursor-Based Records

以下示例说明了 cursor-based 记录的概念。我们将使用上几章中创建和使用的 CUSTOMERS 表:

The following example illustrates the concept of cursor-based records. We will be using the CUSTOMERS table we had created and used in the previous chapters −

DECLARE
   CURSOR customer_cur is
      SELECT id, name, address
      FROM customers;
   customer_rec customer_cur%rowtype;
BEGIN
   OPEN customer_cur;
   LOOP
      FETCH customer_cur into customer_rec;
      EXIT WHEN customer_cur%notfound;
      DBMS_OUTPUT.put_line(customer_rec.id || ' ' || customer_rec.name);
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

1 Ramesh
2 Khilan
3 kaushik
4 Chaitali
5 Hardik
6 Komal

PL/SQL procedure successfully completed.

User-Defined Records

PL/SQL 提供了一个用户定义的记录类型,允许您定义不同的记录结构。这些记录由不同的字段组成。假设您希望跟踪库中的书籍。您可能想要跟踪每本书的以下属性:

PL/SQL provides a user-defined record type that allows you to define the different record structures. These records consist of different fields. Suppose you want to keep track of your books in a library. You might want to track the following attributes about each book −

  1. Title

  2. Author

  3. Subject

  4. Book ID

Defining a Record

记录类型定义为:

The record type is defined as −

TYPE
type_name IS RECORD
  ( field_name1  datatype1  [NOT NULL]  [:= DEFAULT EXPRESSION],
   field_name2   datatype2   [NOT NULL]  [:= DEFAULT EXPRESSION],
   ...
   field_nameN  datatypeN  [NOT NULL]  [:= DEFAULT EXPRESSION);
record-name  type_name;

Book 记录以以下方式声明:

The Book record is declared in the following way −

DECLARE
TYPE books IS RECORD
(title  varchar(50),
   author  varchar(50),
   subject varchar(100),
   book_id   number);
book1 books;
book2 books;

Accessing Fields

要访问记录的任意字段,我们使用点 (.) 运算符。成员访问运算符被编码为记录变量名和我们希望访问的字段之间的句点。下面是一个解释记录用法的示例:

To access any field of a record, we use the dot (.) operator. The member access operator is coded as a period between the record variable name and the field that we wish to access. Following is an example to explain the usage of record −

DECLARE
   type books is record
      (title varchar(50),
      author varchar(50),
      subject varchar(100),
      book_id number);
   book1 books;
   book2 books;
BEGIN
   -- Book 1 specification
   book1.title  := 'C Programming';
   book1.author := 'Nuha Ali ';
   book1.subject := 'C Programming Tutorial';
   book1.book_id := 6495407;
   -- Book 2 specification
   book2.title := 'Telecom Billing';
   book2.author := 'Zara Ali';
   book2.subject := 'Telecom Billing Tutorial';
   book2.book_id := 6495700;

  -- Print book 1 record
   dbms_output.put_line('Book 1 title : '|| book1.title);
   dbms_output.put_line('Book 1 author : '|| book1.author);
   dbms_output.put_line('Book 1 subject : '|| book1.subject);
   dbms_output.put_line('Book 1 book_id : ' || book1.book_id);

   -- Print book 2 record
   dbms_output.put_line('Book 2 title : '|| book2.title);
   dbms_output.put_line('Book 2 author : '|| book2.author);
   dbms_output.put_line('Book 2 subject : '|| book2.subject);
   dbms_output.put_line('Book 2 book_id : '|| book2.book_id);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

PL/SQL procedure successfully completed.

Records as Subprogram Parameters

您可以像传递任何其他变量一样将记录作为子程序参数进行传递。您还可以像在上述示例中访问记录字段一样访问记录字段:

You can pass a record as a subprogram parameter just as you pass any other variable. You can also access the record fields in the same way as you accessed in the above example −

DECLARE
   type books is record
      (title  varchar(50),
      author  varchar(50),
      subject varchar(100),
      book_id   number);
   book1 books;
   book2 books;
PROCEDURE printbook (book books) IS
BEGIN
   dbms_output.put_line ('Book  title :  ' || book.title);
   dbms_output.put_line('Book  author : ' || book.author);
   dbms_output.put_line( 'Book  subject : ' || book.subject);
   dbms_output.put_line( 'Book book_id : ' || book.book_id);
END;

BEGIN
   -- Book 1 specification
   book1.title  := 'C Programming';
   book1.author := 'Nuha Ali ';
   book1.subject := 'C Programming Tutorial';
   book1.book_id := 6495407;

   -- Book 2 specification
   book2.title := 'Telecom Billing';
   book2.author := 'Zara Ali';
   book2.subject := 'Telecom Billing Tutorial';
   book2.book_id := 6495700;

   -- Use procedure to print book info
   printbook(book1);
   printbook(book2);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Book  title : C Programming
Book  author : Nuha Ali
Book subject : C Programming Tutorial
Book  book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700

PL/SQL procedure successfully completed.

PL/SQL - Exceptions

在本教程中,我们将讨论 PL/SQL 中的 Exceptions。Exception 是程序执行过程中的错误条件。PL/SQL 支持程序员使用程序中的 EXCEPTION 块捕获此类条件,并针对错误条件采取适当措施。Exceptions 有两种:

In this chapter, we will discuss Exceptions in PL/SQL. An exception is an error condition during a program execution. PL/SQL supports programmers to catch such conditions using EXCEPTION block in the program and an appropriate action is taken against the error condition. There are two types of exceptions −

  1. System-defined exceptions

  2. User-defined exceptions

Syntax for Exception Handling

Exception 处理的常规语法如下。在这里,你可以列出尽可能多的异常进行处理。默认异常将使用 WHEN others THEN 进行处理:

The general syntax for exception handling is as follows. Here you can list down as many exceptions as you can handle. The default exception will be handled using WHEN others THEN

DECLARE
   <declarations section>
BEGIN
   <executable command(s)>
EXCEPTION
   <exception handling goes here >
   WHEN exception1 THEN
      exception1-handling-statements
   WHEN exception2  THEN
      exception2-handling-statements
   WHEN exception3 THEN
      exception3-handling-statements
   ........
   WHEN others THEN
      exception3-handling-statements
END;

Example

我们编写一个程序来说明概念。我们将使用在前面教程中创建和使用的 CUSTOMERS 表:

Let us write a code to illustrate the concept. We will be using the CUSTOMERS table we had created and used in the previous chapters −

DECLARE
   c_id customers.id%type := 8;
   c_name customerS.Name%type;
   c_addr customers.address%type;
BEGIN
   SELECT  name, address INTO  c_name, c_addr
   FROM customers
   WHERE id = c_id;
   DBMS_OUTPUT.PUT_LINE ('Name: '||  c_name);
   DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);

EXCEPTION
   WHEN no_data_found THEN
      dbms_output.put_line('No such customer!');
   WHEN others THEN
      dbms_output.put_line('Error!');
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

No such customer!

PL/SQL procedure successfully completed.

上述程序显示了给定 ID 的客户的姓名和地址。由于数据库中没有 ID 值为 8 的客户,因此程序引发了在 EXCEPTION block 中捕获的运行时异常 NO_DATA_FOUND

The above program displays the name and address of a customer whose ID is given. Since there is no customer with ID value 8 in our database, the program raises the run-time exception NO_DATA_FOUND, which is captured in the EXCEPTION block.

Raising Exceptions

当数据库服务器有任何内部错误时,它将自动引发异常,但是程序员也可以通过使用 RAISE 命令显式引发异常。以下是在引发异常的简单语法 -

Exceptions are raised by the database server automatically whenever there is any internal database error, but exceptions can be raised explicitly by the programmer by using the command RAISE. Following is the simple syntax for raising an exception −

DECLARE
   exception_name EXCEPTION;
BEGIN
   IF condition THEN
      RAISE exception_name;
   END IF;
EXCEPTION
   WHEN exception_name THEN
   statement;
END;

您可以在引发 Oracle 标准异常或任何用户定义的异常时使用上述语法。在下一部分中,我们将为您提供一个引发用户定义异常的示例。您可以以类似方式引发 Oracle 标准异常。

You can use the above syntax in raising the Oracle standard exception or any user-defined exception. In the next section, we will give you an example on raising a user-defined exception. You can raise the Oracle standard exceptions in a similar way.

User-defined Exceptions

PL/SQL 允许您根据程序的需要定义自己的异常。必须声明用户定义的异常,然后使用 RAISE 语句或 DBMS_STANDARD.RAISE_APPLICATION_ERROR 过程显式引发异常。

PL/SQL allows you to define your own exceptions according to the need of your program. A user-defined exception must be declared and then raised explicitly, using either a RAISE statement or the procedure DBMS_STANDARD.RAISE_APPLICATION_ERROR.

声明异常的语法是 -

The syntax for declaring an exception is −

DECLARE
   my-exception EXCEPTION;

Example

以下示例说明了该概念。此程序询问客户 ID,当用户输入无效 ID 时,将引发异常 invalid_id

The following example illustrates the concept. This program asks for a customer ID, when the user enters an invalid ID, the exception invalid_id is raised.

DECLARE
   c_id customers.id%type := &cc_id;
   c_name customerS.Name%type;
   c_addr customers.address%type;
   -- user defined exception
   ex_invalid_id  EXCEPTION;
BEGIN
   IF c_id <= 0 THEN
      RAISE ex_invalid_id;
   ELSE
      SELECT  name, address INTO  c_name, c_addr
      FROM customers
      WHERE id = c_id;
      DBMS_OUTPUT.PUT_LINE ('Name: '||  c_name);
      DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr);
   END IF;

EXCEPTION
   WHEN ex_invalid_id THEN
      dbms_output.put_line('ID must be greater than zero!');
   WHEN no_data_found THEN
      dbms_output.put_line('No such customer!');
   WHEN others THEN
      dbms_output.put_line('Error!');
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Enter value for cc_id: -6 (let's enter a value -6)
old  2: c_id customers.id%type := &cc_id;
new  2: c_id customers.id%type := -6;
ID must be greater than zero!

PL/SQL procedure successfully completed.

Pre-defined Exceptions

PL/SQL 提供了许多预定义的异常,当程序违反任何数据库规则时,这些异常将被执行。例如,当 SELECT INTO 语句不返回任何行时,将引发预定义的异常 NO_DATA_FOUND。下表列出了几个重要的预定义异常 -

PL/SQL provides many pre-defined exceptions, which are executed when any database rule is violated by a program. For example, the predefined exception NO_DATA_FOUND is raised when a SELECT INTO statement returns no rows. The following table lists few of the important pre-defined exceptions −

Exception

Oracle Error

SQLCODE

Description

ACCESS_INTO_NULL

06530

-6530

It is raised when a null object is automatically assigned a value.

CASE_NOT_FOUND

06592

-6592

It is raised when none of the choices in the WHEN clause of a CASE statement is selected, and there is no ELSE clause.

COLLECTION_IS_NULL

06531

-6531

It is raised when a program attempts to apply collection methods other than EXISTS to an uninitialized nested table or varray, or the program attempts to assign values to the elements of an uninitialized nested table or varray.

DUP_VAL_ON_INDEX

00001

-1

It is raised when duplicate values are attempted to be stored in a column with unique index.

INVALID_CURSOR

01001

-1001

It is raised when attempts are made to make a cursor operation that is not allowed, such as closing an unopened cursor.

INVALID_NUMBER

01722

-1722

It is raised when the conversion of a character string into a number fails because the string does not represent a valid number.

LOGIN_DENIED

01017

-1017

It is raised when a program attempts to log on to the database with an invalid username or password.

NO_DATA_FOUND

01403

+100

It is raised when a SELECT INTO statement returns no rows.

NOT_LOGGED_ON

01012

-1012

It is raised when a database call is issued without being connected to the database.

PROGRAM_ERROR

06501

-6501

It is raised when PL/SQL has an internal problem.

ROWTYPE_MISMATCH

06504

-6504

It is raised when a cursor fetches value in a variable having incompatible data type.

SELF_IS_NULL

30625

-30625

It is raised when a member method is invoked, but the instance of the object type was not initialized.

STORAGE_ERROR

06500

-6500

It is raised when PL/SQL ran out of memory or memory was corrupted.

TOO_MANY_ROWS

01422

-1422

It is raised when a SELECT INTO statement returns more than one row.

VALUE_ERROR

06502

-6502

It is raised when an arithmetic, conversion, truncation, or sizeconstraint error occurs.

ZERO_DIVIDE

01476

1476

It is raised when an attempt is made to divide a number by zero.

PL/SQL - Triggers

在本章中,我们将讨论 PL/SQL 中的触发器。触发器是存储程序,当某些事件发生时会自动执行或触发。触发器事实上是为了响应以下任何事件而编写的 −

In this chapter, we will discuss Triggers in PL/SQL. Triggers are stored programs, which are automatically executed or fired when some events occur. Triggers are, in fact, written to be executed in response to any of the following events −

  1. A database manipulation (DML) statement (DELETE, INSERT, or UPDATE)

  2. A database definition (DDL) statement (CREATE, ALTER, or DROP).

  3. A database operation (SERVERERROR, LOGON, LOGOFF, STARTUP, or SHUTDOWN).

可以在相关联的表、视图、模式或数据库上定义触发器。

Triggers can be defined on the table, view, schema, or database with which the event is associated.

Benefits of Triggers

可以针对以下目的编写触发器:

Triggers can be written for the following purposes −

  1. Generating some derived column values automatically

  2. Enforcing referential integrity

  3. Event logging and storing information on table access

  4. Auditing

  5. Synchronous replication of tables

  6. Imposing security authorizations

  7. Preventing invalid transactions

Creating Triggers

  • 创建触发器的语法为:

The syntax for creating a trigger is −

CREATE [OR REPLACE ] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF }
{INSERT [OR] | UPDATE [OR] | DELETE}
[OF col_name]
ON table_name
[REFERENCING OLD AS o NEW AS n]
[FOR EACH ROW]
WHEN (condition)
DECLARE
   Declaration-statements
BEGIN
   Executable-statements
EXCEPTION
   Exception-handling-statements
END;

其中,

Where,

  1. CREATE [OR REPLACE] TRIGGER trigger_name − Creates or replaces an existing trigger with the trigger_name.

  2. {BEFORE | AFTER | INSTEAD OF} − This specifies when the trigger will be executed. The INSTEAD OF clause is used for creating trigger on a view.

  3. {INSERT [OR] | UPDATE [OR] | DELETE} − This specifies the DML operation.

  4. [OF col_name] − This specifies the column name that will be updated.

  5. [ON table_name] − This specifies the name of the table associated with the trigger.

  6. [REFERENCING OLD AS o NEW AS n] − This allows you to refer new and old values for various DML statements, such as INSERT, UPDATE, and DELETE.

  7. [FOR EACH ROW] − This specifies a row-level trigger, i.e., the trigger will be executed for each row being affected. Otherwise the trigger will execute just once when the SQL statement is executed, which is called a table level trigger.

  8. WHEN (condition) − This provides a condition for rows for which the trigger would fire. This clause is valid only for row-level triggers.

Example

首先,将使用在之前的章节中创建并使用的 CUSTOMERS 表:

To start with, we will be using the CUSTOMERS table we had created and used in the previous chapters −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+

以下程序为 customers 表创建了一个 row-level 触发器,该触发器将在 CUSTOMERS 表上执行的 INSERT、UPDATE 或 DELETE 操作触发。此触发器将显示新旧值之间的薪水差异:

The following program creates a row-level trigger for the customers table that would fire for INSERT or UPDATE or DELETE operations performed on the CUSTOMERS table. This trigger will display the salary difference between the old values and new values −

CREATE OR REPLACE TRIGGER display_salary_changes
BEFORE DELETE OR INSERT OR UPDATE ON customers
FOR EACH ROW
WHEN (NEW.ID > 0)
DECLARE
   sal_diff number;
BEGIN
   sal_diff := :NEW.salary  - :OLD.salary;
   dbms_output.put_line('Old salary: ' || :OLD.salary);
   dbms_output.put_line('New salary: ' || :NEW.salary);
   dbms_output.put_line('Salary difference: ' || sal_diff);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Trigger created.

这里需要考虑以下几点:

The following points need to be considered here −

  1. OLD and NEW references are not available for table-level triggers, rather you can use them for record-level triggers.

  2. If you want to query the table in the same trigger, then you should use the AFTER keyword, because triggers can query the table or change it again only after the initial changes are applied and the table is back in a consistent state.

  3. The above trigger has been written in such a way that it will fire before any DELETE or INSERT or UPDATE operation on the table, but you can write your trigger on a single or multiple operations, for example BEFORE DELETE, which will fire whenever a record will be deleted using the DELETE operation on the table.

Triggering a Trigger

让我们对 CUSTOMERS 表执行一些 DML 操作。这里有一个 INSERT 语句,它将在表中创建一个新记录:

Let us perform some DML operations on the CUSTOMERS table. Here is one INSERT statement, which will create a new record in the table −

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (7, 'Kriti', 22, 'HP', 7500.00 );

当在 CUSTOMERS 表中创建记录时,将触发上述创建触发器 display_salary_changes ,它将显示以下结果:

When a record is created in the CUSTOMERS table, the above create trigger, display_salary_changes will be fired and it will display the following result −

Old salary:
New salary: 7500
Salary difference:

由于这是一个新记录,旧工资不可用,以上结果显示为 null。现在让我们对 CUSTOMERS 表执行另一个 DML 操作。UPDATE 语句将更新表中一个现有的记录:

Because this is a new record, old salary is not available and the above result comes as null. Let us now perform one more DML operation on the CUSTOMERS table. The UPDATE statement will update an existing record in the table −

UPDATE customers
SET salary = salary + 500
WHERE id = 2;

当在 CUSTOMERS 表中更新记录时,将触发上述创建触发器 display_salary_changes ,它将显示以下结果:

When a record is updated in the CUSTOMERS table, the above create trigger, display_salary_changes will be fired and it will display the following result −

Old salary: 1500
New salary: 2000
Salary difference: 500

PL/SQL - Packages

在本章中,我们将讨论 PL/SQL 中的包。包是将具有逻辑关连性的 PL/SQL 类型、变量和子程序进行分组的模式对象。

In this chapter, we will discuss the Packages in PL/SQL. Packages are schema objects that groups logically related PL/SQL types, variables, and subprograms.

一个包会有两个强制性部分:

A package will have two mandatory parts −

  1. Package specification

  2. Package body or definition

Package Specification

规范是对包的界面。它只是 DECLARES 可以从包外部进行引用的类型、变量、常量、异常、游标和子程序。换句话说,它包含有关包内容的所有信息,但不包括子程序的代码。

The specification is the interface to the package. It just DECLARES the types, variables, constants, exceptions, cursors, and subprograms that can be referenced from outside the package. In other words, it contains all information about the content of the package, but excludes the code for the subprograms.

放在规范中的所有对象被称为 public 对象。未在包规范中但已在包正文中编码的任何子程序都被称为 private 对象。

All objects placed in the specification are called public objects. Any subprogram not in the package specification but coded in the package body is called a private object.

以下代码段显示了一个具有单个过程的包规范。你可以在包中定义许多全局变量,以及多个过程或函数。

The following code snippet shows a package specification having a single procedure. You can have many global variables defined and multiple procedures or functions inside a package.

CREATE PACKAGE cust_sal AS
   PROCEDURE find_sal(c_id customers.id%type);
END cust_sal;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Package created.

Package Body

包正文包含对包规范中声明的各种方法的代码,以及其他对包外部代码隐藏的私有声明。

The package body has the codes for various methods declared in the package specification and other private declarations, which are hidden from the code outside the package.

CREATE PACKAGE BODY 语句用于创建包正文。以下代码段显示了为上述所创建的 cust_sal 包的包正文声明。我假设我们已在数据库中创建 CUSTOMERS 表,如 PL/SQL - Variables 章所述。

The CREATE PACKAGE BODY Statement is used for creating the package body. The following code snippet shows the package body declaration for the cust_sal package created above. I assumed that we already have CUSTOMERS table created in our database as mentioned in the PL/SQL - Variables chapter.

CREATE OR REPLACE PACKAGE BODY cust_sal AS

   PROCEDURE find_sal(c_id customers.id%TYPE) IS
   c_sal customers.salary%TYPE;
   BEGIN
      SELECT salary INTO c_sal
      FROM customers
      WHERE id = c_id;
      dbms_output.put_line('Salary: '|| c_sal);
   END find_sal;
END cust_sal;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Package body created.

Using the Package Elements

包元素(变量、过程或函数)可使用以下语法进行访问:

The package elements (variables, procedures or functions) are accessed with the following syntax −

package_name.element_name;

考虑一下这一点,我们已在数据库架构中创建了上述包,以下程序使用 cust_sal 包的 find_sal 方法:

Consider, we already have created the above package in our database schema, the following program uses the find_sal method of the cust_sal package −

DECLARE
   code customers.id%type := &cc_id;
BEGIN
   cust_sal.find_sal(code);
END;
/

当在 SQL 提示符下执行上述代码时,它会提示输入客户 ID,并在输入 ID 时,它会显示相应的工资,如下所示:

When the above code is executed at the SQL prompt, it prompts to enter the customer ID and when you enter an ID, it displays the corresponding salary as follows −

Enter value for cc_id: 1
Salary: 3000

PL/SQL procedure successfully completed.

Example

以下程序提供了一个更完整的包。我们将使用存储在我们的数据库中的,具有以下记录的 CUSTOMERS 表:

The following program provides a more complete package. We will use the CUSTOMERS table stored in our database with the following records −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  3000.00 |
|  2 | Khilan   |  25 | Delhi     |  3000.00 |
|  3 | kaushik  |  23 | Kota      |  3000.00 |
|  4 | Chaitali |  25 | Mumbai    |  7500.00 |
|  5 | Hardik   |  27 | Bhopal    |  9500.00 |
|  6 | Komal    |  22 | MP        |  5500.00 |
+----+----------+-----+-----------+----------+

The Package Specification

CREATE OR REPLACE PACKAGE c_package AS
   -- Adds a customer
   PROCEDURE addCustomer(c_id   customers.id%type,
   c_name  customers.Name%type,
   c_age  customers.age%type,
   c_addr customers.address%type,
   c_sal  customers.salary%type);

   -- Removes a customer
   PROCEDURE delCustomer(c_id  customers.id%TYPE);
   --Lists all customers
   PROCEDURE listCustomer;

END c_package;
/

当在 SQL 提示符下执行上述代码时,它将创建上述包并显示以下结果:

When the above code is executed at the SQL prompt, it creates the above package and displays the following result −

Package created.

Creating the Package Body

CREATE OR REPLACE PACKAGE BODY c_package AS
   PROCEDURE addCustomer(c_id  customers.id%type,
      c_name customers.Name%type,
      c_age  customers.age%type,
      c_addr  customers.address%type,
      c_sal   customers.salary%type)
   IS
   BEGIN
      INSERT INTO customers (id,name,age,address,salary)
         VALUES(c_id, c_name, c_age, c_addr, c_sal);
   END addCustomer;

   PROCEDURE delCustomer(c_id   customers.id%type) IS
   BEGIN
      DELETE FROM customers
      WHERE id = c_id;
   END delCustomer;

   PROCEDURE listCustomer IS
   CURSOR c_customers is
      SELECT  name FROM customers;
   TYPE c_list is TABLE OF customers.Name%type;
   name_list c_list := c_list();
   counter integer :=0;
   BEGIN
      FOR n IN c_customers LOOP
      counter := counter +1;
      name_list.extend;
      name_list(counter) := n.name;
      dbms_output.put_line('Customer(' ||counter|| ')'||name_list(counter));
      END LOOP;
   END listCustomer;

END c_package;
/

上述示例使用了 nested table 。我们将在下一章中讨论嵌套表的概念。

The above example makes use of the nested table. We will discuss the concept of nested table in the next chapter.

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Package body created.

Using The Package

以下程序使用在软件包 c_package 中定义的 declared 和 defined 方法。

The following program uses the methods declared and defined in the package c_package.

DECLARE
   code customers.id%type:= 8;
BEGIN
   c_package.addcustomer(7, 'Rajnish', 25, 'Chennai', 3500);
   c_package.addcustomer(8, 'Subham', 32, 'Delhi', 7500);
   c_package.listcustomer;
   c_package.delcustomer(code);
   c_package.listcustomer;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish
Customer(8): Subham
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish

PL/SQL procedure successfully completed

PL/SQL - Collections

在本章中,我们将讨论 PL/SQL 的 Collection。Collection 是拥有相同数据类型的一组有序元素。每个元素都被一个代表其在 Collection 中位置的唯一下标标识。

In this chapter, we will discuss the Collections in PL/SQL. A collection is an ordered group of elements having the same data type. Each element is identified by a unique subscript that represents its position in the collection.

PL/SQL 提供了三种 Collection 类型 −

PL/SQL provides three collection types −

  1. Index-by tables or Associative array

  2. Nested table

  3. Variable-size array or Varray

Oracle 文档为每种 Collection 类型提供了以下特性 −

Oracle documentation provides the following characteristics for each type of collections −

Collection Type

Number of Elements

Subscript Type

Dense or Sparse

Where Created

Can Be Object Type Attribute

Associative array (or index-by table)

Unbounded

String or integer

Either

Only in PL/SQL block

No

Nested table

Unbounded

Integer

Starts dense, can become sparse

Either in PL/SQL block or at schema level

Yes

Variablesize array (Varray)

Bounded

Integer

Always dense

Either in PL/SQL block or at schema level

Yes

我们已经在第 'PL/SQL arrays' 章讨论过了 varray。在本章中,我们将讨论 PL/SQL 表。

We have already discussed varray in the chapter 'PL/SQL arrays'. In this chapter, we will discuss the PL/SQL tables.

两种类型的 PL/SQL 表,例如索引表和嵌套表有相同的结构,并且它们的行的访问是使用下标符号。不过,这两种类型的表在一点上存在差异;嵌套表可以被储存在数据库列中,而索引表不能。

Both types of PL/SQL tables, i.e., the index-by tables and the nested tables have the same structure and their rows are accessed using the subscript notation. However, these two types of tables differ in one aspect; the nested tables can be stored in a database column and the index-by tables cannot.

Index-By Table

index-by 表(也称为 associative array )是一组 key-value 对。每个键是唯一的,用于查找相应的值。键可以是整数或字符串。

An index-by table (also called an associative array) is a set of key-value pairs. Each key is unique and is used to locate the corresponding value. The key can be either an integer or a string.

使用以下语法创建索引表。在此,我们创建一个名为 table_nameindex-by 表,其键将为 subscript_type,关联值将为 element_type

An index-by table is created using the following syntax. Here, we are creating an index-by table named table_name, the keys of which will be of the subscript_type and associated values will be of the element_type

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY subscript_type;

table_name type_name;

Example

以下示例演示如何创建一个表来存储整数值以及姓名,稍后它会打印相同的姓名列表。

Following example shows how to create a table to store integer values along with names and later it prints the same list of names.

DECLARE
   TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20);
   salary_list salary;
   name   VARCHAR2(20);
BEGIN
   -- adding elements to the table
   salary_list('Rajnish') := 62000;
   salary_list('Minakshi') := 75000;
   salary_list('Martin') := 100000;
   salary_list('James') := 78000;

   -- printing the table
   name := salary_list.FIRST;
   WHILE name IS NOT null LOOP
      dbms_output.put_line
      ('Salary of ' || name || ' is ' || TO_CHAR(salary_list(name)));
      name := salary_list.NEXT(name);
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Salary of James is 78000
Salary of Martin is 100000
Salary of Minakshi is 75000
Salary of Rajnish is 62000

PL/SQL procedure successfully completed.

Example

索引表中的元素也可以是任何数据库表或任何数据库表字段的 %ROWTYPE 。以下示例说明了该概念。我们将使用存储在我们的数据库中的 CUSTOMERS 表为 −

Elements of an index-by table could also be a %ROWTYPE of any database table or %TYPE of any database table field. The following example illustrates the concept. We will use the CUSTOMERS table stored in our database as −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      select name from customers;

   TYPE c_list IS TABLE of customers.Name%type INDEX BY binary_integer;
   name_list c_list;
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list(counter) := n.name;
      dbms_output.put_line('Customer('||counter||'):'||name_lis t(counter));
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed

Nested Tables

nested table 很像一个具有任意数量元素的一维数组。但是,嵌套表在以下方面与数组不同 −

A nested table is like a one-dimensional array with an arbitrary number of elements. However, a nested table differs from an array in the following aspects −

  1. An array has a declared number of elements, but a nested table does not. The size of a nested table can increase dynamically.

  2. An array is always dense, i.e., it always has consecutive subscripts. A nested array is dense initially, but it can become sparse when elements are deleted from it.

嵌套表使用以下语法创建 −

A nested table is created using the following syntax −

TYPE type_name IS TABLE OF element_type [NOT NULL];

table_name type_name;

此声明类似于 index-by 表的声明,但没有 INDEX BY 子句。

This declaration is similar to the declaration of an index-by table, but there is no INDEX BY clause.

嵌套表可以存储在数据库列中。它还可以进一步用于简化 SQL 操作,在该操作中,将单列表与较大表联接。关联数组无法存储在数据库中。

A nested table can be stored in a database column. It can further be used for simplifying SQL operations where you join a single-column table with a larger table. An associative array cannot be stored in the database.

Example

以下示例说明了嵌套表的用法 −

The following examples illustrate the use of nested table −

DECLARE
   TYPE names_table IS TABLE OF VARCHAR2(10);
   TYPE grades IS TABLE OF INTEGER;
   names names_table;
   marks grades;
   total integer;
BEGIN
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
   marks:= grades(98, 97, 78, 87, 92);
   total := names.count;
   dbms_output.put_line('Total '|| total || ' Students');
   FOR i IN 1 .. total LOOP
      dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));
   end loop;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Total 5 Students
Student:Kavita, Marks:98
Student:Pritam, Marks:97
Student:Ayan, Marks:78
Student:Rishav, Marks:87
Student:Aziz, Marks:92

PL/SQL procedure successfully completed.

Example

nested table 的元素也可以是任何数据库表或任何数据库表字段 %TYPE 的 %ROWTYPE 。以下示例说明了该概念。我们将使用存储在我们的数据库中的 CUSTOMERS 表为 −

Elements of a nested table can also be a %ROWTYPE of any database table or %TYPE of any database table field. The following example illustrates the concept. We will use the CUSTOMERS table stored in our database as −

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      SELECT  name FROM customers;
   TYPE c_list IS TABLE of customerS.No.ame%type;
   name_list c_list := c_list();
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list.extend;
      name_list(counter)  := n.name;
      dbms_output.put_line('Customer('||counter||'):'||name_list(counter));
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed.

Collection Methods

PL/SQL 提供了内置收集方法,使收集更容易使用。下表列出了方法及其用途 −

PL/SQL provides the built-in collection methods that make collections easier to use. The following table lists the methods and their purpose −

S.No

Method Name & Purpose

1

EXISTS(n) Returns TRUE if the nth element in a collection exists; otherwise returns FALSE.

2

COUNT Returns the number of elements that a collection currently contains.

3

LIMIT Checks the maximum size of a collection.

4

FIRST Returns the first (smallest) index numbers in a collection that uses the integer subscripts.

5

LAST Returns the last (largest) index numbers in a collection that uses the integer subscripts.

6

PRIOR(n) Returns the index number that precedes index n in a collection.

7

NEXT(n) Returns the index number that succeeds index n.

8

EXTEND Appends one null element to a collection.

9

EXTEND(n) Appends n null elements to a collection.

10

EXTEND(n,i) Appends n copies of the ith element to a collection.

11

TRIM Removes one element from the end of a collection.

12

TRIM(n) Removes n elements from the end of a collection.

13

DELETE Removes all elements from a collection, setting COUNT to 0.

14

DELETE(n) Removes the nth element from an associative array with a numeric key or a nested table. If the associative array has a string key, the element corresponding to the key value is deleted. If n is null, DELETE(n) does nothing.

15

DELETE(m,n) Removes all elements in the range m..n from an associative array or nested table. If m is larger than n or if m or n is null, DELETE(m,n) does nothing.

Collection Exceptions

下表提供了集合异常及其引发的时间 −

The following table provides the collection exceptions and when they are raised −

Collection Exception

Raised in Situations

COLLECTION_IS_NULL

You try to operate on an atomically null collection.

NO_DATA_FOUND

A subscript designates an element that was deleted, or a nonexistent element of an associative array.

SUBSCRIPT_BEYOND_COUNT

A subscript exceeds the number of elements in a collection.

SUBSCRIPT_OUTSIDE_LIMIT

A subscript is outside the allowed range.

VALUE_ERROR

A subscript is null or not convertible to the key type. This exception might occur if the key is defined as a PLS_INTEGER range, and the subscript is outside this range.

PL/SQL - Transactions

在本章中,我们将讨论 PL/SQL 中的事务。数据库 transaction 是一个工作原子单元,可能由一个或多个相关的 SQL 语句构成。称为原子单元是因为构成事务的 SQL 语句所产生的数据库修改可以共同提交,即永久保存在数据库中或从数据库回滚(撤销)。

In this chapter, we will discuss the transactions in PL/SQL. A database transaction is an atomic unit of work that may consist of one or more related SQL statements. It is called atomic because the database modifications brought about by the SQL statements that constitute a transaction can collectively be either committed, i.e., made permanent to the database or rolled back (undone) from the database.

成功执行的 SQL 语句和提交的事务不同。即使 SQL 语句成功执行,但除非提交包含该语句的事务,否则可以回滚该语句并撤销该语句所做的所有更改。

A successfully executed SQL statement and a committed transaction are not same. Even if an SQL statement is executed successfully, unless the transaction containing the statement is committed, it can be rolled back and all changes made by the statement(s) can be undone.

Starting and Ending a Transaction

事务有 beginningend 。当发生以下事件之一时,事务开始:

A transaction has a beginning and an end. A transaction starts when one of the following events take place −

  1. The first SQL statement is performed after connecting to the database.

  2. At each new SQL statement issued after a transaction is completed.

当发生以下事件之一时,事务结束:

A transaction ends when one of the following events take place −

  1. A COMMIT or a ROLLBACK statement is issued.

  2. A DDL statement, such as CREATE TABLE statement, is issued; because in that case a COMMIT is automatically performed.

  3. A DCL statement, such as a GRANT statement, is issued; because in that case a COMMIT is automatically performed.

  4. User disconnects from the database.

  5. User exits from SQL*PLUS by issuing the EXIT command, a COMMIT is automatically performed.

  6. SQL*Plus terminates abnormally, a ROLLBACK is automatically performed.

  7. A DML statement fails; in that case a ROLLBACK is automatically performed for undoing that DML statement.

Committing a Transaction

通过发出 SQL 命令 COMMIT 使事务永久生效。COMMIT 命令的常规语法为:

A transaction is made permanent by issuing the SQL command COMMIT. The general syntax for the COMMIT command is −

COMMIT;

例如,

For example,

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (3, 'kaushik', 23, 'Kota', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (6, 'Komal', 22, 'MP', 4500.00 );

COMMIT;

Rolling Back Transactions

在不执行 COMMIT 的情况下对数据库所做的更改可以使用 ROLLBACK 命令撤销。

Changes made to the database without COMMIT could be undone using the ROLLBACK command.

ROLLBACK 命令的常规语法为:

The general syntax for the ROLLBACK command is −

ROLLBACK [TO SAVEPOINT < savepoint_name>];

当事务由于系统故障等前所未有的情况而中止时,从上次提交后整个事务都会自动回滚。如果不使用 savepoint ,则只需使用以下语句回滚所有更改:

When a transaction is aborted due to some unprecedented situation, like system failure, the entire transaction since a commit is automatically rolled back. If you are not using savepoint, then simply use the following statement to rollback all the changes −

ROLLBACK;

Savepoints

保存点是一种标记,有助于通过设置一些检查点将一个较长的事务拆分为较小的单元。通过在较长的事务中设置保存点,可以在需要时回滚到检查点。这是通过发出 SAVEPOINT 命令来完成的。

Savepoints are sort of markers that help in splitting a long transaction into smaller units by setting some checkpoints. By setting savepoints within a long transaction, you can roll back to a checkpoint if required. This is done by issuing the SAVEPOINT command.

SAVEPOINT 命令的一般语法是:

The general syntax for the SAVEPOINT command is −

SAVEPOINT < savepoint_name >;

例如

For example

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (7, 'Rajnish', 27, 'HP', 9500.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (8, 'Riddhi', 21, 'WB', 4500.00 );
SAVEPOINT sav1;

UPDATE CUSTOMERS
SET SALARY = SALARY + 1000;
ROLLBACK TO sav1;

UPDATE CUSTOMERS
SET SALARY = SALARY + 1000
WHERE ID = 7;
UPDATE CUSTOMERS
SET SALARY = SALARY + 1000
WHERE ID = 8;

COMMIT;

ROLLBACK TO sav1 − 此语句回滚至标记了保存点 sav1 的那一点的所有更改。

ROLLBACK TO sav1 − This statement rolls back all the changes up to the point, where you had marked savepoint sav1.

之后,您所做的更改将开始。

After that, the new changes that you make will start.

Automatic Transaction Control

要设置只要执行 COMMITINSERT, UPDATE 命令时,自动执行 DELETE ,您可以设置 AUTOCOMMIT 环境变量,如下所示:

To execute a COMMIT automatically whenever an INSERT, UPDATE or DELETE command is executed, you can set the AUTOCOMMIT environment variable as −

SET AUTOCOMMIT ON;

您可以使用以下命令关闭自动提交模式:

You can turn-off the auto commit mode using the following command −

SET AUTOCOMMIT OFF;

PL/SQL - Date & Time

在本章里,我们将讨论 PL/SQL 中的日期和时间。在 PL/SQL 中有两类日期和时间相关数据类型 -

In this chapter, we will discuss the Date and Time in PL/SQL. There are two classes of date and time related data types in PL/SQL −

  1. Datetime data types

  2. Interval data types

Datetime 数据类型是 -

The Datetime data types are −

  1. DATE

  2. TIMESTAMP

  3. TIMESTAMP WITH TIME ZONE

  4. TIMESTAMP WITH LOCAL TIME ZONE

区间数据类型包括 −

The Interval data types are −

  1. INTERVAL YEAR TO MONTH

  2. INTERVAL DAY TO SECOND

Field Values for Datetime and Interval Data Types

datetimeinterval 数据类型均由 fields 组成。这些字段的值决定了数据类型的值。下表列出了日期时间和区间的字段及其可能的值。

Both datetime and interval data types consist of fields. The values of these fields determine the value of the data type. The following table lists the fields and their possible values for datetimes and intervals.

Field Name

Valid Datetime Values

Valid Interval Values

YEAR

-4712 to 9999 (excluding year 0)

Any nonzero integer

MONTH

01 to 12

0 to 11

DAY

01 to 31 (limited by the values of MONTH and YEAR, according to the rules of the calendar for the locale)

Any nonzero integer

HOUR

00 to 23

0 to 23

MINUTE

00 to 59

0 to 59

SECOND

00 to 59.9(n), where 9(n) is the precision of time fractional seconds The 9(n) portion is not applicable for DATE.

0 to 59.9(n), where 9(n) is the precision of interval fractional seconds

TIMEZONE_HOUR

-12 to 14 (range accommodates daylight savings time changes) Not applicable for DATE or TIMESTAMP.

Not applicable

TIMEZONE_MINUTE

00 to 59 Not applicable for DATE or TIMESTAMP.

Not applicable

TIMEZONE_REGION

Not applicable for DATE or TIMESTAMP.

Not applicable

TIMEZONE_ABBR

Not applicable for DATE or TIMESTAMP.

Not applicable

The Datetime Data Types and Functions

以下是日期时间数据类型 −

Following are the Datetime data types −

DATE

它在字符和数字数据类型中都存储日期和时间信息。它由世纪、年份、月份、日期、小时、分钟和秒的信息组成。它指定为 −

It stores date and time information in both character and number datatypes. It is made of information on century, year, month, date, hour, minute, and second. It is specified as −

TIMESTAMP

它是 DATE 数据类型的扩展。它存储 DATE 数据类型的年、月和日,以及小时、分钟和秒值。它适用于存储精确的时间值。

It is an extension of the DATE data type. It stores the year, month, and day of the DATE datatype, along with hour, minute, and second values. It is useful for storing precise time values.

TIMESTAMP WITH TIME ZONE

它是 TIMESTAMP 的变体,在其值中包含时区区域名称或时区偏移。时区偏移是以小时和分钟表示的本地时间与 UTC 时间之间的差异。这种数据类型适用于跨地理区域收集和评估日期信息。

It is a variant of TIMESTAMP that includes a time zone region name or a time zone offset in its value. The time zone offset is the difference (in hours and minutes) between local time and UTC. This data type is useful for collecting and evaluating date information across geographic regions.

TIMESTAMP WITH LOCAL TIME ZONE

它是 TIMESTAMP 的另一个变体,在其值中包含一个时区偏移。

It is another variant of TIMESTAMP that includes a time zone offset in its value.

下表提供了日期时间函数(其中 x 具有日期时间值)−

Following table provides the Datetime functions (where, x has the datetime value) −

S.No

Function Name & Description

1

ADD_MONTHS(x, y); Adds y months to x.

2

LAST_DAY(x); Returns the last day of the month.

3

MONTHS_BETWEEN(x, y); Returns the number of months between x and y.

4

NEXT_DAY(x, day); Returns the datetime of the next day after x.

5

NEW_TIME; Returns the time/day value from a time zone specified by the user.

6

ROUND(x [, unit]); Rounds x.

7

SYSDATE(); Returns the current datetime.

8

TRUNC(x [, unit]); Truncates x.

时间戳函数(其中 x 具有时间戳值)−

Timestamp functions (where, x has a timestamp value) −

S.No

Function Name & Description

1

CURRENT_TIMESTAMP(); Returns a TIMESTAMP WITH TIME ZONE containing the current session time along with the session time zone.

2

*EXTRACT({ YEAR

MONTH

DAY

HOUR

MINUTE

SECOND }

{ TIMEZONE_HOUR

TIMEZONE_MINUTE }

{ TIMEZONE_REGION

} TIMEZONE_ABBR ) FROM x)* Extracts and returns a year, month, day, hour, minute, second, or time zone from x.

3

FROM_TZ(x, time_zone); Converts the TIMESTAMP x and the time zone specified by time_zone to a TIMESTAMP WITH TIMEZONE.

4

LOCALTIMESTAMP(); Returns a TIMESTAMP containing the local time in the session time zone.

5

SYSTIMESTAMP(); Returns a TIMESTAMP WITH TIME ZONE containing the current database time along with the database time zone.

6

SYS_EXTRACT_UTC(x); Converts the TIMESTAMP WITH TIMEZONE x to a TIMESTAMP containing the date and time in UTC.

7

TO_TIMESTAMP(x, [format]); Converts the string x to a TIMESTAMP.

8

Examples

以下代码片段展示了上述函数的使用方法:

The following code snippets illustrate the use of the above functions −

Example 1

Example 1

SELECT SYSDATE FROM DUAL;

Output

Output

08/31/2012 5:25:34 PM

Example 2

Example 2

SELECT TO_CHAR(CURRENT_DATE, 'DD-MM-YYYY HH:MI:SS') FROM DUAL;

Output

Output

31-08-2012 05:26:14

Example 3

Example 3

SELECT ADD_MONTHS(SYSDATE, 5) FROM DUAL;

Output

Output

01/31/2013 5:26:31 PM

Example 4

Example 4

SELECT LOCALTIMESTAMP FROM DUAL;

Output

Output

8/31/2012 5:26:55.347000 PM

The Interval Data Types and Functions

以下是 Interval 数据类型:

Following are the Interval data types −

  1. IINTERVAL YEAR TO MONTH − It stores a period of time using the YEAR and MONTH datetime fields.

  2. INTERVAL DAY TO SECOND − It stores a period of time in terms of days, hours, minutes, and seconds.

Interval Functions

S.No

Function Name & Description

1

NUMTODSINTERVAL(x, interval_unit); Converts the number x to an INTERVAL DAY TO SECOND.

2

NUMTOYMINTERVAL(x, interval_unit); Converts the number x to an INTERVAL YEAR TO MONTH.

3

TO_DSINTERVAL(x); Converts the string x to an INTERVAL DAY TO SECOND.

4

TO_YMINTERVAL(x); Converts the string x to an INTERVAL YEAR TO MONTH.

PL/SQL - DBMS Output

在本章中,我们将讨论 PL/SQL 中的 DBMS 输出。 DBMS_OUTPUT 是一个内置包,用于显示输出、调试信息,以及从 PL/SQL 块、子程序、包和触发器发送消息。我们在整个教程中都已使用过此包。

In this chapter, we will discuss the DBMS Output in PL/SQL. The DBMS_OUTPUT is a built-in package that enables you to display output, debugging information, and send messages from PL/SQL blocks, subprograms, packages, and triggers. We have already used this package throughout our tutorial.

我们一起来看一下一个小代码段,它将显示数据库中的所有用户表。尝试在数据库中运行它,以列出所有表名:

Let us look at a small code snippet that will display all the user tables in the database. Try it in your database to list down all the table names −

BEGIN
   dbms_output.put_line  (user || ' Tables in the database:');
   FOR t IN (SELECT table_name FROM user_tables)
   LOOP
      dbms_output.put_line(t.table_name);
   END LOOP;
END;
/

DBMS_OUTPUT Subprograms

DBMS_OUTPUT 包具有以下子程序:

The DBMS_OUTPUT package has the following subprograms −

S.No

Subprogram & Purpose

1

DBMS_OUTPUT.DISABLE; Disables message output.

2

DBMS_OUTPUT.ENABLE(buffer_size IN INTEGER DEFAULT 20000); Enables message output. A NULL value of buffer_size represents unlimited buffer size.

3

DBMS_OUTPUT.GET_LINE (line OUT VARCHAR2, status OUT INTEGER); Retrieves a single line of buffered information.

4

DBMS_OUTPUT.GET_LINES (lines OUT CHARARR, numlines IN OUT INTEGER); Retrieves an array of lines from the buffer.

5

DBMS_OUTPUT.NEW_LINE; Puts an end-of-line marker.

6

DBMS_OUTPUT.PUT(item IN VARCHAR2); Places a partial line in the buffer.

7

Example

DECLARE
   lines dbms_output.chararr;
   num_lines number;
BEGIN
   -- enable the buffer with default size 20000
   dbms_output.enable;

   dbms_output.put_line('Hello Reader!');
   dbms_output.put_line('Hope you have enjoyed the tutorials!');
   dbms_output.put_line('Have a great time exploring pl/sql!');

   num_lines := 3;

   dbms_output.get_lines(lines, num_lines);

   FOR i IN 1..num_lines LOOP
      dbms_output.put_line(lines(i));
   END LOOP;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Hello Reader!
Hope you have enjoyed the tutorials!
Have a great time exploring pl/sql!

PL/SQL procedure successfully completed.

PL/SQL - Object Oriented

在本章中,我们将讨论面向对象的 PL/SQL。PL/SQL 允许定义对象类型,这有助于在 Oracle 中设计面向对象数据库。对象类型允许创建复合类型。使用对象允许您实现具有特定数据结构和对其操作方法的真实世界对象。对象具有属性和方法。属性是对象的性质,用于存储对象的状态;方法用于对行为建模。

In this chapter, we will discuss Object-Oriented PL/SQL. PL/SQL allows defining an object type, which helps in designing object-oriented database in Oracle. An object type allows you to create composite types. Using objects allow you to implement real world objects with specific structure of data and methods for operating it. Objects have attributes and methods. Attributes are properties of an object and are used for storing an object’s state; and methods are used for modeling its behavior.

使用 CREATE [OR REPLACE] TYPE 语句创建对象。以下是一个创建包含几个属性的简单 address 对象的示例:

Objects are created using the CREATE [OR REPLACE] TYPE statement. Following is an example to create a simple address object consisting of few attributes −

CREATE OR REPLACE TYPE address AS OBJECT
(house_no varchar2(10),
 street varchar2(30),
 city varchar2(20),
 state varchar2(10),
 pincode varchar2(10)
);
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

让我们再创建一个对象 customer ,其中我们把 attributesmethods 结合在一起,以获得面向对象的体验:

Let’s create one more object customer where we will wrap attributes and methods together to have object-oriented feeling −

CREATE OR REPLACE TYPE customer AS OBJECT
(code number(5),
 name varchar2(30),
 contact_no varchar2(12),
 addr address,
 member procedure display
);
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

Instantiating an Object

定义对象类型为对象提供蓝图。为了使用此对象,需要创建此对象的实例。您可以使用实例名称和 the access operator (.) 访问对象的属性和方法,如下所示:

Defining an object type provides a blueprint for the object. To use this object, you need to create instances of this object. You can access the attributes and methods of the object using the instance name and the access operator (.) as follows −

DECLARE
   residence address;
BEGIN
   residence := address('103A', 'M.G.Road', 'Jaipur', 'Rajasthan','201301');
   dbms_output.put_line('House No: '|| residence.house_no);
   dbms_output.put_line('Street: '|| residence.street);
   dbms_output.put_line('City: '|| residence.city);
   dbms_output.put_line('State: '|| residence.state);
   dbms_output.put_line('Pincode: '|| residence.pincode);
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

House No: 103A
Street: M.G.Road
City: Jaipur
State: Rajasthan
Pincode: 201301

PL/SQL procedure successfully completed.

Member Methods

Member methods 用于操作对象的 attributes 。在声明对象类型时,您提供了成员方法的声明。对象主体定义了成员方法的代码。对象主体是使用 CREATE TYPE BODY 语句创建的。

Member methods are used for manipulating the attributes of the object. You provide the declaration of a member method while declaring the object type. The object body defines the code for the member methods. The object body is created using the CREATE TYPE BODY statement.

Constructors 是函数,它们返回一个新对象作为其值。每个对象都有一个系统定义的构造函数方法。构造函数的名称与对象类型相同。例如:

Constructors are functions that return a new object as its value. Every object has a system defined constructor method. The name of the constructor is same as the object type. For example −

residence := address('103A', 'M.G.Road', 'Jaipur', 'Rajasthan','201301');

comparison methods 用于比较对象。有两种方法可以比较对象:

The comparison methods are used for comparing objects. There are two ways to compare objects −

Map method

Map method 是一种通过这种方式实现的函数,其值取决于属性的值。例如,对于一个客户对象,如果两个客户的客户代码相同,那么这两个客户可能是一样的。因此,这两个对象之间的关系将取决于代码的值。

The Map method is a function implemented in such a way that its value depends upon the value of the attributes. For example, for a customer object, if the customer code is same for two customers, both customers could be the same. So the relationship between these two objects would depend upon the value of code.

Order method

Order method 实现了用于比较两个对象的一些内部逻辑。例如,对于一个矩形对象,如果它的两边都更大,那么一个矩形将大于另一个矩形。

The Order method implements some internal logic for comparing two objects. For example, for a rectangle object, a rectangle is bigger than another rectangle if both its sides are bigger.

Using Map method

让我们尝试使用以下矩形对象来理解上述概念-

Let us try to understand the above concepts using the following rectangle object −

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 member function enlarge( inc number) return rectangle,
 member procedure display,
 map member function measure return number
);
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

创建类型主体-

Creating the type body −

CREATE OR REPLACE TYPE BODY rectangle AS
   MEMBER FUNCTION enlarge(inc number) return rectangle IS
   BEGIN
      return rectangle(self.length + inc, self.width + inc);
   END enlarge;
   MEMBER PROCEDURE display IS
   BEGIN
      dbms_output.put_line('Length: '|| length);
      dbms_output.put_line('Width: '|| width);
   END display;
   MAP MEMBER FUNCTION measure return number IS
   BEGIN
      return (sqrt(length*length + width*width));
   END measure;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type body created.

现在使用矩形对象及其成员函数-

Now using the rectangle object and its member functions −

DECLARE
   r1 rectangle;
   r2 rectangle;
   r3 rectangle;
   inc_factor number := 5;
BEGIN
   r1 := rectangle(3, 4);
   r2 := rectangle(5, 7);
   r3 := r1.enlarge(inc_factor);
   r3.display;
   IF (r1 > r2) THEN -- calling measure function
      r1.display;
   ELSE
      r2.display;
   END IF;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Length: 8
Width: 9
Length: 5
Width: 7

PL/SQL procedure successfully completed.

Using Order method

现在, same effect could be achieved using an order method 。让我们使用一个 order 方法来重新创建矩形对象-

Now, the same effect could be achieved using an order method. Let us recreate the rectangle object using an order method −

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 member procedure display,
 order member function measure(r rectangle) return number
);
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

创建类型主体-

Creating the type body −

CREATE OR REPLACE TYPE BODY rectangle AS
   MEMBER PROCEDURE display IS
   BEGIN
      dbms_output.put_line('Length: '|| length);
      dbms_output.put_line('Width: '|| width);
   END display;
   ORDER MEMBER FUNCTION measure(r rectangle) return number IS
   BEGIN
      IF(sqrt(self.length*self.length + self.width*self.width)>
         sqrt(r.length*r.length + r.width*r.width)) then
         return(1);
      ELSE
         return(-1);
      END IF;
   END measure;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type body created.

使用矩形对象及其成员函数-

Using the rectangle object and its member functions −

DECLARE
   r1 rectangle;
   r2 rectangle;
BEGIN
   r1 := rectangle(23, 44);
   r2 := rectangle(15, 17);
   r1.display;
   r2.display;
   IF (r1 > r2) THEN -- calling measure function
      r1.display;
   ELSE
      r2.display;
   END IF;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Length: 23
Width: 44
Length: 15
Width: 17
Length: 23
Width: 44

PL/SQL procedure successfully completed.

Inheritance for PL/SQL Objects

PL/SQL允许从现有的基础对象创建对象。要实施继承,基础对象应被声明为 NOT FINAL 。默认值为 FINAL

PL/SQL allows creating object from the existing base objects. To implement inheritance, the base objects should be declared as NOT FINAL. The default is FINAL.

以下程序展示了PL/SQL对象中的继承。让我们创建另一个名为 TableTop 的对象,它从Rectangle对象中继承而来。为此,我们需要创建基础矩形对象-

The following programs illustrate the inheritance in PL/SQL Objects. Let us create another object named TableTop, this is inherited from the Rectangle object. For this, we need to create the base rectangle object −

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 member function enlarge( inc number) return rectangle,
 NOT FINAL member procedure display) NOT FINAL
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

创建基础类型主体-

Creating the base type body −

CREATE OR REPLACE TYPE BODY rectangle AS
   MEMBER FUNCTION enlarge(inc number) return rectangle IS
   BEGIN
      return rectangle(self.length + inc, self.width + inc);
   END enlarge;
   MEMBER PROCEDURE display IS
   BEGIN
      dbms_output.put_line('Length: '|| length);
      dbms_output.put_line('Width: '|| width);
   END display;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type body created.

创建子对象桌台-

Creating the child object tabletop −

CREATE OR REPLACE TYPE tabletop UNDER rectangle
(
   material varchar2(20),
   OVERRIDING member procedure display
)
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.

创建子对象桌台的类型主体-

Creating the type body for the child object tabletop

CREATE OR REPLACE TYPE BODY tabletop AS
OVERRIDING MEMBER PROCEDURE display IS
BEGIN
   dbms_output.put_line('Length: '|| length);
   dbms_output.put_line('Width: '|| width);
   dbms_output.put_line('Material: '|| material);
END display;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type body created.

使用桌台对象及其成员函数-

Using the tabletop object and its member functions −

DECLARE
   t1 tabletop;
   t2 tabletop;
BEGIN
   t1:= tabletop(20, 10, 'Wood');
   t2 := tabletop(50, 30, 'Steel');
   t1.display;
   t2.display;
END;
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Length: 20
Width: 10
Material: Wood
Length: 50
Width: 30
Material: Steel

PL/SQL procedure successfully completed.

Abstract Objects in PL/SQL

NOT INSTANTIABLE 子句允许您声明一个抽象对象。您不能按原样使用抽象对象;您将需要创建此类对象的子类型或子类型来使用它的功能。

The NOT INSTANTIABLE clause allows you to declare an abstract object. You cannot use an abstract object as it is; you will have to create a subtype or child type of such objects to use its functionalities.

例如,

For example,

CREATE OR REPLACE TYPE rectangle AS OBJECT
(length number,
 width number,
 NOT INSTANTIABLE NOT FINAL MEMBER PROCEDURE display)
 NOT INSTANTIABLE NOT FINAL
/

当以上代码在 SQL 提示符下执行时,它会生成以下结果:

When the above code is executed at the SQL prompt, it produces the following result −

Type created.