Oracle外部表 索引表 嵌套表
- 格式:docx
- 大小:20.91 KB
- 文档页数:5
NavicatforOracle外部表知识点总结优选版Navicat for Oracle 外部表知识点总结Navicat for Oracle 外部表访问在外部源的数据,本教程由navicat官网提供,将详解Navicat for Oracle 外部表外部属性、访问参数以及索引组织表。
Navicat for OracleOracle 外部表外部属性默认目录:指定外部表的默认目录。
目录:设置外部目录。
位置:设置外部源位置。
访问驱动程序:设定外部表的访问驱动程序,外部表的默认类型是ORACLE_LOADER。
否决限制:指定在外部数据查询中可以出现错误数的限制。
与度数并行:勾选此项,可在数据源启用并行查询及指定并行访问的度数。
Oracle 外部表访问参数描述外部数据到Oracle 数据库数据列的对应。
使用CLOB:勾选此项,得到返回查询的CLOB 数据值。
Oracle 索引组织表索引组织表是一个基本的B-tree 变体的保存组织,索引组织表的数据保存在用主键排序方式的B-tree 索引结构。
在索引结构中的每一个枝节块保存键和非键列。
索引组织表有完整表的功能,支持的功能有限制、触发器等,额外功能有键压缩。
需要注意的是,索引组织表和常规表的表设计器只是“选项”选项卡不同。
第一章 实数考点一、实数的概念及分类 (3分)1、实数的分类正有理数有理数 零 有限小数和无限循环小数 实数 负有理数 正无理数无理数 无限不循环小数 负无理数整数包括正整数、零、负整数。
正整数又叫自然数。
正整数、零、负整数、正分数、负分数统称为有理数。
2、无理数在理解无理数时,要抓住“无限不循环”这一点,归纳起来有四类: (1)开方开不尽的数,如32,7等;(2)有特定意义的数,如圆周率π,或化简后含有π的数,如3π+8等;…等;(4)某些三角函数,如sin60o 等(这类在初三会出现) 考点二、实数的倒数、相反数和绝对值1、相反数实数与它的相反数是一对数(只有符号不同的两个数叫做互为相反数,零的相反数是零),从数轴上看,互为相反数的两个数所对应的点关于原点对称,如果a 与b 互为相反数,则有a+b=0,a=-b ,反之亦成立。
oracle三种表连接⽅式
1、排序合并连接(Sort Merge Join)
排序合并连接的执⾏过程如下所⽰:
* 将每个⾏源的⾏按连接谓词列排序
* 然后合并两个已排序的⾏源,并返回⽣成的⾏源
例如:
select * from employees d,departments t where d.department_id=t.department_id;
访问机制如下:访问departments表并排序department_id列,访问employees表并排序department_id列,然后依次交替⽐较、归并。
注意:排序合并连接⼀般⽤在两张表中没有索引,并且连接列已经排好序的情况下。
2、嵌套循环连接(Nested Loops Join)
* 两个表中的⼀个被定义为“外部表”(或“驱动表”)
* 另⼀个表被称为“内部表”
* 将针对外部表中的每⼀⾏检索内部表中所有匹配的⾏
注意:join的顺序很重要,⼀般选择⼩表作为“驱动表”,⼤表作为“内部表”。
如两个表,⼀个100⾏,⼀个10000⾏,理想的连接⽅式是:100⾏的⼩表作为“驱动表”,10000⾏的⼤表作为“内部表”,⽤⼩表中的每条记录去匹配⼤表中的记录。
如果两张表的连接词在⼤表中是索引列,则是最完美的。
3、哈希连接(Hash Join)
* 优化器对⼩表利⽤连接键在内存中建⽴hash表
* 扫描⼤表,每得到⼀条记录,就来hash表中“探测”⼀次,找出与hash表匹配的⾏
注意:Hash Join 是CBO做⼤数据集连接时的常⽤⽅式。
1.1.1嵌套循环连接在嵌套循环连接中,Oracle从第一个行源中读取第一行,然后和第二个行源中的数据进行对比。
所有匹配的记录放在结果集中,然后Oracle将读取第一个行源中的下一行。
按这种方式直至第一个数据源中的所在行都经过处理。
第一个记录源通常称为外部表,或者驱动表,相应的第二个行源称为内部表。
使用嵌套循环连接是一种从连接结果中提取第一批记录的最快速的方法。
在驱动行源表(就是您正在查找的记录)较小、或者内部行源表已连接的列有惟一的索引或高度可选的非惟一索引时, 嵌套循环连接效果是比较理想的。
嵌套循环连接比其他连接方法有优势,它可以快速地从结果集中提取第一批记录,而不用等待整个结果集完全确定下来。
这样,在理想情况下,终端用户就可以通过查询屏幕查看第一批记录,而在同时读取其他记录。
不管如何定义连接的条件或者模式,任何两行记录源可以使用嵌套循环连接,所以嵌套循环连接是非常灵活的。
然而,如果内部行源表(读取的第二张表)已连接的列上不包含索引,或者索引不是高度可选时, 嵌套循环连接效率是很低的。
如果驱动行源表(从驱动表中提取的记录)非常庞大时,其他的连接方法可能更加有效。
图1-1说明了程序清单1-1中查询执行的方法。
select /*+ordered*/ename,dept.deptnofrom dept,empwhere dept.deptno=emp.deptno1.1.2排列合并连接在排列合并连接中,Oracle分别将第一个源表、第二个源表按它们各自要连接的列排序,然后将两个已经排序的源表合并。
如果找到匹配的数据,就放到结果集中。
在缺乏数据的选择性或者可用的索引时,或者两个源表都过于庞大(超过记录数的5%)时,排序合并连接将比嵌套循环连更加高效。
但是,排列合并连接只能用于等价连接(WHERE D.deptno=E.dejptno,而不是WHERE D.deptno>=E.deptno)。
排列合并连接需要临时的内存块,以用于排序(如果SORT_AREA_SIZE设置得太小的话)。
Oracle中表的连接及其调整只有对这些问题有了清晰的理解后,我们才能针对特定的查询需求选择合适的连接方式,开发出健壮的数据库应用程序。
选择合适的表连接方法对SQL语句运行的性能有着至关重要的影响。
下面我们就Oracle常用的一些连接方法及适用情景做一个简单的介绍。
常用的表连接方式:a.嵌套循环连接(Nested Loop)b.排序合并连接(Sort Merge)c. 哈希连接(Hash join)一、嵌套循环连接(Nested Loop)嵌套循环连接的工作方式是这样的:1、Oracle首先选择一张表作为连接的驱动表,这张表也称为外部表(Outer Table)。
由驱动表进行驱动连接的表或数据源称为内部表(Inner Table)。
2、提取驱动表中符合条件的记录,与被驱动表的连接列进行关联查询符合条件的记录。
在这个过程中,Oracle首先提取驱动表中符合条件的第一条记录,再与内部表的连接列进行关联查询相应的记录行。
在关联查询的过程中,Oracle 会持续提取驱动表中其他符合条件的记录与内部表关联查询。
这两个过程是并行进行的,因此嵌套循环连接返回前几条记录的速度是非常快的。
在这里需要说明的是,由于Oracle最小的IO单位为单个数据块,因此在这个过程中Oracle会首先提取驱动表中符合条件的单个数据块中的所有行,再与内部表进行关联连接查询的,然后提取下一个数据块中的记录持续地循环连接下去。
当然,如果单行记录跨越多个数据块的话,就是一次单条记录进行关联查询的。
3、嵌套循环连接的过程如下所示:我们可以看出这里面存在着两个循环,一个是外部循环,提取驱动表中符合条件的每条记录。
另外一个是内部循环,根据外循环中提取的每条记录对内部表进行连接查询相应的记录。
由于这两个循环是嵌套进行的,故此种连接方法称为嵌套循环连接。
嵌套循环连接适用于查询的选择性强、约束性高并且仅返回小部分记录的结果集。
通常要求驱动表的记录(符合条件的记录,通常通过高效的索引访问)较少,且被驱动表连接列有唯一索引或者选择性强的非唯一索引时,嵌套循环连接的效率是比较高的。
OraclePLSQL嵌套表的使⽤PL/SQL当中有⼀个常⽤的容器,nested Table,在项⽬开发中,需要借⽤容器来实现⼀些计算操作,PL/SQL并不想其他语⾔当中有⼀些数组等⽐较容易使⽤的容器,在此整理⼀下nested tables⼀些常⽤的操作。
⼀、简介netsted tables 可以看成⼀个变长数组,可以存放任意数量的元素(只要内存⾜够⼤),通过下标来实现对元素的访问,nested tables 有点是可以在SQL中直接使⽤。
nested table 内存存储模型nested tables 为了提⾼删除元素的效率,元素删除后并不移动后续的元素,从图中可以看nested tables 的下标是从1开始的,这点跟其它语⾔的数组或者容器有些区别。
(1)定义。
TYPE tb_table IS TABLE OF VARCHAR2(100) ; --定义⼀个嵌套表格类型存储字符型数据tb_instance tb_table:=tb_table(); -- 采⽤上⾯定义的类型顶⼀个⼀个对象。
(2)添加元素tb_instance.extend(1);--在末尾扩充⼀个元素tb_instance(tb_st):=i; --为末尾的元素赋值(3) 删除元素tb_instance.delete(index); --删除元素(4)迭代器由于nested tables 元素的删除仅仅是留下⼀个空槽,元素遍历时我们要跳过这些空槽,nested table有以下的属性来访问存在的元素Fist : 第⼀个存在的元素下标Last: 最后⼀个存在的元素下标exists(index): 判断下标index的元素是否存在NEXT(index): 获取 index下标后存在元素的下标,如果index是最后⼀个元素,则返回NULLPRIOR(index): 获取 index下标前⾯存在元素的下标,如果index是第⼀个元素,则返回NULL以上操作属性⽅法的存在可以让我们实现对Nested tables 的遍历了⽰例代码如下:DECLARE-- Local variables herei INTEGER;counter INTEGER;TYPE tb_table IS TABLE OF VARCHAR2(100);tb_instance tb_table := tb_table();PROCEDURE log(l VARCHAR2) ISBEGINdbms_output.put_line(l);END;PROCEDURE remove_depulate(p_tb_instance IN OUT tb_table) ISi INTEGER;j INTEGER;BEGINi := p_tb_instance.first;WHILE i IS NOT NULL LOOPj := p_tb_instance.next(i);WHILE j IS NOT NULL LOOPIF p_tb_instance(i) = p_tb_instance(j) THENp_tb_instance.delete(i);EXIT;END IF;j := p_tb_instance.next(j);END LOOP;i := p_tb_instance.next(i);END LOOP;END;BEGINFOR i IN1 .. 10 LOOP --每个元素增加两次tb_instance.extend(1); tb_instance.extend(1);tb_instance(tb_st) := i;log('last:'|| tb_st);tb_instance(tb_st) := i;END LOOP;remove_depulate(tb_instance); --去掉容器中重复的元素log('-------------------------------------------------------');counter := tb_instance.first; --通过属性⽅法遍历容器当中的元素WHILE counter IS NOT NULL LOOPdbms_output.put_line('Element #'|| counter ||' = '|| tb_instance(counter));counter := tb_instance.next(counter);END LOOP;END;上⾯的代码使⽤到了容器的增加,删除,遍历操作,修改操作直接通过下标访问修改就OK了。
Oracle之外部表有时候,数据库海量数据的存储,是一个令人头疼的问题。
别的不说,光是频繁的执行insert(1000次/秒)都是一场恶梦。
但是,如果将数据保存到文家里,而不是数据库中,数据序列化的开销就小得多了。
但是,对于文件的各种复杂检索,又是一件相当麻烦的事。
幸好,Oracle有这样一种特性,它可以将某些特定格式的文件映射到数据库中,形成一个“表”,称为“外部表”。
单用户更改文件内容时,外部表中的数据即随之改变。
同时,用户又可以像检索普通表一样,以只读的方式对外部表进行检索。
我们假设有这样一个文件(DATA.TXT):1|this is a string2|这里是个字符串3|ABC要把这样一个文件映射成外部表,有以下工作要做:首先,我们需要为Oracle创建一个Directory,创建方式为,在数据库中执行,须用DBA用户创建,并给应用授权。
create directory EXT_TABLE_DIR as '/home/oracle/app/oracle/oradata/php/'注意“/home/oracle/app/oracle/oradata/php/”是一个存在于Oracle数据库服务器本身上边的实际存在的文件夹;然后,将DA TA.TXT文件拷贝到上述文件夹下;最后,创建一个对应外部表,create table EXT_TABLE_NAME(COL_1 NUMBER,COL_2 V ARCHAR2(512))organization external(type oracle_loaderdefault directory EXT_TABLE_DIRaccess parameters ( fields terminated by '|' )location ('DATA.TXT'))reject limit unlimited;注意蓝色部分,EXT_TABLE_NAME是要映射成的外部表名称,EXT_TABLE_DIR是第一步里我们创建的Oracle的Directory,“|”是文件里的分割符,DA TA.TXT是文件名。
Oracle嵌套表的使用一、嵌套表的定义:嵌套表是表中之表。
一个嵌套表是某些行的集合,它在主表中表示为其中的一列。
对主表中的每一条记录,嵌套表可以包含多个行。
在某种意义上,它是在一个表中存储一对多关系的一种方法。
考察一个包含部门信息的表,在任何时间每个部门会有很多工程正在实施。
在一个严格的关系模型中,将需要建立两个独立的表department和project。
嵌套表允许在department表中存放关于工程的信息。
勿需执行联合操作,就可以通过department表直接访问工程表中的记录。
这种不经联合而直接选择数据的能力使得用户对数据访问更加容易。
甚至在并没有定义方法来访问嵌套表的情况下,也能够很清楚地把部门和工程中的数据联系在一起。
在严格的关系模型中,department和project两个表的联系需要通过外部关键字〔外键〕关系才能实现。
二、举例说明嵌套表的使用:假设有一个关于动物饲养员的表,希望其中具有他们饲养的动物的信息。
用一个嵌套表,就可以在同一个表中存储饲养员和其饲养的全部动物的信息。
1、创立类型animal_ty:此类型中,对于每个动物都包含有一个记录,记载了其品种、名称和出生日期信息。
CREATE TYPE animal_ty AS OBJECT (breed varchar2(25),name varchar2(25),birthdate date);2、创立animals_nt:此类型将用作一个嵌套表的根底类型。
CREATE TYPE animals_nt as table of animal_ty;3、创立表breeder:饲养员的信息表create table breeder(breedername varchar2(25),animals animal_nt)nested table animals store as animals_nt_tab;4、向嵌套表中插入记录insert into breedervalues('mary',animal_nt(animal_ty('dog','butch','31-MAR-97'), animal_ty('dog','rover','31-MAR-97'),animal_ty('dog','julio','31-MAR-97')));insert into breedervalues('jane',animal_nt(animal_ty('cat','an','31-MAR-97'),animal_ty('cat','jame','31-MAR-97'),animal_ty('cat','killer','31-MAR-97')));commit;5、查询嵌套表select name,birthdate fromtable(select animals from breeder);select name,birthdate fromtable(select animals from breederwhere breedername=’mary’)where name=’dog’;三、嵌套表的特点:1、对象复用:如果编写面向对象的代码,就提高了重用以前编写的代码模块的时机。
Oracle外部表External Table Example The following statement creates an external table that represents a subset of the sample table hr.departments. The opaque_format_ spec is shown in italics. Please refer to Oracle Database Utilities for information on the ORACLE_LOADER access driver and how to specify values for the opaque_format_ spec.CREATE TABLE dept_external (deptno NUMBER(6),dname VARCHAR2(20),loc VARCHAR2(25))ORGANIZATION EXTERNAL(TYPE oracle_loaderDEFAULT DIRECTORY adminACCESS PARAMETERS(RECORDS DELIMITED BY newlineBADFILE 'ulcase1.bad'DISCARDFILE 'ulcase1.dis'LOGFILE 'ulcase1.log'SKIP 20FIELDS TERMINATED BY "," OPTIONALLY ENCLOSED BY '"'(deptno INTEGER EXTERNAL(6),dname CHAR(20),loc CHAR(25)))LOCATION ('ulcase1.ctl'))REJECT LIMIT UNLIMITED;Index-Organized Table Example The following statement is a variation of the sample table hr.countries, which is index organized:CREATE TABLE countries_demo( country_id CHAR(2)CONSTRAINT country_id_nn_demo NOT NULL, country_nameVARCHAR2(40), currency_nameVARCHAR2(25), currency_symbolVARCHAR2(3), region VARCHAR2(15), CONSTRAINT country_c_id_pk_demoPRIMARY KEY (country_id ) )ORGANIZATION INDEXINCLUDING country_namePCTTHRESHOLD 2STORAGE( INITIAL 4KNEXT 2KPCTINCREASE 0MINEXTENTS 1MAXEXTENTS 1 )OVERFLOWSTORAGE( INITIAL 4KNEXT 2KPCTINCREASE 0MINEXTENTS 1MAXEXTENTS 1 );Nested Table Example The following statement shows how the sample tablepm.print_media was created with a nested table column ad_textdocs_ntab:CREATE TABLE print_media( product_id NUMBER(6), ad_idNUMBER(6), ad_composite BLOB, ad_sourcetext CLOB, ad_finaltext CLOB, ad_fltextn NCLOB, ad_textdocs_ntabtextdoc_tab, ad_photo BLOB, ad_graphic BFILE, ad_headeradheader_typ) NESTED TABLE ad_textdocs_ntab STORE AS textdocs_nestedtab;Oracle外部表就好像是一张视图,在数据库中可以像试图一样进行查询等操作。
这个试图允许用户在外部数据上运行任何的SQL语句,而不需要先将外部表中的数据装载进数据库中。
外部表是指不在数据库中的表,如操作系统上的一个按一定格式分割的文本文件或者其他类型的表。
这个外部表对于Oracle数据库来说,就好像是一张视图,在数据库中可以像试图一样进行查询等操作。
这个试图允许用户在外部数据上运行任何的SQL语句,而不需要先将外部表中的数据装载进数据库中。
不过需要注意是,外部数据表都是只读的,不能够更改。
不过在使用外部表时仍然有不少的限制。
限制一:需要先建立目录对象。
在使用外部数据表的时候,需要先建立目录对象。
也就是说,要想Oracle数据库系统访问操作系统文件,就必须在数据库中建立指向这个操作系统文件的目录对象,然后通过这个目录对象访问相应的操作系统文件,即用目录对象存储操作文件的保存位置。
不过需要注意,这个目录对象普通用户是无权创建的。
一般情况下只有特权用户或者数据库管理员角色才可以创建目录对象。
如果允许其他用户也可以创建目录对象的话,就需要授权给其他用户。
其实这个目录对象就是操作系统中文件或者表格的存储位置。
不过在建立对象的时候,需要小心,Oracle数据库系统不会去确认这个目录是否真的存在。
如果在输入这个目录对象的时候,不小心把路径写错了,那可能这个外部表仍然可以正常建立,但是却无法查询到数据。
由于建立目录对象时,缺乏这种自我检查的机制,为此在将路径赋予给这个目录对象时,需要特别的注意。
另外需要注意的是路径的大小写。
在Windows操作系统中,其路径是不区分大小写的。
而在Linux操作系统,这个路径需要区分大小写。
故在不同的操作系统中,建立目录对象时需要注意这个大小写的差异。
最好数据库管理员可以养成一个习惯,无论在什么操作系统中,都采用小写的目录名与文件名。
那么在不同的操作系统中,就不用受到这个大小写的困扰了。
最后需要注意的是,目录对象名必须唯一。
如果目录对象名字有重复的话,系统会提示错误信息:“名称已有现有对象引用”,而不会自动覆盖原有的对象名设置。
虽然这个对象名设置比较简单,但是其是数据库寻找操作系统上文件的唯一途径。
所以这个目录对象的创建必须确保准确。
否则的话,外部表就可能无法正常使用。
限制二:对于操作系统文件的限制。
其实外部表简单的说,就是跟操作系统上固定格式的文件或者表格的一个连接。
为了Oracle数据库系统能够正确链接外部表,对于外部表的格式就提出了比较严格的要求。
如果不符合这些要求的话,数据库系统就无法正确读取外部表中的数据。
如对于分隔符有比较严格的要求。
虽然在外部文件或者表格中,可以使用多种分隔符,如英文状态下的逗号或者分号等等。
但是有一个限制,即在同一个操作系统文件中只能够使用一个分割符号,要么逗号或者分号等等。
因为在建立外部表时,必须指定操作系统文件所使用的分隔符号。
如果有多种分隔符号的话,数据库系统将无法识别。
另外在外部表格中,不能够带有标题信息。
如现在有一张表格,以逗号分隔。
而在其第一列数据中有各个列的标题信息。
而数据库系统在连接这个表的时候,会将这些标题信息当作普通的纪录来对待。
即会将这些信息也显示在外部表中。
为此如果这个标题信息与外部表的字段类型不一致(如字段内容是number数据类型,而标题信息则是字符型数据,则在查询时就会出错)。
如果数据类型恰巧一致的话,这个标题信息Oracle数据库也会当作普通记录来对待。
如在建立外部表的时候,最好确认一下操作系统文件中是否包含标题信息。
如果有的话,需要删除。
否则的话,可能会出错。
最后需要说明的是,当Oracle数据库系统访问这个操作系统文件的时候,会在这个文件所在的目录自动创建一个日志文件。
无论最后是否访问成功,这个日志文件都会如期建立。
查看这个日志文件,可以了解数据库访问外部表的频率、是否成功访问等等。
限制三:在建立临时表时的限制。
在建立临时表时,也会有不少的限制。
如表中字段的名称有一些特殊字符的话,那么这个表列的名称必须使用英文状态的下的双引号连接起来。
如采用”studentno#”。
遇到列名字中有特殊符号时,如果不采用双引号括起来,虽然临时表可以正常创建,但是在采用的时候会出现错误,无法正常查询数据。
如数据库系统可能会提醒:“数据库插件错误”等信息。
为此最好在创建临时表时不要在列名中使用一些特殊的字符。
其实不光光是建立临时表有这种限制,建立其他标或者试图都有类似的限制。
其次,这个外部表毕竟与内部表不同。
在创建外部表的时候,其实在数据库中跟本没有创建表。
也就是说,不会为外部表分配任何的存储空间。
创建外部表只是在数据字典中创建了外部表的元数据,以便对应访问外部表中的数据,而不在数据库中存储外部表的数据。
简单地说,数据库存储的只是与外部文件的一种对应关系,如字段与字段的对应关系。
而没有存储实际的数据。
为此在表的操作与管理上,就会受到很大的限制。
如在外部表上,是不能够为表创建索引。
因为创建索引就意味着要存在对应的索引记录。
而外部表其实在数据库不会有存储。
故在外部中是无法建立索引的。
如果硬要建立的话,则系统会提示“操作在外部组织表上不受支持”的错误提示。
同样的道理,在数据库中也不能够更新外部表中的数据,如插入记录、删除记录或者更新信息等等。
简而言之,这个外部表对于数据库来说,是只读的,不可更新。
限制四:删除外部表或者目录对象。
当外部表不用时,需要及时删除外部表或者与之对应的目录对象。
不过在删除这些内容时会有一些限制。
这些限制主要是管理上的限制,而不是技术上的限制。
也就是说,Oracle 数据库系统没有对其进行强制的限制。
但是如果数据库管理员不遵守这些限制的话,可能会出现一些问题。
如要先删除外部表,然后再删除目录对象。
有时候一个目录对象中可能会包含多个外部表。
此时必须要确认所有的外部表都不用了,都已经删除干净了,然后才能够删除目录对象。
在创建外部表时,操作系统会判断一下,与之对应的目录对象是否已经创建。
但是在删除对象时,系统不会去判断跟这个目录对象关联的外部表是否已经全部删除。
如果目录对象删除了,但是还有外部表存在。
此时查询这个外部表的时候,系统就会提示“对象不存在”的错误信息。
所以这个删除目录对象时,数据库系统缺乏一种检查,此时只有数据库管理员在删除目录对象时,先手工确认一下这个目录对象是否存在其他的外部表。