外部表介绍
oracle外部表用来存取数据库以外的文本文
件(text
file)或oracle专属格式文件。因此,建立外部表时不会产生段、区、数据块等存储结构,只有与表相关的定义放在数据字典中。外部表,顾名思义,存
储在数据库外面的表。当存取时才能从oracle专属格式文件中取得数据,外部表仅供查询,不能对外部表的内容进行修改(insert、update、
delete操作)。不能对外部表建立索引。因为创建索引就意味着要存在对应的索引记录。而外部表其实在没有存储在数据库中。故在外部是无法建立索引的。
如果硬要建立的话,则系统会提示“操作在外部组织表上不受支持”的错误提示。
notice: 外部表是oracle 9i后引入的。
外部表特征
(1) 位于文件系统之中(一定要在数据库服务器中,而不是其它网络路径),按一定格式分割,
例如@#$等,文本文件或者其他类型的文件可以作为外部表。
(2) 对外部表的访问可以通过sql语句来完成,而不需要先将外部表中的数据装载进数据库中。
(3) 外部数据表都是只读的,因此在外部表不能够执行dml操作,也不能创建索引。
(4) analyze语句不支持采集外部表的统计数据,应该使用dmbs_stats包来采集外部表的统计数据。
(5) 可以查询操作和连接。也可以并行操作。
(6) 数据在数据库的外部组织,是操作系统文件。
(7) 操作系统文件在数据库中的标志是通过一个逻辑目录来映射的。
外部表范例:
1:创建目录对象并授权
从9i开始,oracle数据库若需要存取文件系统,就必须使用目录对象,以相对路径方式存取文件,强化数据库的安全性。建立目录对象、授予权限。
sql>create or replace directory dump_dir as '/oradata/exterltab';
给用户授予指定目录的操作权限
sql>grant read,write on directory dump_dir to etl;
2:创建外部表
我创建了一个平面文件作为测试用例,如下所示,总共5条记录,其中一条错误记录
[oracle@db-server exterltab]$ more student.data
10001@#$kerry@#$male@#$28@#$1
10002@#$jimmy@#$male@#$22@#$1
10003@#$ken@#$male@#$21@#$1
10004@#$merry@#$femal@#$20@#$1
this is a bad file
外部表语法也是蛮复杂的,参数选项非常多,这里不做过多解释。有兴趣自然可以翻阅官方文档。
出现下面错误,是因为student.data
文件中有不符合规范的记录,可以删除“this is a bad file”这一条记录,但是这是为了测试下面情况,所以可以通过执行 alter
table exter_test reject limit unlimited;跳过一些限制。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2UzM5QzM4UTN4EjMxYDMvwFOwQTMwIzLcJDN1MzNvw1ZvxmYvwVbvNmLn9GbiRXauNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.png)
此时去查看/oradata/exterltab,你会发现自动生成了exter_test_8907.bad 和 exter_test_8907.log两个文件,其中log记录访问外部表的记录信息,bad文件记录错误记录的信息。大体如下所示
[oracle@db-server exterltab]$ ls
exter_test_8907.bad exter_test_8907.log student.data
[oracle@db-server exterltab]$
3:查看外部表的目录
xxx_external_locations 可以知道当前所有的目录对象以及相关的外部表,还会查询出这些外部表所对应的操作系统文件的名字。
select * from all_external_locations;
select * from user_external_locations;
select * from dba_external_locations;
4:查看外部表的详细信息
5:删除外部表
删除外部表sql语法跟普通表一样,但是不同之
处在于有可能还要删除与之对应的目录对象。当外部表不用时,需要及时删除外部表或者与之对应的目录对象。不过在删除这些内容时会有一些限制。这些限制主要
是管理上的限制,而不是技术上的限制。也就是说,oracle数据库系统没有对其进行强制的限制。但是如果数据库管理员不遵守这些限制的话,可能会出现一
些问题。如要先删除外部表,然后再删除目录对象。有时候一个目录对象中可能会包含多个外部表。此时必须要确认所有的外部表都不用了,都已经删除干净了,然
后才能够删除目录对象。在创建外部表时,操作系统会判断一下,与之对应的目录对象是否已经创建。但是在删除对象时,系统不会去判断跟这个目录对象关联的外
部表是否已经全部删除。如果目录对象删除了,但是还有外部表存在。此时查询这个外部表的时候,系统就会提示“对象不存在”的错误信息。所以这个删除目录对
象时,数据库系统缺乏一种检查,此 时只有数据库管理员在删除目录对象时,先手工确认一下这个目录对象是否存在其他的外部表。
外部表限制:
1. 只能对表进行select,不能进行delete、update、insert这些dml操作。
2. 因为外部表需要在oracle数据库“服务端”创建目录,os文件必须放在这些目录中。即这些文件只能放在数据库服务端。如果数据文件不位于服务器,则无法使用外部表
3. 外部表上不能创建索引。但可以建立视图
4. 外部表不支持lob对象。如果要使用lob类型,则不能使用外部表。
eg:删除外部表的记录
eg: 在外部表上创建视图
外部表优势:
如果要谈外部表的优势,一般会和sqlldr来对比,外部表很多语法跟sqlldr控制文件确实有很多类似的地方,下面谈谈自己的理解和"oracel 9i&10g编程艺术"里面的一些对比
1.
sqlldr需要将数据装载入库后才能查询相关记录,如果只是为了查询一些记录,外部表确实比sqlldr要有优势一些,很方便又不占用数据库存储空间。
尤其是很大的数据,以前做移动综合分析项目处理sgsn话单(几百g的数据,如果全部装载入库,非常浪费空间和时间)时就有这样的体会。外部表虚拟的导入
过程极快
2:当平面文件改变时,外部表内的数据会跟着改变。这样避免了插入、更新、删除等操作,对于超大记录的外部表相当有优势,我只需要使用shell命令就能搞定数据库需要很高代价才能完成的事情。
3:外部表可以使用复杂的where
条件有选择地加载数据。尽管sqlldr 有一个when 子句用来选择要加载的行,但是你只能使用and 表达式和执行相等性比较的表达式,在when
子句中不能使用区间(大于、小于),没有or 表达式,也没有is null 等。
4:能够合并(merge)数据。可以取一个填满数据的操作系统文件,并由它更新现有的数据库记录。
5:能执行高效的代码查找。可以将一个外部表联结到另一个数据库表作为加载过程的一部分。
6:使用insert 更容易地执行多表插入。从oracle9i 开始,通过使用复杂的when 条件,可以用一个insert 语句插入一个或多个表。尽管sqlldr 也可以加载到多个表中,但是相应的语法相当复杂。