sqlldr是把数据加载到数据库中;外部表中的数据是基于操作系统文件的,真正的数据没有保存到数据库中,是在操作系统文件里面的。所以外部表里面的数据只可以select。外部表基本上可以替代sqlldr。但是在以下3种情况下,应该选择sqlldr而不是外部表:
1.必须通过网络加载数据,也就是说,输入文件不在数据库服务器上。
2.多个用户必须并发的使用相同的外部表来处理不同的输入文件。
3.必须使用LOB类型。外部表不支持LOG。
利用sqlldr的例子来生成外部表的脚本
[oracle@linux sqlldr]$ pwd /u01/sqlldr [oracle@linux sqlldr]$ cat demo1.ctl LOAD DATA INFILE * INTO TABLE DEPT FIELDS TERMINATED BY ',' (DEPTNO,DNAME,LOC) BEGINDATA 10,Sales,Virginia 20,Accounting,Virginia 30,Consulting,Virginia 40,Finance,Virginia ABC,XYZ,Hello [oracle@linux sqlldr]$ sqlldr ing/ing demo1.ctl external_table=generate_only SQL*Loader: Release 10.2.0.4.0 - Production on 星期二 10月 4 21:59:06 2011 Copyright (c) 1982, 2007, Oracle. All rights reserved.
查看生成的log文件
[oracle@linux sqlldr]$ pwd /u01/sqlldr [oracle@linux sqlldr]$ cat demo1.log SQL*Loader: Release 10.2.0.4.0 - Production on 星期二 10月 4 21:59:06 2011 Copyright (c) 1982, 2007, Oracle. All rights reserved. 控制文件: demo1.ctl 数据文件: demo1.ctl 错误文件: demo1.bad 废弃文件: 未作指定 (可废弃所有记录) 要加载的数: ALL 要跳过的数: 0 允许的错误: 50 继续: 未作指定 所用路径: 外部表 表 DEPT,已加载从每个逻辑记录 插入选项对此表 INSERT 生效 列名 位置 长度 中止 包装数据类型 ------------------------------ ---------- ----- ---- ---- --------------------- DEPTNO FIRST * , CHARACTER DNAME NEXT * , CHARACTER LOC NEXT * , CHARACTER 文件需要 CREATE DIRECTORY 语句 ------------------------------------------------------------------------ CREATE DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 AS '/u01/sqlldr' --sqlldr连接到数据库,查询数据字典。没有找到合适的目录,就创建一个SYS_SQLLDR_XT_TMPDIR_00000目录。 用于外部表的 CREATE TABLE 语句: ------------------------------------------------------------------------ CREATE TABLE "SYS_SQLLDR_X_EXT_DEPT" --创建一张表SYS_SQLLDR_X_EXT_DEPT ( "DEPTNO" NUMBER(10), "DNAME" VARCHAR2(20), "LOC" VARCHAR2(20) ) ORGANIZATION external --表明这不是一张普通表,而是一张外部表。 ( TYPE oracle_loader --加载数据的类型。另外还有一个10G才支持的ORACLE_DATAPUMP可以用来加载或卸载数据。 DEFAULT DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 --使用前面创建的目录SYS_SQLLDR_XT_TMPDIR_00000 ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE CHARACTERSET ZHS16GBK --记录默认也换行符结束。 BADFILE 'SYS_SQLLDR_XT_TMPDIR_00000':'demo1.bad' --在刚创建的目录中记录一个坏文件,无法加载的记录会记录到此文件中。 LOGFILE 'demo1.log_xt' --日志文件。 READSIZE 1048576 --加载数据的缓存区大小。1024*1024=1048576 SKIP 6 --跳过前面6行不加载,因为前面6行是sqlldr控制文件的信息。 FIELDS TERMINATED BY "," LDRTRIM --数据以逗号分隔,LDRTRIM表示去掉前后的空白字符。 REJECT ROWS WITH ALL NULL FIELDS --外部表会在坏文件中记录全空的行,而不加载这些行。 ( "DEPTNO" CHAR(255) TERMINATED BY ",", "DNAME" CHAR(255) TERMINATED BY ",", "LOC" CHAR(255) TERMINATED BY "," ) ) location ( 'demo1.ctl' --告诉oracle所加载的文件的文件名。 ) )REJECT LIMIT UNLIMITED 用于加载内部表的 INSERT 语句: ------------------------------------------------------------------------ INSERT /*+ append */ INTO DEPT --用于从外部表本身直接加载数据。 ( DEPTNO, DNAME, LOC ) SELECT "DEPTNO", "DNAME", "LOC" FROM "SYS_SQLLDR_X_EXT_DEPT" 用于清除由以前的语句创建的对象的语句: ------------------------------------------------------------------------ DROP TABLE "SYS_SQLLDR_X_EXT_DEPT" --删除外部表。 DROP DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 --删除目录。 从 星期二 10月 04 21:59:06 2011 开始运行 在 星期二 10月 04 21:59:06 2011 处运行结束 经过时间为: 00: 00: 00.14 CPU 时间为: 00: 00: 00.04
下面就执行生成的脚本
SQL> conn /as sysdba 已连接。 SQL> CREATE DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 AS '/u01/sqlldr'; 目录已创建。 SQL> grant read,write on directory SYS_SQLLDR_XT_TMPDIR_00000 to ing; 授权成功。 SQL> conn ing/ing 已连接。 SQL> CREATE TABLE "SYS_SQLLDR_X_EXT_DEPT" 2 ( 3 "DEPTNO" NUMBER(10), 4 "DNAME" VARCHAR2(20), 5 "LOC" VARCHAR2(20) 6 ) 7 ORGANIZATION external 8 ( 9 TYPE oracle_loader 10 DEFAULT DIRECTORY SYS_SQLLDR_XT_TMPDIR_00000 11 ACCESS PARAMETERS 12 ( 13 RECORDS DELIMITED BY NEWLINE CHARACTERSET ZHS16GBK BADFILE 'SYS_SQLLDR_XT_TMPDIR_00000':'demo1.bad' LOGFILE 'demo1.log_xt' READSIZE 1048576 "DEPTNO" CHAR(255) SKIP 6 FIELDS TERMINATED BY "," LDRTRIM REJECT ROWS WITH ALL NULL FIELDS ( "DEPTNO" CHAR(255) TERMINATED BY ",", 23 "DNAME" CHAR(255) 24 TERMINATED BY ",", 25 "LOC" CHAR(255) 26 TERMINATED BY "," 27 ) 28 ) 29 location 30 ( 31 'demo1.ctl' 32 ) 33 )REJECT LIMIT UNLIMITED; 表已创建。
查询外部表
SQL> select * from SYS_SQLLDR_X_EXT_DEPT; DEPTNO DNAME LOC ---------- -------------------- -------------------- 10 Sales Virginia 20 Accounting Virginia 30 Consulting Virginia 40 Finance Virginia
此时到目录下面去查看bad文件会发现存在一条记录,正是无法加载到数据库中的记录,因为ABC无法转换问数字。
[oracle@linux sqlldr]$ pwd /u01/sqlldr [oracle@linux sqlldr]$ ll | grep demo1 -rw-r--r-- 1 oracle oinstall 14 10-04 22:15 demo1.bad -rw-r--r-- 1 oracle oinstall 187 10-04 21:58 demo1.ctl -rw-r--r-- 1 oracle oinstall 2319 10-04 21:59 demo1.log -rw-r--r-- 1 oracle oinstall 570 10-04 22:15 demo1.log_xt [oracle@linux sqlldr]$ cat demo1.bad ABC,XYZ,Hello
使用外部表加载不同的文件
首先另行准备一个数据文件(故意空了6行,因为我们定义外部表的时候指定了SKIP 6嘛)
[oracle@linux sqlldr]$ pwd /u01/sqlldr [oracle@linux sqlldr]$ cat demo2.data 50,Sales,Virginia 60,Accounting,Virginia 70,Consulting,Virginia 80,Finance,Virginia
然后执行命令
SQL> alter table SYS_SQLLDR_X_EXT_DEPT location('demo2.data'); 表已更改。 SQL> select * from SYS_SQLLDR_X_EXT_DEPT; DEPTNO DNAME LOC ---------- -------------------- -------------------- 50 Sales Virginia 60 Accounting Virginia 70 Consulting Virginia 80 Finance Virginia