pl/sql集合
处理单行单列数据,可以使用标量变量;
处理单行多列的数据,可以使用pl/sql记录(%rowtype,record);
处理单列多行数据,可以使用pl/sql集合。

pl/sql集合类型是类似于高级语言数组的一种复合数据类型。
包括:嵌套表(table),数组(varray)两种。

一、嵌套表
1.定义:
嵌套表用于处理相同类型的多个数值,其中每个数值称为一个元素。
元素的个数从1开始,元素个数的多少没有限制
1.2 语法:
type type_name is table of element_type;
identifier type_name;
说明:
type_name 是用户定义类型名
element_type 是元素类型
identifier 是用户使用自定义类型定义的变量
1.3 举例:
第一个例子:1个元素的例子
declare
type type_varchar2 is table of varchar2(20);
v_type type_varchar2;
begin
v_type:=type_varchar2('A');
dbms_output.put_line('输出元素:'||v_type(1));
end;
多个元素的例子
declare
type type_varchar2 is table of varchar2(20);
v_type type_varchar2;
begin
v_type:=type_varchar2('A','adsvad','svadfvadv');
dbms_output.put_line('输出元素:'||v_type(2));
end;
总结:
给嵌套表变量赋值时必须在嵌套表类型内添加元素,元素可以是1个或者多个。
不能将元素直接赋值给嵌套表变量。
嵌套表变量只有在赋值后才能被使用,通过下标来使用嵌套表变量内的元素。
下标是元素添加到嵌套表变量内的顺序。

二、数组(varray)
1.定义
数组用于处理相同类型的多个数值,其中每个数值称为一个元素。
元素的个数从1开始,元素的最大个数是有限制的。
2.语法:
type type_name is varray(size_limite) of element_type [not null];
identifier type_name;
说明:
type_name 是用户定义类型名
varray() 是数组的关键字
size_limite 是数组的长度
element_type 是元素类型
identifier 是用户使用自定义类型定义的变量
数组和嵌套表的区别:
关键字不同:table、varray
长度限制不同:table没有长度限制、varray有长度限制
3.举例
declare
type type_arr_varchar2 is varray(10) of varchar2(20);
v_arr type_arr_varchar2;
begin
v_arr:=type_arr_varchar2('张三','李四');
dbms_output.put_line('输出元素:'||v_arr(1));
dbms_output.put_line('输出元素:'||v_arr(2));
end;
用查询赋值:
declare
type type_arr_ename is varray(20) of emp.ename%type;
v_arr type_arr_ename:=type_arr_ename('');
begin
select ename into v_arr(1) from emp where empno=&no;
dbms_output.put_line('雇员名:'||v_arr(1));
end;
说明:
table和varray的功能是相同的,都可以用来存储相同类型的多个数值;
table和varray的使用方法是相同的,都需要先定义类型,再定义变量,
再将元素添加的变量中,最后通过下标来使用元素。
table和varray的属性是相同的。

三、集合属性
集合属性是数据库提供给用户的操作集合的方法(函数和过程),
过程包括:extend,trim,delete
函数包括:exists,count,limit,first,last,prior,next。
集合方法只能在pl/sql语句中使用,不能在sql语句中使用。
1.extend:
用于扩展集合变量的尺寸,并为它们增加元素。
集合变量的初始化:
通过集合类型构造函数可以给集合变量的初始化(给集合变量分配了大块的内存空间)。
extend是在给集合变量分配的大块内存空间内给元素分配小块的内存空间。
三种调用格式:
extend 分配一个元素的内存空间
extend(n) 分配n个元素的内存空间
extend(n,i) 分配n个元素的内存空间,并且用第i个元素给这n个元素赋初始值

第一个例子可以改写为下面的通用方式。
declare
type type_varchar2 is table of varchar2(20);
v_type type_varchar2:=type_varchar2();
begin
v_type.extend;
v_type(1):='A';
dbms_output.put_line('输出元素:'||v_type(1));
end;

table语法改良:
type type_name is table of element_type;
identifier type_name:=type_name();
varray语法改良:
type type_name is varray(size_limite) of element_type [not null];
identifier type_name:=type_name();

例1:extend用于table
declare
type type_tab_ename is table of emp.ename%type;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select ename from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
end;

例2:extend(n)用于varray
select count(1) from emp;
declare
type type_arr_ename is varray(16) of emp.ename%type;
v_arr type_arr_ename:=type_arr_ename();
v_cnt number:=1;
begin
v_arr.extend(16);
for rs in (select ename from emp) loop
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
end;
例3:extend(n,i)用于varray,且i元素必须已经存在
declare
type ename_table_type is varray(20) of varchar2(10);
ename_table ename_table_type;
begin
ename_table:=ename_table_type('mary');
ename_table.extend(5,1);
dbms_output.put_line('元素个数:'||ename_table.count);
for i in 1..ename_table.count loop
dbms_output.put_line('元素'||i||':'||ename_table(i));
end loop;
end;

2.trim:用于从集合尾部删除元素,
有两种调用格式:
trim :删除最后一个元素
trim(n):删除最后n个元素
适用于嵌套表和varray
declare
type ename_table_type is table of varchar2(10);
ename_table ename_table_type;
begin
ename_table:=ename_table_type('a','b','c','d','e');
ename_table.trim(2);
dbms_output.put_line('元素个数:'||ename_table.count);
end;

3.delete:删除指定元素,
有三种调用方式:
delete 删除全部元素
delete(n) 删除第n个元素(删除1个元素)
delete(m,n) 删除集合变量从m到n之间的所有元素
只适用于嵌套表,delete(n)\delete(m,n)不适用于varray。
例1:delete 删除第n个元素
declare
type type_tab_ename is table of emp.ename%type;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select ename from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
dbms_output.put_line('元素个数:'||v_arr.count);
v_arr.delete;
dbms_output.put_line('元素个数:'||v_arr.count);
end;
例1-2:varray
declare
type type_tab_ename is varray(16) of emp.ename%type;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select ename from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
dbms_output.put_line('元素个数:'||v_arr.count);
v_arr.delete;
dbms_output.put_line('元素个数:'||v_arr.count);
end;
例2:delete(n) 删除第n个元素
declare
type type_tab_ename is table of emp.ename%type;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select ename from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
dbms_output.put_line('元素个数:'||v_arr.count);
v_cnt:=v_arr.count;
v_arr.delete(5);
dbms_output.put_line('元素个数:'||v_arr.count);
for i in 1..v_cnt loop
if i=5 then
continue;
end if;
dbms_output.put_line('元素'||i||':'||v_arr(i));
end loop;
end;

例3:delete(m,n) 删除集合变量从m到n之间的所有元素
declare
type type_tab_ename is table of emp.ename%type;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select ename from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs.ename;
dbms_output.put_line('雇员名:'||v_arr(v_cnt));
v_cnt:=v_cnt+1;
end loop;
dbms_output.put_line('元素个数:'||v_arr.count);
v_cnt:=v_arr.count;
v_arr.delete(5,10);
dbms_output.put_line('元素个数:'||v_arr.count);
for i in 1..v_cnt loop
if i>=5 and i<=10 then
continue;
end if;
dbms_output.put_line('元素'||i||':'||v_arr(i));
end loop;
end;

4.exists:用于确定集合元素是否存在
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type:=ename_table_type();
begin
if ename_table.exists(1) then
ename_table(1):='scott';
dbms_output.put_line('元素:'||ename_table(1));
else
dbms_output.put_line('必须初始化集合元素');
end if;
end;

5.count:用于返回当前集合变量中的元素总个数.

6.limit:用于返回集合元素的最大个数.
嵌套表元素个数没有限制,无返回值
varray元素个数在定义时设置,返回varray所允许的最大元素个数
declare
type ename_table_type is varray(20) of emp.ename%type;
ename_table ename_table_type:=ename_table_type();
begin
dbms_output.put_line('集合元素的最大个数:'||ename_table.limit);
end;
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type:=ename_table_type();
begin
dbms_output.put_line('集合元素的最大个数:'||ename_table.limit);
end;

7.first和last:
first 用于返回集合变量第一个元素的下标,
last 用于返回集合变量最后一个元素的下标
declare
type ename_table_type is varray(10) of emp.ename%type;
ename_table ename_table_type:=ename_table_type('scott','smith','mary','blake');
begin
dbms_output.put_line('第一个元素的下标:'||ename_table.first);
dbms_output.put_line('最后一个元素的下标:'||ename_table.last);
dbms_output.put_line('第一个元素:'||ename_table(ename_table.first));
dbms_output.put_line('最后一个元素:'||ename_table(ename_table.last));
end;

8.prior和next:
prior 用于返回当前集合元素的前一个元素的下标,
next 用于返回当前集合元素的后一个元素的下标
declare
type ename_table_type is varray(10) of emp.ename%type;
ename_table ename_table_type:=ename_table_type('scott','smith','mary','blake');
begin
dbms_output.put_line('当前元素:'||ename_table(2));
dbms_output.put_line('当前元素的前一个元素的下标:'||ename_table.prior(2));
dbms_output.put_line('当前元素的后一个元素的下标:'||ename_table.next(2));
dbms_output.put_line('当前元素的前一个元素:'||ename_table(ename_table.prior(2)));
dbms_output.put_line('当前元素的后一个元素:'||ename_table(ename_table.next(2)));
end;

处理单行单列数据,可以使用标量变量(varchar2、number、date、boolean);
处理单行多列的数据,可以使用pl/sql记录(%rowtype,record);
处理单列多行数据,可以使用pl/sql集合(table、varray);
那么处理多列多行数据,怎么办呢?

四、集合类型的嵌套(联合)
1.table和%rowtype的联合
declare
type type_tab_ename is table of emp%rowtype;
v_arr type_tab_ename:=type_tab_ename();
v_cnt number:=1;
begin
for rs in (select * from emp) loop
v_arr.extend;
v_arr(v_cnt):=rs;
dbms_output.put_line('雇员名:'||v_arr(v_cnt).ename);
v_cnt:=v_cnt+1;
end loop;
end;

2.二维数组 varray和varray的嵌套
declare
type d1_varray_type is varray(10) of number;--定义一维VARRAY
type nd1_varray_type is varray(5) of d1_varray_type;--定义二维VARRAY集合
--初始化二维集合变量
v_arr nd1_varray_type:=nd1_varray_type(
d1_varray_type(2,4),
d1_varray_type(5,73));
begin
dbms_output.put_line('显示二维数组所有元素');
for i in 1..v_arr.count loop
for j in 1..v_arr(i).count loop
dbms_output.put_line('v_arr('||i||','||j||')='||v_arr(i)(j));
end loop;
end loop;
end;

(2,4)
(5,73)

如果多维集合的元素个数没有限制,那么可以在嵌套表类型中嵌套另一个嵌套表类型
3.二维嵌套表 table和table的嵌套
declare
type d1_table_type is table of number;--定义一维嵌套表
type nd1_table_type is table of d1_table_type;--定义二维嵌套表集合
--初始化二维集合变量
v_tab nd1_table_type:=nd1_table_type(
d1_table_type(58,100,102),
d1_table_type(55,6),
d1_table_type(2));
begin
dbms_output.put_line('显示二维数组所有元素');
for i in 1..v_tab.count loop
for j in 1..v_tab(i).count loop
dbms_output.put_line('v_tab('||i||','||j||')='||v_tab(i)(j));
end loop;
end loop;
end;

五、集合间的赋值:=
1.赋值符:=
将一个集合的数据赋值个另一个集合
源集合和目标集合的数据类型必须完全一致.
declare
type name_varray_type is varray(4) of varchar2(10);
name_array1 name_varray_type;
name_array2 name_varray_type;
begin
name_array1:=name_varray_type('scott','smith');
name_array2:=name_varray_type('a','a','a','a');
dbms_output.put_line('name_array2的原数据:');
for i in 1..name_array2.count loop
dbms_output.put(' '||name_array2(i));
end loop;
dbms_output.new_line;
name_array2:=name_array1; --用:=符号赋值
dbms_output.put_line('name_array2的新数据:');
for i in 1..name_array2.count loop
dbms_output.put(' '||name_array2(i));
end loop;
dbms_output.new_line;
end;

2.给集合赋NULL值:
清空集合变量的所有数据(集合方法DETELE,TRIM也可以)
declare
type name_varray_type is varray(4) of varchar2(10);
name_array name_varray_type;
name_empty name_varray_type;
begin
name_array:=name_varray_type('scott','smith');
dbms_output.put_line('name_array的原有元素个数:'||name_array.count);
name_array:=name_empty;
if name_array is null then
dbms_output.put_line('name_array的现有元素个数:0');
end if;
end;

六、嵌套表特有操作:
set:用于取消嵌套表中的重复值.
multiset union:用于取得两个嵌套表的并集(可重)
multiset union distinct:用于取得两个嵌套表的并集(distinct)。
multiset intersect:用于取得两个嵌套表的交集.
nultiset except:用于取得两个嵌套表的差集
1.set:
用于取消特定嵌套表中的重复值.
declare
type nt_table_type is table of number;
v_tab nt_table_type:=nt_table_type(2,4,3,1,2);
r_tab nt_table_type;
begin
r_tab:=set(v_tab);
for i in 1..r_tab.count loop
dbms_output.put_line('r_tab'||i||':'||r_tab(i));
end loop;
end;

2.multiset union:
用于获取两个嵌套表的并集。
两个嵌套表都有的元素在结果集中会重复。
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset union nt2;
for i in 1..result.count loop
dbms_output.put_line('result'||i||':'||result(i));
end loop;
end;
3.multiset union distinct:
用于获取两个嵌套表的并集。
两个嵌套表都有的元素在结果集中不会重复。
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset union distinct nt2;
for i in 1..result.count loop
dbms_output.put_line('result'||i||':'||result(i));
end loop;
end;
4.multiset intersect
用于获取两个嵌套表的交集
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset intersect nt2;
for i in 1..result.count loop
dbms_output.put_line('result'||i||':'||result(i));
end loop;
end;
5.multiset except
用于获取两个嵌套表的差集。
即在第一个嵌套表中存在,但在第二个嵌套表不存在的元素。
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset except nt2;
for i in 1..result.count loop
dbms_output.put_line('result'||i||':'||result(i));
end loop;
end;

操作符is empty: 用于检测嵌套表是否为null。
操作符=和!=: 用于检测两个嵌套表是否相同。
函数cardinality:用于返回嵌套表变量的元素个数
submultiset of: 用于确定一个嵌套表是否为另一个嵌套表的子集
操作符member of:用于检测特定数据是否为嵌套表元素
操作符is a set: 用于检测嵌套表是否包含重复的元素值
6.is empty:
用于检测嵌套表是否为null。
即检测嵌套表是否没有元素。
declare
type name_table_type is table of varchar2(10);
name_table name_table_type:=name_table_type();
begin
if name_table is empty then
dbms_output.put_line('嵌套表为空');
else
dbms_output.put_line('嵌套表中有元素');
end if;
end;
7.=和!=
用于检测两个嵌套表是否相同。
declare
type name_table_type is table of varchar2(10);
name_table1 name_table_type;
name_table2 name_table_type;
begin
name_table1:=name_table_type('scott');
name_table2:=name_table_type('smith');
if name_table1=name_table2 then
dbms_output.put_line('两个嵌套表完全相同');
else
dbms_output.put_line('两个嵌套表数值不同');
end if;
end;
8.cardinality
用于返回嵌套表中的元素个数。
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,1);
begin
dbms_output.put_line('元素个数:'||cardinality(nt1));
end;
9.submultiset of
用于确定一个嵌套表是否为另一个嵌套表的子集.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(1,2,3,4);
begin
if nt1 submultiset of nt2 then
dbms_output.put_line('nt1是nt2的子集');
end if;
end;
10.member of
用于检测特定数据是否为嵌套表的元素.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,4);
v1 number:=&v1;
begin
if v1 member of nt1 then
dbms_output.put_line(v1||'是嵌套表nt1的元素');
else
dbms_output.put_line(v1||'不是嵌套表nt1的元素');
end if;
end;
11.is a set
用于检测嵌套表是否包含重复的元素值
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,5);
begin
if nt1 is a set then
dbms_output.put_line('嵌套表无重复值');
else
dbms_output.put_line('嵌套表有重复值');
end if;
end;

七、作业
1.做一个split函数,功能如下:
输入'张三、李四、王五'
调用函数时输出多行,显示如下:
create or replace type type_table_varchar2 is table of varchar2(20);
create or replace function split(p_var varchar2,p_fengefu varchar2) return type_table_varchar2
is
v_rs type_table_varchar2:=type_table_varchar2();
begin
XXXX
return v_rs;
end;

select column_value from table(split('张三、李四、王五','、'));
张三
李四
王五
2.做一个匿名块,对数组进行排序,并显示排序后的元素。比如:
排序前数组元素顺序为:13 25 7 18 2 6 9 12
排序后数组元素顺序为:2 6 7 9 12 13 18 25

Oracle_PL/SQL(7) 集合的更多相关文章

  1. SQL进阶系列之7用SQL进行集合运算

    写在前面 集合论是SQL语言的根基,因为这种特性,SQL也被称为面向集合语言 导入篇:集合运算的几个注意事项 注意事项1:SQL能操作具有重复行的集合(multiset.bag),可以通过可选项ALL ...

  2. SQL的集合运算符介绍

    最近学习了SQL SERVER方面的知识,毕竟做Web应用,少不了跟数据库打交道.学习的来源主要是<程序员的SQL金典>这本书. 今天介绍数据库里面的集合运算符,它是指匹配集合的每一个结果 ...

  3. sql的集合操作

    原文转自:http://blog.csdn.net/qsyzb/article/details/12560917 SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作. ...

  4. PL/SQL 记录集合IS TABLE OF的使用

    在PL/SQL代码块中使用select into 赋值的话,有可能返回的是一个结果集.此时,如果使用基本类型或自定义的记录类型,将会报错. 因此,需要定义一个变量,是某种类型的集合.下面以一个基于表的 ...

  5. Oracle_PL/SQL(9) 例外处理

    例外处理1.例外分类:预定义例外,非预定义例外,自定义例外三种传递例外:如果在例外处理部分exception没有捕捉例外,oracle会将例外传递到调用环境.捕捉并处理例外:使用例外处理部分完成exc ...

  6. Oracle_PL/SQL(8) 动态sql

    动态sql0.pl/sql块的限制 不能执行ddl操作(create.drop.alter): 不能执行部分dcl操作(grant.revoke). 1.语法动态sql:在执行时才能确定要执行的sql ...

  7. Oracle_PL/SQL(6) 触发器(序列、视图)

    序列1.创建序列create sequence seq_alog start with 1 increment by 1 maxvalue 999999999999999999999999999 mi ...

  8. 用python(2.7)自定义实现SQL的集合操作

    有的时候需要在不同的数据库实例之间做集合操作,这就无法直接使用SQL语句的join,left join了.相同类型的数据库之间虽然也有类似于DBLINK和FEDERATED之类的东西,但一来这些东西不 ...

  9. SQL 语句集合

    创建数据库 创建之前判断该数据库是否存在 if exists (select * from sysdatabases where name='databaseName') drop database ...

随机推荐

  1. 7.mysql-安装和卸载.md

    目录 卸载 停止window的MySQL服务. 卸载MySQL安装程序.找到"控制面板"-> "程序和功能",卸载MySQL程序. 安装 MYSQL的安装 ...

  2. mysql 回顾

    主键可以是一个或者是多个列,但所有的列(或者是列的组合)必须是唯一的,非空的 关键字distinct 可以去重,实现该效果还可以使用group by limit 默认从 0 开始,limit 5 其实 ...

  3. python抽象方法

    1.抽象方法的概念 之前我们定义一个基类的时候,如果要求子类必须重写父类中的某一个方法,可以这样做: 定义一个名为Pizza的基类,让其get_radius方法必须被子类继承 class Pizza( ...

  4. mysql 查询上个月某一天

    本文地址:http://www.cnblogs.com/jying/p/8877065.html 需求:获取上个月15号的日期 网上一搜一大堆粘贴复制的大坑:(如下是查询上个月最后一天,可是我要的不一 ...

  5. python opencv3 给图片加中文

    转自:https://www.cnblogs.com/arkenstone/p/6961453.html opencv3.2将中文输出到图片上 opencv自带的putText函数无法输出utf8类型 ...

  6. JS----click3种方法

    js最常用的click事件3种方法 1.onclick=name() <!DOCTYPE html> <html leng="en"> <head&g ...

  7. TF-IDF原理及使用

    1.TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率).(逆文档词频) 2.自我理解: 公式TF = $$\frac{语料库中关键词 ...

  8. pandas.DataFrame.to_excel

    1. file_name = 'aa.xlsx' df.to_excel(file_name) #这种file_name不能重复,已经生成过的就会报错 writer = pd.ExcelWriter( ...

  9. 04_web基础(二)之web构建

    03.04.05.06web项目创建 07.第一个Servlet程序 1.拷贝tomcat 中的 servlet-api.jar 在lib包下面 2.新建一个HelloWordServlet类并实现 ...

  10. java课后作业总结

    今天的课后作业是做一个查找一段文章中单词出现的概率,统计并 输出出现概率最高的几个单词.拿到题目,老师还是往常一样提醒着我们先分析题目,构建大概的编程思路.程序需要遇到文本文件的输入输出操作,这一直一 ...