在 oracle 中使用集合的主要目的是什么?
按表索引
嵌套表
可变大小数组
你能解释一下上述类型的集合之间的区别吗?
在 oracle 中使用集合的主要目的是什么?
按表索引
嵌套表
可变大小数组
你能解释一下上述类型的集合之间的区别吗?
让我们从嵌套表开始,它们是最常见的集合形式,因此代表了有用的比较基础。
嵌套表是一个变量,它可以保存多个实例,通常是数据库表中的一条记录。它们可能会这样声明:
type emp_nt is table of emp%rowtype;
emp_rec_nt emp_nt;
每当我们想要存储我们想要做同样事情的多个数据实例时,它们很有用。经典示例是使用 BULK COLLECT 存储多条记录:
select *
bulk collect into emp_rec_nt
from employees;
这给了我们一个可以循环的数据源;至关重要的是,我们可以向后和向前导航,甚至可以跳到结尾或开头,这是我们用光标无法做到的。嵌套表可以是任何数据类型的集合,包括诸如 PL/SQL 记录或用户定义类型之类的组合。
一个 Index By 表最好被称为(正如文档所做的那样)一个 Associative Array 。这些是带有索引的单个属性的简单集合。嵌套表也有索引,但它们的索引只是行数。使用关联数组,索引可以是有意义的,即源自数据值。因此它们对于缓存数据值以供以后使用很有用。索引可以是一个数字,或者(从 9iR2 开始)一个非常有用的字符串。例如,这是一个由员工标识符索引的薪水关联数组。
type emp_sal_aa is table of emp.sql%type
index by emp.empno%type;
l_emp_sales emp_sal_aa;
请注意,我可以使用 INDEX BY BINARY_INTEGER 声明该数组,但使用 %TYPE 语法(自记录代码)更清晰。该数组的元素可以通过索引值标识,在本例中为 EMPNO:
l_emp_sals(l_emp_no) := l_emp_sal;
除了缓存引用表或类似的查找值之外,关联数组的用例并不多。
变量数组只是嵌套表,对元素的数量有预定义的限制。所以也许这个名字有误导性:它们实际上是固定数组。VArrays 几乎没有我们可以用嵌套表做的事情(除了限制元素的数量,我们很少会想要这样做)。它们是这样声明的:
type emp_va is varray(14) of emp%rowtype;
emp_rec_va emp_va;
我们可以使用批量收集来填充 VArray ...
select *
bulk collect into emp_rec_va
from employees;
但是,我们必须确定查询将最多返回VArray 声明中指定的元素数量。否则 SELECT 将抛出 ORA-22165。
变量数组没有已知的用例。好吧,这有点苛刻,但几乎所有时候您都会使用嵌套表。VArray 相对于嵌套表的一大优势是它们保证了元素的顺序。因此,如果您必须按照插入元素的顺序取出元素,请使用 VArray。
PL/SQL 文档用一整章的篇幅介绍集合。 了解更多。
关联数组,也称为索引表,可让您使用任意数字和字符串查找下标值的元素。这些类似于其他编程语言中的哈希表。
嵌套表包含任意数量的元素。他们使用序号作为下标。您可以定义等效的 SQL 类型,允许将嵌套表存储在数据库表中并通过 SQL 进行操作。
Varrays(可变大小数组的缩写)包含固定数量的元素(尽管您可以在运行时更改元素数量)。他们使用序号作为下标。您可以定义等效的 SQL 类型,允许将可变数组存储在数据库表中。它们可以通过 SQL 存储和检索,但灵活性不如嵌套表。
嵌套表和关联数组(以前称为索引表)都使用类似的下标表示法,但在持久性和参数传递的简易性方面它们具有不同的特征。
嵌套表可以存储在数据库列中,但关联数组不能。嵌套表可以简化 SQL 操作,您通常会将单列表与更大的表连接起来。
关联数组适用于相对较小的查找表,其中每次调用过程或初始化包时可以在内存中构建集合。它们适合收集事先未知数量的信息,因为它们的大小没有固定的限制。它们的索引值更灵活,因为关联数组下标可以是负数,可以是非连续的,并且可以使用字符串值而不是数字。
PL/SQL 自动在主机数组和使用数字键值的关联数组之间进行转换。将集合传入和传出数据库服务器的最有效方法是在关联数组中设置数据值,然后将这些关联数组与批量构造(FORALL 语句或 BULK COLLECT 子句)一起使用。
在以下情况下,可变数组是一个不错的选择:
元素的数量是预先知道的。
元素通常都是按顺序访问的。
当存储在数据库中时,可变数组保持它们的顺序和下标。
每个 varray 存储为单个对象,或者在它是列的表内(如果 varray 小于 4KB)或在表外但仍然在同一个表空间中(如果 varray 大于 4KB)。您必须同时更新或检索 varray 的所有元素,这在一次对所有元素执行某些操作时最合适。但是您可能会发现以这种方式存储和检索大量元素是不切实际的。
在以下情况下,嵌套表是一个不错的选择:
索引值不是连续的。
没有固定数量的索引值。但是,施加了最大限制。
您需要一次删除或更新一些元素,但不是所有元素。
您通常会创建一个单独的查找表,主表的每一行都有多个条目,并通过连接查询访问它。
嵌套表可以是稀疏的:您可以删除任意元素,而不仅仅是从末尾删除一个项目。
嵌套表数据存储在单独的存储表中,该表是系统生成的与嵌套表关联的数据库表。当您访问嵌套表时,数据库会为您连接表。这使得嵌套表适用于只影响集合中某些元素的查询和更新。
当嵌套表存储在数据库中并从数据库中检索时,您不能依赖嵌套表的顺序和下标保持稳定,因为顺序和下标不会保留在数据库中。
你可以使用链接
或者只是阅读它。
嵌套表只是一个包含 n 个元素的数组。
declare
type nested_table_of_integer is table of integer;
v_my_nested_table nested_table_of_integer;
begin
v_my_nested_table := nested_table_of_integer(); -- initialize
v_my_nested_table.extend(10); -- add 10 elements
v_my_nested_table(1) := 100;
v_my_nested_table(11) := 1000; -- ORA-06533: Subscript beyond count
end;
嵌套表必须如图所示进行初始化。一开始它的元素为零。要添加元素,我们使用 EXTEND。这个嵌套表有 10 个元素。它们的索引为 1 到 10。元素 1 的值为 100。其他元素的值为 null。访问不存在的元素(例如第 11 个元素)会引发错误。
另一方面,关联数组是名称/值对的数组。让我们使用数字(通常是 pls_integer)来命名:
declare
type associative_array_of_integer is table of integer index by pls_integer;
v_my_associative_array associative_array_of_integer;
begin
v_my_associative_array(1) := 100;
v_my_associative_array(11) := 1000;
v_my_associative_array(12) := v_my_associative_array(2); -- ORA-01403: no data found
end;
关联数组不需要初始化。它是空的并且被填充。这里我们将名为 1 的元素与值 100 相关联,将名为 11 的元素与值 1000 相关联。所以数组中有两个元素。当我们尝试访问不在数组中的名称时,我们得到一个找不到数据的异常。
我们还可以使用字符串作为名称:
declare
type associative_array_of_integer is table of integer index by varchar2(100);
v_my_associative_array associative_array_of_integer;
begin
v_my_associative_array('age father') := 39;
v_my_associative_array('age mother') := 32;
v_my_associative_array('age daughter') := 11;
end;
您可以使用这两个集合来获取表数据,但使用方式不同。嵌套表有一个计数,您可以从 1 循环到计数以访问其元素:
declare
type nested_table_of_integer is table of integer;
v_my_nested_table nested_table_of_integer;
begin
v_my_nested_table := nested_table_of_integer(); -- initialize
select table_name bulk collect into v_my_nested_table from user_tables;
for i in 1 .. v_my_nested_table.count loop
dbms_output.put_line(v_my_nested_table(i));
end loop;
end;
然而,必须使用 FIRST 和 NEXT 从碰巧是下一个和下一个和下一个的第一个索引中读取关联数组。
declare
type associative_array_of_integer is table of integer index by pls_integer;
v_my_associative_array associative_array_of_integer;
i integer;
begin
select table_name bulk collect into v_my_associative_array from user_tables;
i := v_my_associative_array.first;
while i is not null loop
dbms_output.put_line(v_my_associative_array(i));
i := v_my_associative_array.next(i);
end loop;
end;
这里的“名称”恰好是 1、2、3 等(因此由批量集合给出),例如,您可以访问 v_my_associative_array(1)。然而,在你的程序后面,在数组中进行一些可能的删除操作之后,可能会出现间隙,所以你不知道是否存在名为 1 的元素,也不知道元素 4 之前的元素是否恰好是元素 3。与批量收集一样元素的“名称”没有任何意义,您不会真正使用它们,而是通过如图所示的链。
集合是一组有序的元素,所有元素的类型都相同。每个元素都由一个唯一的下标标识,该下标代表其在集合中的位置
PL/SQL 提供了三种集合类型 -</p>
索引表或关联数组 嵌套表 可变大小数组或 Varray
使用集合的主要目的是提高应用程序性能。通过使用集合,我们可以“缓存”需要频繁访问和需要修改的静态数据。这会减少对数据库的调用。
此外,如果您需要处理许多类似类型的项目,将这些项目存储在一个集合中将使您可以轻松地遍历每个元素,并通过索引引用每个元素。