浅析oracle嵌套表!

原创 2007年09月18日 13:03:00
 浅析oracle嵌套表! /*

以前在做报表的时候会经常用到oracle的内存表(其实是oracle嵌套表的部分功能,这里在下边介绍)来提高性能。
利用oracle内存表进行临时运算通过ref cursor来返回我们想要的结果集。
open cur for select * from table(fun_to_table_rb1_1(cur_qc,cur_qm));
关于这部分的一些测试可以参看:http://www.itpub.net/showthread.php?threadid=617298

最近把oracle嵌套表的其他功能仔细看了看并做了个简单整理。

oracle提供两种使用嵌套表的方法:
1. PL/SQL代码中作为扩展PL/SQL语言;(这部分内容就是上边所说oracle内存表是oracle嵌套表的部分功能)
2. 作为物理存储机制,以持久地存储集合。

*/

--创建测试表:

CREATE TABLE dept
  (deptno NUMBER(2) PRIMARY KEY,
   dname VARCHAR2(14),
   loc VARCHAR2(13)
  );
  
CREATE TABLE emp
  (empno NUMBER(4) PRIMARY KEY,
   ename VARCHAR2(10),
   job VARCHAR2(9),
   mgr NUMBER(4) REFERENCES emp,
   hiredate DATE,
   sal NUMBER(7,2),
   comm NUMBER(7,2),
   deptno NUMBER(2) REFERENCES dept
  );
  
INSERT INTO dept SELECT * FROM scott.dept;
INSERT INTO emp SELECT * FROM scott.emp;

--创建type

CREATE OR REPLACE TYPE emp_type AS OBJECT
  (empno NUMBER(4),
   ename VARCHAR2(10),
   job VARCHAR2(9),
   mgr NUMBER(4),
   hiredate DATE,
   sal NUMBER(7,2),
   comm NUMBER(7,2)
  );
  
CREATE OR REPLACE TYPE emp_tab_type AS TABLE OF emp_type;

--使用嵌套表

CREATE TABLE dept_and_emp
  (deptno NUMBER(2) PRIMARY KEY,
   dname VARCHAR2(14),
   loc VARCHAR2(13),
   emps emp_tab_type
  )
  NESTED TABLE emps STORE AS emps_nest;

--可以在嵌套表上增加约束(这里我们先不执行此步骤,等做完下一步测试我们再创建约束)
--ALTER TABLE emps_nt ADD CONSTRAINT emps_empno_unique
--嵌套表不支持参照完整性约束,不能参考任何其他表甚至自己
--给嵌套表增加数据,我们看看这两种方式的结果有何不同
方式1:INSERT INTO
  dept_and_emp
  SELECT dept.*,
   CAST(
  MULTISET( SELECT empno, ename, job, mgr, hiredate, sal,
  comm
   FROM
  emp
   WHERE emp.deptno
  = dept.deptno ) AS emp_tab_type )
   FROM
  dept;
--Oracle同样提供方法去掉集合的嵌套,像关系型表一样处理(能够将EMPS列当作一个表,并自然连接且不需要连接条件):
SELECT d.deptno, d.dname, emp.* FROM dept_and_emp D, TABLE(d.emps) emp;
--这里执行看到结果是14条数据

delete from dept_and_emp;

方式2:INSERT INTO dept_and_emp
SELECT dept.*, CAST(MULTISET( SELECT empno, ename, job, mgr, hiredate, sal, comm
  FROM
  emp,dept
   WHERE emp.deptno
  = dept.deptno ) AS emp_tab_type ) from dept;

SELECT d.deptno, d.dname, emp.* FROM dept_and_emp D, TABLE(d.emps) emp;
--这里执行看到结果是56条数据,显然是错误的

--第一个是按照where等连接条件符合的某一个dept的emp表的数据作为一个集合存储,而第二个没有任何关联条件,就是把所有emp的数据
--全部作为一个dept的数据存储,这个写法显然是错误的,如果我们把刚才讲的约束给嵌套表加上,就可以起到防止这种错误的功效了。

--增加约束再执行我们上边的第二个insert语句将会报错
--我们按照上边第一个insert语句插入数据,继续我们下边的测试。

--按照“每行实际是一张表”的思想来更新:
UPDATE TABLE( SELECT emps FROM dept_and_emp WHERE deptno = 10) SET comm = 100;

--插入与删除的语法:
  INSERT INTO TABLE(SELECT emps FROM dept_and_emp WHERE deptno=10)
  VALUES (1234,'NewEmp','Clerk',7782,SYSDATE,1200,NULL);
  
  DELETE FROM TABLE(SELECT emps FROM dept_and_emp WHERE deptno=20)
  WHERE ename='SCOTT';

--一般而言,必须总是连接,而不能单独查询嵌套表(如emp_nest)中的数据,但是如果确实需要,是可以的。
--hint NESTED_TABLE_GET_REFS被用于EXP和IMP处理嵌套表。

  SELECT /*+NESTED_TABLE_GET_REFS+*/ NESTED_TABLE_ID, SYS_NC_ROWINFO$ FROM emps_nest;

--而察看EMPS_NEST的结构看不到NESTED_TABLE_ID,SYS_NC_ROWINFO$两列。对父表DEPT_AND_EMP来说NESTED_TABLE_ID是一个外键。
--使用这个hint就可以直接操作嵌套表了:
  UPDATE /*+NESTED_TABLE_GET_REFS+*/ emps_nest SET ename=INITCAP(ename);
  
--嵌套表的存储:
--上例中,现实产生了两张表:
/*
  DEPT_AND_EMP
  (deptnob NUMBER(2),
  dname VARCHAR2(14),
  loc VARCHAR2(13),
  SYS_NC0000400005$,
RAW(16))
  
  EMPS_NEST
  (SYS_NC_ROWINFO$,
  NESTED_TABLE_ID,
RAW(16),
  empno NUMBER(4),
  ename VARCHAR2(10),
  job VARCHAR2(9),
  mgr NUMBER(4),
  hiredate DATE,
  sal NUMBER(7,2),
  comm NUMBER(7,2)) 
*/ 
--默认情况下,每个嵌套表列都产生一个额外的RAW(16)隐藏列,并在其上创建了唯一约束,用以指向嵌套表。而嵌套表中有两个
--隐藏列:SYS_NC_ROWINFO$是作为一个对象返回所有标量元素的一个伪列;另一个NESTED_TABLE_ID的外键回指向父表。
--可以看到真实代码:
/*
  CREATE TABLE DEPT_AND_EMP
  (DEPTNO NUMBER(2,0),
   DNAME VARCHAR2(14),
   LOC VARCHAR2(13),
   EMPS EMP_TAB_TYPE)
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
  LOGGING STORAGE(INITIAL 131072 NEXT 131072
  MINEXTENTS 1 MAXEXTENTS 4096
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUP 1
  BUFFER_POOL DEFAULT)
  TABLESPACE USER
  NESTED TABLE EMPS
  STORE AS EMPS_NEST
  RETURN BY VALUE;
  
  RETURN BY VALUE用来描述嵌套表如何返回到客户应用程序中。
  NESTED_TABLE_ID列必须是索引的,那么较好的解决办法就是使用IOT存储嵌套表。
  CREATE TABLE DEPT_AND_EMP
  (DEPTNO NUMBER(2,0),
   DNAME VARCHAR2(14),
   LOC VARCHAR2(13),
   EMPS EMP_TAB_TYPE)
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
  LOGGING STORAGE(INITIAL 131072 NEXT 131072
  MINEXTENTS 1 MAXEXTENTS 4096
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUP 1
  BUFFER_POOL DEFAULT) TABLESPACE USER
  NESTED TABLE EMPS
  STORE AS EMPS_NEST
  ((empno NOT NULL,
UNIQUE(empno),
PRIMARY KEY(nested_table_id,empno))
  ORGANIZATION
  INDEX COMPRESS 1)
  RETURN BY VALUE;
  
  这样与最初默认的嵌套表相比,使用了较少的存储空间并有最需要的索引。
  不使用嵌套表作为永久存储机制的原因
  1.增加了RAW(16)列的额外开销,父表和子表都将增加这个额外的列;
  2.当通常已经有唯一约束时,父表上的唯一约束是额外开销;
  3.没有使用不支持的结构(NESTED_TABLE_GET_REFS),嵌套表不容易使用。
  一般推荐在编程结构和视图中使用嵌套表。如果要使用嵌套表作为存储机制,
确保嵌套表是IOT,以避免NESTED_TABLE_ID和嵌套表本身中索引的额外开销。

以上参考oracle高级专家编程。
*/

相关文章推荐

oracle的嵌套表

  • 2013年01月18日 13:34
  • 8KB
  • 下载

[Oracle] 第17章 集合-嵌套表

嵌套表是一种类似于索引表的结构,也可以用于保存多个数据,而且也可以保存复合类型的数据。 嵌套表指的是在一个数据表定义时同时加入其它内部表的定义,这一概念是在 。 可以使用 SQL 进行访问,也可以进行...
  • LRjava
  • LRjava
  • 2016年09月24日 14:02
  • 131

oracle 三种集合数据类型【varray,嵌套表,联合数组】+record

在oracle 11.2中,oracle总共提供了三种集合类型:varray,嵌套表,联合数组。所谓集合,简单来说就是保存多行数据的数据类型,相当于保存在内存中的小型表,便于暂时保存数据,以及数据的重...

ORACLE 集合(关联数组,嵌套表,VARRAY)

三种集合比较   元素下标 个数限制 初始化 表数据列 索引表 (binary_integer、pls_integer、varchar2) 无限制 不需要 不可以 ...

oracle 复合类型 (索引表,嵌套表,数组array)

/* 回顾oracle 复合类型 (记录和集合) *//* 1.记录是为了更方便的处理单行多列,而集合是为了更方便的处理单列多行 */-- (一 )记录/* 1. 首先创建一个简单表开始 */  cr...

oracle:变长数组varray,嵌套表,集合

创建变长数组类型 CREATE TYPE varray_type AS VARRAY(2) OF VARCHAR2(50);    这个变长数组最多可以容纳两个数据,数据的类型为 varchar...

oracle 嵌套表

转自: http://www.webjx.com/htmldata/2005-10-22/1129938613.html 嵌套表 就是表中之表;可变数组是表中之抽象类型; 嵌套表可以有效地代替多...
  • Magina3
  • Magina3
  • 2011年11月07日 17:24
  • 579

SQL-Oracle09嵌套表与可变数组

嵌套表(了解) 嵌套表:在一个表中还包含了一个子表   //------------------------------------------------------ CREATE TA...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:浅析oracle嵌套表!
举报原因:
原因补充:

(最多只允许输入30个字)