Oracle PL/SQL 集合:Varray、嵌套和按表索引

什么是收藏?

集合是特定数据类型元素的有序集合。它可以是简单数据类型或复杂数据类型(如用户定义或记录类型)的集合。

在集合中,每个元素都由一个术语来标识,称为 “下标”。 集合中的每个项目都分配有一个唯一的下标。可以通过引用该唯一下标来操作或获取该集合中的数据。

当需要处理或操作大量相同类型的数据时,集合是最有用的。可以使用“BULK”选项填充和操作整个集合 Oracle.

集合根据结构、下标和存储进行分类,如下所示。

  • 按表索引(也称为关联数组)
  • 嵌套表
  • 变量数组

在任何时候,集合中的数据都可以通过三个术语来引用:集合名称、下标、字段/列名称,即“ ( )。 ”。您将在下面的部分进一步了解上述这些收集类别。

变量数组

Varray 是一种数组大小固定的集合方法。数组大小不能超过其固定值。Varray 的下标为数值。以下是 Varray 的属性。

  • 上限尺寸固定
  • 从下标“1”开始按顺序填充
  • 此集合类型始终是密集的,即我们无法删除任何数组元素。Varray 可以整体删除,也可以从末尾修剪。
  • 由于它的本质总是密集的,所以它的灵活性很差。
  • 当已知数组大小时使用并对所有数组元素执行类似的活动更为合适。
  • 下标和序列始终保持稳定,即集合的下标和计数始终相同。
  • 在程序中使用它们之前需要初始化它们。对未初始化的集合执行任何操作(EXISTS 操作除外)都会抛出错误。
  • 它可以被创建为一个数据库对象,在整个数据库或子程序内部可见,并且只能在该子程序中使用。

下图将以图表方式解释 Varray(dense)的内存分配。

1 2 3 4 5 6 7
价值 XYZ 直流电压 斯德 CXS 维BC 新和成 QWE

VARRAY 的语法:

TYPE <type_name> IS VARRAY (<SIZE>) OF <DATA_TYPE>;
  • 在上面的语法中,type_name 被声明为给定大小限制的 'DATA_TYPE' 类型的 VARRAY。数据类型可以是简单类型或复杂类型。

嵌套表

嵌套表是一种数组大小不固定的集合。它具有数字下标类型。下面是有关嵌套表类型的更多描述。

  • 嵌套表没有大小上限。
  • 由于上限大小不固定,每次使用集合之前都需要扩展内存。我们可以使用“EXTEND”关键字来扩展集合。
  • 从下标“1”开始按顺序填充。
  • 此集合类型可以同时为 密集和稀疏,即我们可以将集合创建为密集的,并且我们也可以随机删除单个数组元素,使其变得稀疏。
  • 它为删除数组元素提供了更大的灵活性。
  • 它存储在系统生成的数据库表中,可以在选择查询中使用来获取值。
  • 下标和序列不稳定,即数组元素的下标和计数可以变化。
  • 在程序中使用它们之前需要进行初始化,对未初始化的集合进行任何操作(EXISTS 操作除外)都会抛出错误。
  • 它可以被创建为一个数据库对象,在整个数据库或子程序内部可见,并且只能在该子程序中使用。

下图将以图表形式解释嵌套表(密集和稀疏)的内存分配。黑色元素空间表示集合中的空元素,即稀疏元素。

1 2 3 4 5 6 7
值(密集) XYZ 直流电压 斯德 CXS 维BC 新和成 QWE
值(稀疏) QWE ASD 阿富汗 ASD 黄万华

嵌套表的语法:

TYPE <tvpe name> IS TABLE OF <DATA TYPE>;
  • 在上面的语法中,type_name 被声明为 'DATA_TYPE' 类型的嵌套表集合。数据类型可以是简单类型,也可以是复杂类型。

按表索引

按表索引是一种数组大小不固定的集合。与其他集合类型不同,按表索引集合中的下标可以由用户定义。以下是按表索引的属性。

  • 下标可以是整数或字符串。在创建集合时,应提及下标类型。
  • 这些集合不是按顺序存储的。
  • 它们在本质上总是稀疏的。
  • 数组大小不固定。
  • 它们不能存储在数据库列中。它们应在特定会话中的任何程序中创建和使用。
  • 它们在维护下标方面提供了更大的灵活性。
  • 下标也可以是负下标序列。
  • 它们更适合用于相对较小的集合值,其中集合可以在同一个子程序中初始化和使用。
  • 在开始使用它们之前不需要初始化它们。
  • 它不能作为数据库对象创建。它只能在子程序内部创建,并且只能在该子程序中使用。
  • 此集合类型中不能使用 BULK COLLECT,因为集合中每条记录都必须明确给出下标。

下图将以图表形式解释嵌套表(稀疏)的内存分配。黑色元素空间表示集合中的空元素,即稀疏元素。

下标 (varchar) 第一 第二 第三 第四 第五 第六 第七
值(稀疏) QWE ASD 阿富汗 ASD 黄万华

表索引的语法

TYPE <type_name> IS TABLE OF <DATA_TYPE> INDEX BY VARCHAR2 (10);
  • 在上面的语法中,type_name 被声明为类型为“DATA_TYPE”的索引表集合。数据类型可以是简单类型或复杂类型。subsciprt/index 变量被指定为 VARCHAR2 类型,最大大小为 10。

集合中的构造函数和初始化概念

构造函数是 Oracle 提供的内置函数,其名称与对象或集合相同。当对象或集合在会话中第一次被引用时,它们会首先执行。以下是集合上下文中构造函数的重要细节:

  • 对于集合,应该明确调用这些构造函数来初始化它。
  • 在引入程序之前,Varray 和 Nested 表都需要通过这些构造函数进行初始化。
  • 构造函数隐式扩展了集合(Varray 除外)的内存分配,因此构造函数也可以将变量分配给集合。
  • 通过构造函数为集合分配值永远不会使集合变得稀疏。

收集方法

Oracle 提供许多函数来操作和使用集合。这些函数在程序中非常有用,可以确定和修改集合的不同属性。下表将给出不同的函数及其描述。

付款方式 描述 句法
存在(n) 此方法将返回布尔结果。如果 nth 元素存在于该集合中,否则将返回 FALSE。只有 EXISTS 函数可以在未初始化的集合中使用 .EXISTS(元素位置)
COUNT个 给出集合中元素的总数 。数数
极限 它返回集合的最大大小。对于 Varray,它将返回已定义的固定大小。对于嵌套表和按表索引,它返回 NULL 。限制
第一 返回集合第一个索引变量(下标)的值 。第一的
LAST 返回集合最后一个索引变量(下标)的值 。最后的
先前 (n) 返回集合中位于索引变量之前的 nth 元素。如果没有前导索引值,则返回 NULL .PRIOR(n)
下一个(n) 返回集合中成功索引变量的 nth 元素。如果没有成功索引值则返回 NULL .NEXT(n)
延伸 在集合末尾扩展一个元素 。延长
延伸(n) 在集合末尾扩展 n 个元素 .EXTEND(n)
扩展 (n,i) 扩展 i 的 n 个副本th 集合末尾的元素 .EXTEND(n,i)
TRIM 从集合末尾删除一个元素 。修剪
修剪(n) 从集合末尾删除 n 个元素 .TRIM(n)
删除 删除集合中的所有元素。使集合为空 。删除
删除(n) 从集合中删除第 n 个元素。如果第 n 个th 元素为 NULL,则此操作不会执行任何操作 .删除(n)
删除 (m,n) 删除范围 m 内的元素th 至nth 在集合中 .删除(m,n)

例1:子程序级别的记录类型

在此示例中,我们将了解如何使用“批量收集'以及如何引用收集数据。

子程序级别的记录类型

DECLARE
TYPE emp_det IS RECORD
(
EMP_NO NUMBER,
EMP_NAME VARCHAR2(150),
MANAGER NUMBER,
SALARY NUMBER
);
TYPE emp_det_tbl IS TABLE OF emp_det; guru99_emp_rec emp_det_tbl:= emp_det_tbl(); 
BEGIN
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1000,’AAA’,25000,1000);
INSERT INTO emp (emp_no,emp_name, salary, manager) VALUES (1001,'XXX’,10000,1000);
INSERT INTO emp (emp_no, emp_name, salary, manager) VALUES (1002,'YYY',15000,1000);
INSERT INTO emp (emp_no,emp_name,salary, manager) VALUES (1003,’ZZZ’,'7500,1000);
COMMIT:
SELECT emp no,emp_name,manager,salary BULK COLLECT INTO guru99_emp_rec
FROM emp;
dbms_output.put_line (‘Employee Detail');
FOR i IN guru99_emp_rec.FIRST..guru99_emp_rec.LAST
LOOP
dbms_output.put_line (‘Employee Number: '||guru99_emp_rec(i).emp_no); 
dbms_output.put_line (‘Employee Name: '||guru99_emp_rec(i).emp_name); 
dbms_output.put_line (‘Employee Salary:'|| guru99_emp_rec(i).salary); 
dbms_output.put_line(‘Employee Manager Number:'||guru99_emp_rec(i).manager);
dbms_output.put_line('--------------------------------');
END LOOP;
END;
/

代码说明:

  • 代码行 2-8: 记录类型 'emp_det' 由 emp_no、emp_name、salary 和 manager 等列声明,数据类型为 NUMBER、VARCHAR2、NUMBER、NUMBER。
  • 代码第 9 行: 创建记录类型元素“emp_det”的集合“emp_det_tbl”
  • 代码第 10 行: 将变量“guru99_emp_rec”声明为“emp_det_tbl”类型并使用空构造函数初始化。
  • 代码行12-15: 将示例数据插入“emp”表。
  • 代码第 16 行: 提交插入事务。
  • 代码第 17 行: 使用命令“BULK COLLECT”从“emp”表中获取记录,并将收集变量作为批量填充。现在变量“guru99_emp_rec”包含表“emp”中存在的所有记录。
  • 代码行19-26: 设置“FOR”循环用于逐一打印集合中的所有记录。集合方法 FIRST 和 LAST 用作 循环.

输出:如您在上面的屏幕截图中看到的,当执行上述代码时,您将获得以下输出

Employee Detail
Employee Number: 1000
Employee Name: AAA
Employee Salary: 25000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1001
Employee Name: XXX
Employee Salary: 10000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1002
Employee Name: YYY
Employee Salary: 15000
Employee Manager Number: 1000
----------------------------------------------
Employee Number: 1003
Employee Name: ZZZ
Employee Salary: 7500
Employee Manager Number: 1000
----------------------------------------------

总结一下这篇文章: