一、外部表概述
外部表只能在Oracle 9i 之后来使用。简单地说,外部表,是指不存在于数据库中的表。
通过向Oracle 提供描述外部表的元数据,我们可以把一个操作系统文件当成一个只读的数
据库表,就像这些数据存储在一个普通数据库表中一样来进行访问。外部表是对数据库表的
延伸。
二、外部表的特性
位于文件系统之中,按一定格式分割,如文本文件或者其他类型的表可以作为外部表。
对外部表的访问可以通过SQL 语句来完成,而不需要先将外部表中的数据装载进数据库中。
外部数据表都是只读的,因此在外部表不能够执行DML 操作,也不能创建索引。
ANALYZE 语句不支持采集外部表的统计数据,应该使用DMBS_STATS 包来采集外部表的统计
数据。
三、创建外部表的注意事项
(一)需要先建立目录对象
在建立对象的时候,需要小心,Oracle 数据库系统不会去确认这个目录是否真的存在。
如果在输入这个目录对象的时候,不小心把路径写错了,那可能这个外部表仍然可以正常建
立,但是却无法查询到数据。由于建立目录对象时,缺乏这种自我检查的机制,为此在将路
径赋予给这个目录对象时,需要特别的注意。另外需要注意的是路径的大小写。在Windows
操作系统中,其路径是不区分大小写的。而在Linux 操作系统,这个路径需要区分大小写。
故在不同的操作系统中,建立目录对象时需要注意这个大小写的差异。
(二)对于操作系统文件的要求
建立外部表时,必须指定操作系统文件所使用的分隔符号。并且该分隔符有且只有一个。
创建外部表时,不能含有标题列。如果这个标题信息与外部表的字段类型不一致(如字段内
容是number 数据类型,而标题信息则是字符型数据,则在查询时就会出错)。如果数据类型
恰巧一致的话,这个标题信息Oracle 数据库也会当作普通记录来对待。
当Oracle 数据库系统访问这个操作系统文件的时候,会在这个文件所在的目录自动创建一
个日志文件。无论最后是否访问成功,这个日志文件都会如期建立。查看这个日志文件,可
以了解数据库访问外部表的频率、是否成功访问等等。默认情况下,该日志在与外部表的相
同directory 下产生。
(三)在建立临时表时的相关限制
对表中字段的名称存在特殊字符的情况下,必须使用英文状态的下的双引号将该表列名
称连接起来。如采用”SalseID#”。
对于列名字中特殊符号未采用双引号括起来时,会导致无法正常查询数据。
建议不用使用特殊的列标题字符
在创建外部表的时候,并没有在数据库中创建表,也不会为外部表分配任何的存储空间。
创建外部表只是在数据字典中创建了外部表的元数据,以便对应访问外部表中的数据,而不
在数据库中存储外部表的数据。
简单地说,数据库存储的只是与外部文件的一种对应关系,如字段与字段的对应关系。
而没有存储实际的数据。
由于存储实际数据,故无法为外部表创建索引,同时在数据使用DML 时也不支持对外部
表的插入、更新、删除等操作。
(四)删除外部表或者目录对象
一般情况下,先删除外部表,然后再删除目录对象,如果目录对象中有多个表,应删除
所有表之后再删除目录对象。
如果在未删除外部表的情况下,强制删除了目录,在查询到被删除的外部表时,将收到
"对象不存在"的错误信息。
查询dba_external_locations 来获得当前所有的目录对象以及相关的外部表,同时会
给出这些外部表所对应的操作系统文件的名字。如果只是在数据库层面上删除外部表,并
不会自动删除操作系统上的外部表文件。
(五)对于操作系统平台的限制
不同的操作系统对于外部表有不同的解释和显示方式
如在Linux 操作系统中创建的文件是分号分隔且每行一条记录,但该文件在Windows
操作系统上打开则并非如此。
建议避免不同操作系统以及不同字符集所带来的影响
四、两种外部表
Oracle 为外部表提供了两种访问的驱动程序,默认的访问程序是oracle_loader,它允许使
用oracle 的装载技术从外部文件中读取数据。另一种访问驱动程序是oracle_datapump 它从
数据库读取数据库并将数据插入到外部表中。
(一)Oracle_loader驱动程序
1.创建datapump 外部表的语法实例:
CREATE TABLE "SYS_SQLLDR_X_EXT_DEPT_NEW" (
"DEPTNO" NUMBER(2),
"DNAME" VARCHAR2(14),
"LOC" VARCHAR2(13)
)
ORGANIZATION external
(
TYPE oracle_loader --指定外部表的访问方式,9i 不支持oracle_datapump
DEFAULT DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000
ACCESS PARAMETERS --配置外部表参数
(
RECORDS DELIMITED BY NEWLINE CHARACTERSET US7ASCII --记录以换行为结束
BADFILE SYS_SQLLDR_XT_TMPDIR_00000:'demo1.bad'--存放处理失败的记录文件描述
LOGFILE 'demo1.log_xt' --日志文件
READSIZE 1048576
--Oracle 读取输入数据文件所用的默认缓冲区,此处为MB
SKIP 6 --跳过的记录数,因为我们使用了控制文件,所以前面的控制信息需要跳过
FIELDS TERMINATED BY "," LDRTRIM --描述字段的终止符
REJECT ROWS WITH ALL NULL FIELDS --所有为空值的行被跳过并记录到bad file.
( --下面是描述外部文件各个列的定义
"DEPTNO" CHAR(255) TERMINATED BY ",",
"DNAME" CHAR(255) TERMINATED BY ",",
"LOC" CHAR(255) TERMINATED BY ","
)
)
location
(
'demo1.ctl' --描述外部文件的文件名
)
)REJECT LIMIT UNLIMITED --描述允许的错误数,此处为无限制
/2.示例
创建外部表去访问/home/oracle 下stu.dat 文件中的记录
//在数据库上创建目录
SQL> create or replace directory dir as '/home/oracle';
//构造数据
[oracle@oracle ~]$ vim stu.dat
000001,ALICE
000002,JACK
000003,DAVID
000004,MIKE
000005,KEVIN
//创建外部表
SQL> create table stu
(id number,name varchar(10))
organization external
(type oracle_loader
default directory dir
access parameters
(
records delimited by newline
badfile dir:'exp.bad'
logfile dir:'emp.log'
fields terminated by ','
missing field values are null
(id,name))
location ('stu.dat'))
reject limit unlimited;
//检索数据
SQL> select * from stu;
ID NAME
---------- ----------
1 ALICE
2 JACK
3 DAVID
4 MIKE
5 KEVIN
(二)Oracle_datapump驱动程序
创建一个外部表去访问另一个数据库中的数据库,先把令一个数据库中的数据导入一个
文件,然后再去访问外部文件。
1.创建datapump 外部表的语法实例:
create table ex_tb1 --创建外部表
(ename,job,sal,dname) --表列描述,注意未指定数据类型
organization external
(
type oracle_datapump
--使用datapump 将查询结果填充到外部表,此处由select 生成不支持oracle_loader
default directory dat_dir --指定外部表的存放目录
location('tb1.exp,tb2.exp'))
parallel 2
--按并行方式来填充,这里的并行度必须与生成的文件数量一致才能起作用
as
select ename,job,sal,dname --填充使用的原始数据
from emp join dept
on emp.deptno=dept.deptno2.示例:
数据库orcl 要访问数据库prod 中一个表emp 中的部分数据,步骤如下:
--//在prod 数据库上创建目录
SQL> create or replace directory dir as '/home/oracle';
Directory created.
--//对scott 用户授权
SQL> grant write,read on directory dir to scott;
Grant succeeded.
--//解锁scott 用户
SQL> alter user scott identified by oracle account unlock;
User altered.
--//连接scott 用户并且创建外部表
SQL> conn scott/oracle;
Connected.
--//创建外部表
SQL> CREATE TABLE ext_emp
organization external
(
type oracle_datapump
default directory dir
location('emp.dat')
)
as
SELECT ename,empno,deptno
FROM emp;
--//连接到orcl 数据库
[oracle@oracle ~]$ export ORACLE_SID=orcl
[oracle@oracle ~]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.1.0 - Production on Fri Aug 9 22:23:05 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
--//在orcl 数据库上创建目录
SQL> create or replace directory dir as '/home/oracle';
--//创建外部表
SQL> create table ext_prod_emp(
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
DEPTNO NUMBER(2)
)
organization external
(
type oracle_datapump
default directory dir
location('emp.dat')
);
Table created.
SQL> select * from ext_prod_emp;注:在外部表上不能执行DML 操作
使用CREATE TABLE 语句的ORGANIZATION EXTENERAL 子句来创建外部表。外部表不分配
任何盘区,因为仅仅是在数据字典中创建元数据。
五:创建外部表完整示例:
1:创建文件目录并授权
--切换到 oracle 用户
[root@localhost ~]# su - oracle
--在linux的文件系统上创建 存放外部文件的目录
[oracle@localhost ~]$ cd /home/oracle/
[oracle@localhost ~]$ ls
database grid h:1emp.txt h:1spooltest.txt oracle_system_files_back rlwrap-0.37
Desktop h:1dept.sql h:1.lst h:emp.txt oyt.lst rlwrap-0.37.tar.gz
[oracle@localhost ~]$ mkdir extertablefile;
[oracle@localhost ~]$ ls
database extertablefile h:1dept.sql h:1.lst h:emp.txt oyt.lst rlwrap-0.37.tar.gz
Desktop grid h:1emp.txt h:1spooltest.txt oracle_system_files_back rlwrap-0.37
[oracle@localhost ~]$ cd extertablefile/
[oracle@localhost extertablefile]$ pwd
/home/oracle/extertablefile
[oracle@localhost extertablefile]$ ls
[oracle@localhost extertablefile]$ ll
total 0
--连接 oracle数据库 [oracle@localhost extertablefile]$ rlwrap sqlplus / as sysdba; SQL*Plus: Release 11.2.0.3.0 Production on Sat Jul 14 18:26:17 2018 Copyright (c) 1982, 2011, Oracle. All rights reserved. Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
---查看数据库实例信息
SYS@orcl> select instance_name ,status from v$instance; INSTANCE_NAME STATUS
---------------- ------------
orcl OPEN
---创建 exterdir 外部文件目录
SYS@orcl> create directory exterdir as '/home/oracle/extertablefile'; Directory created.
---给 scott用户赋予创建 文件目录的权限
SYS@orcl> grant create any directory to scott; Grant succeeded.
---连接 scott用户
SYS@orcl> conn scott/scott
Connected.
---创建文件目录:exterdirscott
SCOTT@orcl> create directory exterdirscott as '/home/oracle/extertablefile'; Directory created. SCOTT@orcl> conn / as sysdba;
Connected.
----给scott 赋予 sys用户创建的 exterdir 文件目录的读取、编写 的权限
SYS@orcl> grant read ,write on directory exterdir to scott; Grant succeeded. SYS@orcl>