PL/SQL:集合类型 (定义,分类,使用场景,集合方法)

来源:互联网 发布:婚礼快剪mac用什么软件 编辑:程序博客网 时间:2024/06/16 22:57

COLLECTION

单行单列    变量    单行多列    记录    多行单列    集合    多行多列    记录+集合

定义:

       集合是相同类型元素的组合。数据库中相当于"多行单列", 类似于数组, 使用唯一的下标来标识其中的每个元素


分类:

分类语法下标元素个数赋初始值.extend能否存在DB中索引表TYPE type_name IS TABLE OF element_type
  
INDEX BY index_type;
整数或字符
可以为负无限制不需要不需要只能用在PLSQL中嵌套表TYPE type_name IS TABLE OF element_type;

整型
只能为正无限制用同名构造函数赋值
其参数可以为空必要可以使用create type创建, 一直存在数据库中变长数组TYPE type_name IS VARRAY(n) OF element_type;

有限制

使用场景
  • 索引表: 通常第一选择是索引表,因为它不需要初始化或者extend且无个数限制操作,并且是迄今为止最高效的集合类型。
                唯一不足的一点是它只能用于PL/SQL而不能直接用于数据库。
                如果你需要允许使用负数索引,应该选择索引表;
  • 嵌套表: 如果你需要使用10g,11g中的那些集合操作,应该选择Nested table;
  • 变长数组: 如果需要限制集合元素的个数




1、索引表

TYPE type_name IS TABLE OF element_type INDEX BY index_type;  

table_name            type_name 


element_type:集合中的元素的类型。如number、char, 也可以是记录

index_type    :只能是整型或者字符串 pls_integer , binary_integer or char


示例表:

例1:


例2:游标 + 集合
1
declare
2
  cursor name_cur     is select last_name from student where rownum <= 10;
3
  type last_name_type is table of student.last_name%type index by pls_integer;
4
  last_name_tab       last_name_type;
5
  v_idx               pls_integer := 0;    --index by pls_integer 需要一个整数变量做计数器
6
begin
7
  for src in name_cur loop     --游标for循环
8
    v_idx := v_idx + 1; 
9
    last_name_tab(v_idx) := src.last_name;  --索引表集合赋值
10
    dbms_output.put_line('插入 ' || last_name_tab(v_idx));
11
  end loop;
12
  
13
  for i in last_name_tab.first .. last_name_tab.last LOOP --数值for循环
14
    dbms_output.put_line('展示 : ' || last_name_tab(i));
15
  end loop;
16
end;

  注意:
          引用不存在的元素会抛出NO_DATA_FOUND异常。例如, DBMS_OUTPUT.PUT_LINE (last_name_tab(11));



2、嵌套表

TYPE type_name IS TABLE OF element_type ;
table_name 
           type_name 

嵌套表和索引表区别:
  • 嵌套表没有index by,其下标固定为整型
  • 必须使用和其同名的构造器函数对其初始化
    • 因为当声明嵌套表时, 其本身被设置为null. 为了引用嵌套表中的单个元素, 必须先使用同名构造器函数对他初始化
    • 嵌套表的构造器函数与嵌套表完全同名, 可以带参也可以无参
      • 带参: coll_name := coll_name ('firstname', 'lastname');
      • 无参: coll_name := coll_name ();
  • 循环遍历时,必须持续使用 .extend() 方法分配存储空间

例子:
1
declare
2
  cursor name_cur     is select last_name from student where rownum <= 10;
3
  v_idx               pls_integer := 0;
4
  type last_name_type is table of student.last_name%type; --定义嵌套表, 元素类型是学生姓名
5
  last_name_tab       last_name_type := last_name_type(); --定义变量, 并初始化嵌套表!
6
begin
7
  for i in name_cur loop
8
    last_name_tab.extend; --必须先调用它的extend方法给集合添加存储空间
9
    v_idx := v_idx + 1;
10
    last_name_tab(v_idx) := i.last_name; --赋值,和取值语法是一样的!
11
    dbms_output.put_line('Insert ' || last_name_tab(v_idx));
12
  end loop;
13
end;



3、变长数组

定义:

         有最大长度限制的嵌套表, 编码上和嵌套表完全相同


语法:

TYPE type_name IS  VARRAY(最大值) OF element_type;

varray_name type_name 


例子:

修改上例,使用变长数组 

1
DECLARE 
2
    CURSOR name_cur IS SELECT last_name FROM student WHERE  ROWNUM <= 10; 
3
    v_idx           PLS_INTEGER := 0; 
4
    TYPE type_name  IS varray(10) OF student.last_name%TYPE;  --最大长度为10的嵌套表
5
    cool_name       type_name := type_name(); 
6
BEGIN 
7
    FOR i IN name_cur LOOP 
8
        cool_name.extend; 
9
        v_idx := v_idx + 1; 
10
        cool_name (v_idx) := i.last_name; 
11
        dbms_output.Put_line ('Insert ' || Last_name_tab (v_idx)); 
12
    END LOOP; 
13
END;




※ 集合方法 ※


定义:
        集合方法是集合对象的内置函数,可以使用"."标记来调用: 

exists(n)     索引处的元素是否存在, 返回TRUE|FALSE
count         当前集合中的元素总个数 (count的不是占位符的个数!)
limit           集合元素索引的最大值  (索引表和嵌套表是不限个数的,所以返回null,变长数组返回定义时的最大索引 )
first / last   返回集合第一个/最后一个元素的下标
prior / next 当前元素的前一个 / 后一个元素
extend         增加元素,扩展集合的容量,不能用于索引表
  • x.extend    增加一个null元素  
  • x.extend(n)    增加n个null元素
  • x.extend(n,i)    增加n个元素,元素值与第i个元素相同
trim             从尾部删除, 不能用于索引表, 被删元素不保留占位符
  • x.trim    删除一个元素
  • x.trim(n)    删除n个元素
delete         按索引删除集合元素, 被删元素保留占位符
  • delete    删除所有
  • delete(n)    删除第n个
  • delete(a,b)    删除a--b之间的所有元素

思考:

collection.trim(1) 和 collection.delete(collection.count) 一样吗??




多层集合


元素类型为集合的集合

9i开始,可以创建多层集合,相当于其它语言中的二维数组

语法: 

        varray_name(外层下标)(内晨下标) 

例子:

1
declare
2
  type type_varry_in  is varray(4) of pls_integer;   --里面变长数组 元素类型是整形
3
  varray_in           type_varry_in := type_varry_in(1, 3, 5, 7); --里面数组赋值
4
  type type_varry_out is varray(3) of type_varry_in; --外面变长数组 元素类型是 变长数组
5
  varray_out          type_varry_out := type_varry_out(varray_in); --外面数组赋值为里面数组
6
begin
7
  varray_out.extend; --里面的数组为什么不用初始化
8
  varray_out(varray_out.count)       := type_varry_in(2, 4, 6, 8);
9
  
10
  varray_out.extend;
11
  varray_out(varray_out.count)       := type_varry_in(-1, -2, -3, -4);
12
13
  for outer in 1..varray_out.count loop
14
    for inner in 1..varray_in.count loop
15
      dbms_output.put_line('第 ' || outer || ' 行第 ' || inner || ' 列 = ' || varray_out(outer)(inner));
16
      if mod(inner,4) = 0 then dbms_output.new_line(); end if;
17
    end loop;
18
  end loop;
19
end;




集合 + 游标 = 标识多行多列数据


1
※ 例子 ※
2
declare
3
  --声明游标类型,里面放4个学生的姓名
4
  cursor cur_student is select first_name, last_name from student where rownum <= 4;
5
  type type_student  is table of cur_student%rowtype index by binary_integer; --声明索引表,里面的元素是基于上面游标的记录类型
6
  coll_student       type_student;
7
  v_idx          pls_integer := 0;  --声明做下标的变量, 别忘记初值!
8
begin
9
  for src in c_student loop  --遍历游标,把游标里的学生信息插入到集合中
10
    v_idx := v_idx + 1;
11
12
    --给集合赋值
13
    --写法1:
14
    coll_student(v_idx).first_name := src.first_name;
15
    coll_student(v_idx).last_name  := src.last_name;
16
17
    --写法2: 使用记录类型(下标) := 游标 i 直接给记录赋值, 屌屌的
18
    coll_student(v_idx) := src;
19
    dbms_output.put_line('遍历:' || coll_student(v_idx).first_name || ' - ' || coll_student(v_idx).last_name);
20
  end loop;
21
22
  --遍历集合, 注意和遍历游标的区别!
23
  --写法1: first/last方法返回集合上下标, 遇到被删除的元素会报错:找不到
24
  for i in coll_student.first .. coll_student.last LOOP --i是数值型的
25
26
  --写法2: count方法返回集合个数, 遇到被删除的元素会报错:找不到
27
  for i in 1 .. coll_student.count LOOP --i是数值型的
28
    dbms_output.put_line(coll_student(i).first_name || ' ' || coll_student(i).last_name);
29
  end loop;
30
31
end;

  注意:
          引用不存在的元素会抛出NO_DATA_FOUND异常。例如, DBMS_OUTPUT.PUT_LINE (last_name_tab(11));
原创粉丝点击