oracle集合


oracle集合

1初识集合

集合是oracle中的一种数据类型 存放一组数据类型相同的数据

集合组成

下标组成
下标的类型包含数字(整数,pls_integer,binary_integer)和字符串
值的类型可以是数据库中的所有类型(基本数据类型,记录类型(record,%rowtype),%type,集合类型)

集合三种类型

集合是一个比较广义的概念,在pl/sql中提供了3中类型的集合

索引表

  • 可以通过数字或字符串作为下标来查找其中的元素,仅在pl/sql中使用

嵌套表

  • 拥有索引表的所有特性,但是下标只能是数字类型(连续的整数)
  • 可以在plsql中使用也可以在数据库中使用

变长数组

  • 下标只能是数字类型,创建时需要指定最大长度
  • 可以在plsql中使用也可以在数据库中使用

2索引表类型

2.1语法

定义一个索引表类型
type 类型名称 is table of 元素值的数据类型 index by 下标的数据类型;

索引变量的声明
变量名 类型名;

索引变量的使用
变量名(下标);

2.2简单使用

declare 
  --定义一个索引表类型
  type itype is table of varchar2(30) index by pls_integer;
  --声明一个集合变量
  ind itype;
begin
  ind(1):='张三';
  ind(4):='李四';
  dbms_output.put_line(ind(4)||','||ind(1));
end;

输出

李四,张三

3集合的属性或方法

3.1属性或方法简单汇总

集合属性/方法 描述
first 取集合第一个元素的下标
last 取集合元素最后一个元素的下标
next(下标) 取集合当前下标的下一个元素的下标
prior(下标) 取集合当前下标的上一个元素的下标
count 取集合中元素的个数
delete 删除集合中的元素
limit 取集合最大的元素的个数(变长数组)

3.2属性或方法示例

declare
  --定义一个集合类型
  type itype is table of varchar2(30) index by varchar2(30);
  --声明一个索引表
  eng itype;
begin
  --给索引表赋值
  eng('a'):='张三';
  eng('b'):='李四';
  eng('c'):='王五';
  eng('d'):='赵六';
  --打印集合中第一个元素的下标
  dbms_output.put_line('第一个元素的下标: '||eng.first);
  --打印集合中最后一个一个元素的下标
  dbms_output.put_line('最后一个元素的下标: '||eng.last);
  --打印集合中第二个元素的下标
  dbms_output.put_line('第二个元素的下标: '||eng.next(eng.first));
  --打印集合中倒数第二个元素的下标
  dbms_output.put_line('倒数第二个元素的下标: '||eng.prior(eng.last));
  --打印集合中元素的个数
  dbms_output.put_line('元素个数: '||eng.count);
end;

输出

第一个元素的下标: a
最后一个元素的下标: d
第二个元素的下标: b
倒数第二个元素的下标: c
元素个数: 4

declare
  --定义一个集合类型
  type itype is table of varchar2(30) index by varchar2(10);
  --定义一个变量保存集合的下标
  v_ind varchar(10);
  --声明一个索引表
  eng itype;
begin
  --给索引赋值
  eng('a'):='张三';
  eng('b'):='李四';
  eng('c'):='王五';
  eng('d'):='赵六';
  
  --遍历打印集合中的元素
  --将第一个元素的下标放入变量v_ind中
  v_ind:=eng.first;
  loop
    --打印集合元素
    dbms_output.put_line(eng(v_ind));
    --判断退出条件,当下标的值等于最后一个下标的值
    exit when v_ind=eng.last;
    --循环控制语句
    v_ind:=eng.next(v_ind);
  end loop;
end;

输出:

张三
李四
王五
赵六

4bulk collect语句循环遍历

集合提供了bulk collect语句获取表中数据
通过bulk colleck语句存入集合中的元素下标从1开始并且是连续的

注意:集合下标必须数字类型

4.1语法1

select 列.. bulk collect into 集合变量 from 表 where条件

获取emp表中30部门中的员工号和姓名

declare
  --定义索引表集合存储emp表中empno和ename
  type i_empno is table of emp.empno%type index by pls_integer;
  type i_ename is table of emp.ename%type index by pls_integer;
  --定义索引变量
  eno i_empno;
  eme i_ename;
begin
  --bull collect语句获取empno和ename
  select empno,ename bulk collect into eno,eme from emp where deptno=30;
  for i in eno.first..eno.last loop
    dbms_output.put_line(eno(i)||eme(i));
  end loop;
end;

输出

7499ALLEN
7521WARD
7654MARTIN
7698BLAKE
7844TURNER
7900JAMES

4.2语法2

execute immediate 'select语句' bulk collect into 集合变量

获取emp表中30部门中的员工号和姓名

declare
  --声明一个变量存放selqct查询结果
  v_sql varchar2(255);
  --定义索引表集合存储emp表中empno和ename
  type i_empno is table of emp.empno%type index by pls_integer;
  type i_ename is table of emp.ename%type index by pls_integer;
  --定义索引变量
  eno i_empno;
  eme i_ename;
begin
  --将sql语句赋值给v_sql
  v_sql:='select empno,ename from emp where deptno=30';
  --bulk collect语句,将v_sql查询到的结果放到eno和eme中
  execute immediate v_sql bulk collect into eno,eme;
  --循环打印eno和eme中所有的数据
  for i in eno.first..eme.last loop
    dbms_output.put_line(eno(i)||eme(i));
  end loop;
end;

输出

7499ALLEN
7521WARD
7654MARTIN
7698BLAKE
7844TURNER
7900JAMES

4.3语法3

fetch 游标 bulk collect into 集合变量

获取emp表中30部门中的员工号和姓名

declare
  --声明一个游标
  cursor cur is select empno,ename from emp where deptno=30;
  --声明集合,存放empno和ename
  type i_empno is table of emp.empno%type index by pls_integer;
  type i_ename is table of emp.ename%type index by pls_integer;
  --声明索引变量
  eno i_empno;
  eme i_ename;
begin
  --打开游标
  open cur;
  --bulk collect语句,将cur查询到的结果放到eno和eme中
  fetch cur bulk collect into eno,eme;
  --关闭游标
  close cur;
  
  --循环打印出eno和eme集合中的所有数据
  for i in eno.first..eno.last loop
    dbms_output.put_line(eno(i)||','||eme(i));
  end loop;
end;

输出

7499,ALLEN
7521,WARD
7654,MARTIN
7698,BLAKE
7844,TURNER
7900,JAMES

5嵌套表

嵌套表和索引表一样都是存放一组数据类型相同的数据
它的下标只能是整数类型(下标是连续的整数)

嵌套表即可以在plsq中使用,也可以在数据库中使用
在使用前需要初始化嵌套表变量

5.1plsql中使用

语法

定义嵌套表类型

type 类型名 is table of 存储的数据的数据类型(长度);

嵌套表变量声明

变量名 嵌套表类型名;

使用
1初始化嵌套表

  --初始化一个空的嵌套表
  变量名:=嵌套表类型名();
  --初始化一个带元素的嵌套表
  变量名:=嵌套表类型名(值,值,值,..,值);

2扩展嵌套表

变量名.extend(n);

3赋值

变量名(下标):=值;

初始化一个空的嵌套表

declare
  --声明一个嵌套表类型
  type mytype is table of varchar2(20);
  --声明一个变量
  c1 mytype;
begin
  --初始化c1
  c1:=mytype();
  --打印嵌套表的元素个数
  dbms_output.put_line(c1.count);
  --将嵌套表c2扩展2个元素
  c1.extend(1);
  --打印嵌套表的个数;
  dbms_output.put_line(c1.count);
  --扩展几个元素才能添加几个
  c1(1):='A';
  c1.extend(5);
  for i in 2..6 loop
    c1(i):=chr(64+i);
  end loop;
  --遍历嵌套表
  for i in c1.first..c1.last loop
    dbms_output.put_line(c1(i));
  end loop;
end;  

输出

0
1
A
B
C
D
E
F

初始化一个带元素的嵌套表

declare
  --定义一个嵌套表
  type mytype is table of varchar(20);
  --声明一个变量
  c2 mytype;
begin
  --初始化嵌套表c1
  c2:=mytype('SMTIH','ALIEN','SCOTT','TOM');
  --打印嵌套表c2的个数
  dbms_output.put_line(c2.count);
  --扩展2个元素
  c2.extend(2);
  --打印嵌套表c2的个数
  dbms_output.put_line(c2.count);
  --再次添加一个元素
  c2(6):='张三';
  --遍历嵌套表
  for i in c2.first..c2.last loop
    dbms_output.put_line(c2(i));
  end loop;
end;

输出

4
6
SMTIH
ALIEN
SCOTT
TOM

张三

5.2数据库中使用

如果在pl/sql中使用嵌套表,那么其功能与索引表比较相似
嵌套表的一个重要的特色是支持作为数据表列 存储
因此可以将嵌套表存储在数据表中或者从数据表中取出嵌套表
这是索引表不具有的功能

为了让嵌套表类型能在数据表中使用,要求嵌套表类型必须保存到数据字典中
因此需要使用create type语句创建一个持久的嵌套表类型

创建语法

create type 类型名 is table of 元素数据类型;
create type ctype is table of varchar2(30);
declare
  --声明一个嵌套表类型变量
  c ctype;
begin
  select ename bulk collect into c from emp where deptno=10;
  for i in c.first..c.last loop
    dbms_output.put_line(c(i));
  end loop;
end;

输出

june
CLARK
KING
MILLER

5.3嵌套表类型在建表时使用

语法

create table 表名(
  列名 类型,
  嵌套表列名 嵌套表类型
)nested table 嵌套表列名 store as 表名

建表

create table x(
  id number(10),
  namelist ctype
)nested table namelist store as y;

查看表x和表y的结构

SQL> desc x;
Name     Type       Nullable Default Comments 
-------- ---------- -------- ------- -------- 
ID       NUMBER(10) Y                         
NAMELIST CTYPE      Y                         
SQL> desc y;
Name Type Nullable Default Comments 
---- ---- -------- ------- -------- 

插入数据

insert into x(id,namelist) values(10,ctype('SMITH','SCOTT','ALIEN'));

查看数据

SQL> select * from x;
         ID NAMELIST
----------- --------
         10 <Object>

这里需要使用 table的子查询
用来专门查询复杂类型,
单行单列的子查询,而且子查询的列必须是集合列

SQL> select * from table(select namelist from x where id=10);
COLUMN_VALUE
------------------------------
SMITH
SCOTT
ALIEN

6变长数组

下标同样只能是数字类型,使用前需要初始化,和扩展
变长数组类型在定义时,需要指定它的最大长度
变长数组在扩展时,不能超过最大长度

6.1在plsql代码块中使用

语法

创建语句

type 类型名 is varray(最大长度) of 元素的数据类型;

使用
1初始化

  变量名:=类型名(); --初始化一个空的变长数组
  变量名:=类型名(元素值,元素值,..);--初始化一个带元素的变长数组

2扩展

变量名.extend(n)

3赋值

变量名(n):=值

注意 : 使用在bulk collect into语句中时,不需要初始化和扩展

declare
  --定义一个类型
  type atype is varray(5) of varchar2(30);
  --声明一个变量
  a atype;
begin
  --初始化
  a:=atype();
  dbms_output.put_line(a.limit);
  --扩展
  a.extend(4);
  for i in 1..4 loop
    a(i):=chr(96+i);
  end loop;
  for i in a.first..a.last loop
    dbms_output.put_line(a(i));
  end loop;
end;

输出

5
a
b
c
d

注意 : 变长数组扩展时,不能超过最大长度

6.2在数据库中使用

创建语法

create type 类型名 is varray(长度) of 类型;

查询emp表中工资排名第5位到第14位的姓名

create type atype is varray(10) of varchar2(30);
declare
  --声明一个变长表类型变量
  a atype;
begin
  select ename bulk collect into a from 
  (select ename,row_number() over(order by sal desc 
  nulls last) ranks from emp) where ranks between 5 and 14;
  for i in a.first..a.last loop
    dbms_output.put_line(a(i));
  end loop;
end;

6.3在建表时使用

语法

create table 表名(
  变量 类型,
  变长数组列 变长数组类型
);
SQL> create table z(
  2    id number(10),
  3    namelist atype
  4  );
Table created
SQL> insert into z(id,namelist) values(10,atype('Aa','Bb','Cc','Dd'));
1 row inserted

SQL> commit;
Commit complete
SQL> select * from z;
         ID NAMELIST
----------- --------
         10 <Object>
SQL> select * from table(select namelist from z where id=10);
COLUMN_VALUE
------------------------------
Aa
Bb
Cc
Dd


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM