在Oracle中使用不同类型的PL/SQL集合的目的



在oracle中使用集合的主要目的是什么?

  1. 表索引

  2. 嵌套表

  3. 可变尺寸ARRAY

你能解释一下以上藏品类型之间的区别吗?

让我们从嵌套表开始,它们是最常见的集合形式,因此代表了一个有用的比较基础。

嵌套表是一个变量,它可以容纳多个实例,通常是数据库表中的一条记录。它们可能会这样声明:

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记录或用户定义类型等组合。

"索引依据"表最好称为"关联数组"(与文档一样)。这些是带有索引的单个属性的简单集合。嵌套表也有索引,但它们的索引只是行计数。对于关联数组,索引可能是有意义的,即来源于数据值。因此,它们对于缓存数据值以供以后使用非常有用。索引可以是一个数字,也可以是(由于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。

变量数组没有已知的用例。好吧,这有点苛刻,但几乎所有时候你都会使用嵌套表。VArrays相对于嵌套表的一大优势是,它们保证了元素的顺序。因此,如果必须以与插入相同的顺序取出元素,请使用VArray。

PL/SQL文档用整整一章的篇幅介绍集合。了解更多信息。

PL/SQL提供以下集合类型:-

关联数组,也称为表索引,允许您使用任意数字和字符串查找元素的下标值。这些类似于其他编程语言中的哈希表。

嵌套表包含任意数量的元素。他们使用序号作为下标。您可以定义等效的SQL类型,允许嵌套表存储在数据库表中并通过SQL进行操作。

Varray(可变大小数组的缩写)包含固定数量的元素(尽管您可以在运行时更改元素的数量)。他们使用序号作为下标。您可以定义等效的SQL类型,允许varray存储在数据库表中。它们可以通过SQL进行存储和检索,但灵活性不如嵌套表。

1.在嵌套表和关联数组之间进行选择:-

嵌套表和关联数组(以前称为表索引)都使用类似的下标表示法,但在持久性和参数传递的方便性方面,它们有不同的特性。

嵌套表可以存储在数据库列中,但关联数组不能。嵌套表可以简化SQL操作,通常将单列表与较大的表连接在一起。

关联数组适用于相对较小的查找表,每次调用过程或初始化包时,都可以在内存中构造集合。它们非常适合收集事先未知数量的信息,因为它们的大小没有固定的限制。它们的索引值更灵活,因为关联数组下标可以是负数,可以是非序列的,并且可以使用字符串值而不是数字。

PL/SQL会自动在主机数组和使用数字键值的关联数组之间进行转换。将集合传递到数据库服务器和从数据库服务器传递集合的最有效方法是在关联数组中设置数据值,然后将这些关联数组与大容量构造(FORALL语句或bulk COLLECT子句)一起使用。

2.在嵌套表和Varray之间进行选择:-

Varrays是一个不错的选择当:

元件的数量是预先已知的。

这些元素通常都是按顺序访问的。

当存储在数据库中时,varray会保留它们的顺序和下标。

每个varray都存储为一个单独的对象,要么存储在作为列的表内(如果varray小于4KB),要么存储于表外但仍在同一个表空间中(如果varray大于4KB)。必须同时更新或检索varray的所有元素,这在同时对所有元素执行某些操作时最为合适。但是,您可能会发现以这种方式存储和检索大量元素是不切实际的。

当出现以下情况时,嵌套表是一个不错的选择:

索引值不连续。

没有设定数量的索引值。但是,有一个最高限额。

您需要删除或更新某些元素,但不能同时删除或更新所有元素。

您通常会创建一个单独的查找表,主表的每一行都有多个条目,并通过联接查询访问它。

嵌套表可以是稀疏的:您可以删除任意元素,而不仅仅是从末尾删除一个项。

嵌套表数据存储在单独的存储表中,该存储表是与嵌套表关联的系统生成的数据库表。当您访问嵌套表时,数据库会为您联接表。这使得嵌套表适合于只影响集合中某些元素的查询和更新。

当嵌套表存储在数据库中并从数据库中检索时,不能依赖嵌套表的顺序和下标保持稳定,因为顺序和下标不会保留在数据库中。

U可以使用链接

嵌套数组和关联数组之间的区别是什么?

或者只是读一读。

嵌套表只是一个由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提供三种收集类型——

按表或关联数组索引嵌套表可变大小数组或Varray

使用集合的主要目的是提高应用程序性能。通过使用集合,我们可以"缓存"需要频繁访问和修改的静态数据。这会减少对数据库的调用。

此外,如果您需要处理多个类似类型的项,将这些项存储在集合中将允许您轻松地遍历每个元素,并通过索引引用每个元素。

有关集合的更多详细信息,请参阅本文

最新更新