关于外部表
Oracle数据库允许你以只读方式访问外部表的数据。外部表被定义为不驻留在数据库的表,而且,只要提供了访问驱动程序外部表支持任意格式。只要提供了描述外部表的元数据,Oracle数据库就可以展现外部表中的数据,就像它是驻留在一个常规的数据库表一样。使用SQL可以直接并行查询外部表。
对于外部表,你可以执行查询操作,连接操作或者对数据进行排序。你也可以给外部表创建视图或者同义词。但是,外部表不支持DML操作(更新、插入或者删除),也不能创建索引。
外部表提供了一个框架,我们可以将任意SELECT语句返回的结果转化为独立于平台的Oracle专有的格式,Oracle数据泵可以使用这种格式的文件。外部表为执行基本提取、转换和加载(ETL)任务提供了一个重要的手段,这在数据仓库中是很常见的。
定义外部表元数据是通过CREATE TABLE...ORGANIZATION EXTERNAL来完成。这个外部表定义可以视为一个视图,可以执行任意的SQL查询,而无需把外部表数据加载到数据库。访问驱动程序是用来把外部表数据读取到表的实际机制。当你使用外部表卸载数据时,Oracle会根据SELECT语句中的数据类型自动创建元数据。
Oracle数据库提供了两种外部表访问驱动程序。默认的访问驱动程序是ORACLE_LOADER,它使用Oracle加载技术从外部表中读取数据。ORACLE_LOADER提供了数据映射功能,这是SQL*Loader实用程序控制文件语法的一个子集。第二个访问驱动程序是ORACLE_DATAPUMP,它是从数据库中读取数据并插入到外部表中,保存为一个或多个外部文件,然后重新加载到Oracle数据库。
注意:
外部表不支持使用ANALYZE语句来手机统计信息,可以使用DBMS_STATS包来代替;
外部表不支持虚列;
创建外部表
你可以通过CREATE TABLE...ORGANIZATION EXTERNAL语句来创建外部表,该语句仅在数据字典中创建元数据。
下面的示例创建了一个外部表,然后将数据加载到一个数据库表中。或者,你可以通过指定CREATE TABLE语句的AS子查询,使用外部表框架来卸载数据。外部表数据泵卸载只能使用ORACLE_DATAPUMP访问驱动程序。
示例:创建一个外部表并加载数据
在这个示例中,外部表的数据保存在两个文本文件,empxt1.dat和empxt2.dat。
文件empxt1.dat包含以下数据:
点击(此处)折叠或打开
-
360,Jane,Janus,ST_CLERK,121,17-MAY-2001,3000,0,50,jjanus
-
361,Mark,Jasper,SA_REP,145,17-MAY-2001,8000,.1,80,mjasper
-
362,Brenda,Starr,AD_ASST,200,17-MAY-2001,5500,0,10,bstarr
- 363,Alex,Alda,AC_MGR,145,17-MAY-2001,9000,.15,80,aalda
文件empxt2.dat包含以下数据:
点击(此处)折叠或打开
-
401,Jesse,Cromwell,HR_REP,203,17-MAY-2001,7000,0,40,jcromwel
-
402,Abby,Applegate,IT_PROG,103,17-MAY-2001,9000,.2,60,aapplega
-
403,Carol,Cousins,AD_VP,100,17-MAY-2001,27000,.3,90,ccousins
- 404,John,Richardson,AC_ACCOUNT,205,17-MAY-2001,5000,0,110,jrichard
下面的SQL语句在HR模式下,创建了一个名为admin_ext_employees的外部表,并将外部表的数据加载到hr.employees表中。
以下的段落包含了上述示例的描述信息。
点击(此处)折叠或打开
-
CONNECT / AS SYSDBA;
-
-- Set up directories and grant access to hr
-
CREATE OR REPLACE DIRECTORY admin_dat_dir
-
AS \'/flatfiles/data\';
-
CREATE OR REPLACE DIRECTORY admin_log_dir
-
AS \'/flatfiles/log\';
-
CREATE OR REPLACE DIRECTORY admin_bad_dir
-
AS \'/flatfiles/bad\';
-
GRANT READ ON DIRECTORY admin_dat_dir TO hr;
-
GRANT WRITE ON DIRECTORY admin_log_dir TO hr;
-
GRANT WRITE ON DIRECTORY admin_bad_dir TO hr;
-
-- hr connects. Provide the user password (hr) when prompted.
-
CONNECT hr
-
-- create the external table
-
CREATE TABLE admin_ext_employees
-
(employee_id NUMBER(4),
-
first_name VARCHAR2(20),
-
last_name VARCHAR2(25),
-
job_id VARCHAR2(10),
-
manager_id NUMBER(4),
-
hire_date DATE,
-
salary NUMBER(8,2),
-
commission_pct NUMBER(2,2),
-
department_id NUMBER(4),
-
email VARCHAR2(25)
-
)
-
ORGANIZATION EXTERNAL
-
(
-
TYPE ORACLE_LOADER
-
DEFAULT DIRECTORY admin_dat_dir
-
ACCESS PARAMETERS
-
(
-
records delimited by newline
-
badfile admin_bad_dir:\'empxt%a_%p.bad\'
-
logfile admin_log_dir:\'empxt%a_%p.log\'
-
fields terminated by \',\'
-
missing field values are null
-
( employee_id, first_name, last_name, job_id, manager_id,
-
hire_date char date_format date mask \"dd-mon-yyyy\",
-
salary, commission_pct, department_id, email
-
)
-
)
-
LOCATION (\'empxt1.dat\', \'empxt2.dat\')
-
)
-
PARALLEL
-
REJECT LIMIT UNLIMITED;
-
-- enable parallel for loading (good if lots of data to load)
-
ALTER SESSION ENABLE PARALLEL DML;
-
-- load the data in hr employees table
-
INSERT INTO employees (employee_id, first_name, last_name, job_id, manager_id,
-
hire_date, salary, commission_pct, department_id, email)
- SELECT * FROM admin_ext_employees;
示例最开始的几条语句创建了几个目录对象,包括包含数据源的操作系统目录,也包括输入参数需要用到的保存不良记录以及日志的目录。如果合适的话,你必须赋予读或者写目录对象权限。
注意:
当创建目录对象或者BFILEs时,必须确保满足下面几个条件:
操作系统文件不能是符号连接或者硬连接;
Oracle数据库目录对象中定义的操作系统目录路径必须存在;
Oracle数据库目录对象中定义的操作系统目录,在其组件中不应包含任何符号连接;
Type参数用来指定外部表的访问驱动程序。访问驱动程序时用来为数据库解析外部数据。如果你忽略了Type类型说明,ORACLE_LOADER是默认的访问驱动程序。如果你指定AS子查询子句从一个Oracle数据库卸载数据,并重新加在到相同或不同的Oracle数据库,您必须指定ORACLE_DATAPUMP访问驱动程序。
在ACCESS PARAMETERS子句中制定的访问参数,对数据库时不透明的。这些访问参数由访问驱动程序定义,当访问外部表时需要提供给访问驱动程序。请参考Oracle实用程序对ORACLE_LOADER访问参数的描述。
并行子句允许对数据源进行并行查询。默认的并行的颗粒是数据源,但数据源内的并行访问只能尽可能地实现。例如,如果PARALLEL参数被指定为3,那么多个并行处理服务器可以处理一个数据源。但是,只有满足所有以下条件时,访问驱动程序才会提供并行访问:
- 介质允许一个数据库内随机定位
- 可能从随机位置中找到记录边界
- 数据文件足够大,值得并行访问
注意:
只有当有大量的数据处理指定PARALLEL子句是有价值的。否则,这是不可取指定并行条款,而这样做可能是有害的。
REJECT LIMIT子句指定了在查询外部表期间,对可能发生地错误数量没有限制。对于并行访问,
REJECT LIMIT子句分别独立适用于每一个并行执行服务器。例如,如果REJECT LIMIT子句被指定为10,那么每个并行查询过程可以允许最多10个拒绝。因此,使用并行度为2和REJECT LIMIT为10,语句可能在10到20个拒绝之间会面临失败。如果一个并行服务器处理了所有10个拒绝,那么就达到了上限,语句将会终止。然而,一个并行处理服务器可以处理9个拒绝,另一个并行处理服务器也可以处理9个拒绝,那么这个语句虽然有18个拒绝,但是也会成功执行。因此,精确执行并行查询的REJECT LIMIT值只能是0和UNLIMITED。
在这个示例中,INSERT INTO TABLE语句生成从外部数据源到处理Oracle数据库数据的SQL引擎的数据流。因为数据在被访问驱动程序从外部表源解析后并提供给外部表接口,外部数据从外部表示转换成Oracle数据库内部数据类型。
修改外部表
您可以使用下表所示的ALTER TABLE子句来改变外部表的特性,其他子句都是不允许的。
ALTER TABLE 子句 |
描述 |
举例 |
REJECT LIMIT |
修改拒绝限制,默认值为0 |
ALTER TABLE admin_ext_employees REJECT LIMIT 100; |
PROJECT COLUMN |
决定访问驱动程序在随后的查询中如何验证数据行: PROJECT COLUMN REFERENCED:访问驱动程序仅处理查询中选择的列。当从同一个外部表中查询不同列时,该设置可能无法提供一致的行集合。 PROJECT COLUMN ALL:访问驱动程序处理定义在外部表上的所有列。该设置当查询外部表时始终提供一致的行集合。这是默认设置。 |
ALTER TABLE admin_ext_employees PROJECT COLUMN REFERENCED; ALTER TABLE admin_ext_employees PROJECT COLUMN ALL; |
DEFAULT DIRECTORY |
修改指定的默认目录 |
ALTER TABLE admin_ext_employees DEFAULT DIRECTORY admin_dat2_dir; |
预处理外部表
警告:
在使用预处理子句时要考虑安全隐患。
外部表可以通过用户提供的预处理程序进行预处理。通过使用预处理程序,用户可以从驱动程序不支持的文件格式中使用数据。例如,用户可能希望访问存储在一个压缩格式的数据,通过指定一个解压缩程序用于ORACLE_LOADER访问驱动程序,这样就允许解压缩数据,进而驱动程序就能处理数据。
要使用预处理功能,在ORACLE_LOADER访问驱动程序的访问参数中,您必须指定PREPROCESSOR子句。预处理器必须是一个目录对象,并且访问外部表的用户必须具有目录对象的执行权限。下面的示例包括PREPROCESSOR子句并且指定了目录和预处理程序。
点击(此处)折叠或打开
-
CREATE TABLE sales_transactions_ext
-
(PROD_ID NUMBER,
-
CUST_ID NUMBER,
-
TIME_ID DATE,
-
CHANNEL_ID CHAR,
-
PROMO_ID NUMBER,
-
QUANTITY_SOLD NUMBER,
-
AMOUNT_SOLD NUMBER(10,2),
-
UNIT_COST NUMBER(10,2),
-
UNIT_PRICE NUMBER(10,2))
-
ORGANIZATION external
-
(TYPE oracle_loader
-
DEFAULT DIRECTORY data_file_dir
-
ACCESS PARAMETERS
-
(RECORDS DELIMITED BY NEWLINE
-
CHARACTERSET AL32UTF8
-
PREPROCESSOR exec_file_dir:\'zcat\'
-
BADFILE log_file_dir:\'sh_sales.bad_xt\'
-
LOGFILE log_file_dir:\'sh_sales.log_xt\'
-
FIELDS TERMINATED BY \"|\" LDRTRIM
-
( PROD_ID,
-
CUST_ID,
-
TIME_ID,
-
CHANNEL_ID,
-
PROMO_ID,
-
QUANTITY_SOLD,
-
AMOUNT_SOLD,
-
UNIT_COST,
-
UNIT_PRICE))
-
location (\'sh_sales.dat.gz\')
- )REJECT LIMIT UNLIMITED;
PREPROCESSOR子句不适用于使用Oracle Database Vault的数据库。
删除外部表
对于外部表,DROP TABLE语句仅删除在数据库中的元数据。由于外部表驻留在数据库之外,因此外部表的实际数据不受影响。
外部表的系统和对象权限
外部表的系统和对象特权是那些常规表权限的子集。只有以下系统权限适用于外部表:
CREATE ANY TABLE
ALTER ANY TABLE
DROP ANY TABLE
SELECT ANY TABLE
只有下列对象权限适用于外部表:
ALTER
SELECT
然而,在一个目录相关联的对象的权限是:
READ
WRITE
对于外部表,需要对包含数据源目录对象的读权限,对于包含不良数据、日志或者丢弃文件等目录对象则需要写权限。