2013年(350)
分类: Oracle
2013-04-10 11:26:07
通常对于逻辑比较复杂的系统可能存在这种情况,因为导出的数据来源于多个系统,因此可能提供给DBA的也是多个数据文件。没有关系,先不要急着报怨,像SQL*Loader 这么有历史底蕴的工具,什么风雨没见过,这种小 case ,人家早就已经预见到了,并不需要你执行多次加载,只需要在控制文件中做适当配置即可。不过有一点非常重要,提供的数据文件中的数据存放格式必须完全相同。
下面简单演示,之前老是用 BONUS ,这里咱们换个表吧,新建一个 MANAGER 表:
SQL> CREATE TABLE MANAGER(
2 MGRNO NUMBER,
3 MNAME VARCHAR2(30),
4 JOB VARCHAR2(30),
5 REMARK VARCHAR2(4000));
表已创建。有多个数据文件,分别如下:
10,SMITH,SALES MANAGER
11,ALLEN.W,TECH MANAGER
16,BLAKE,HR MANAGER示例保存为数据文件ldr_case8_1.dat。
12,WARD,SERVICE MANAGER
13,TURNER,SELLS DIRECTOR
15,JAMES,HR DIRECTOR示例代码保存为数据文件ldr_case8_2.dat。
示例代码保存为数据文件ldr_case8_3.dat。
创建控制文件,只需要指定多个 INFILE 参数即可,如下所示:
LOAD DATA
INFILE ldr_case8_1.dat
INFILE ldr_case8_2.dat
INFILE ldr_case8_3.dat
TRUNCATE INTO TABLE MANAGER
FIELDS TERMINATED BY ","
(MGRNO,MNAME,JOB)示例代码保存为控制文件ldr_case8.ctl。
执行 SQLLDR 命令:
F:\oracle\script> SQLLDR SCOTT/TIGER CONTROL=LDR_CASE8.CTL
SQL*Loader: Release 10.2.0.1.0 - Production on 星期四 3月 12 11:26:09 2009
Copyright (c) 1982, 2007, Oracle. All rights reserved.
达到提交点 - 逻辑记录计数 2
达到提交点 - 逻辑记录计数 3
达到提交点 - 逻辑记录计数 5
达到提交点 - 逻辑记录计数 6
达到提交点 - 逻辑记录计数 7SQL*Plus 中查看导入结果:
SQL> SELECT *FROM MANAGER;
MGRNO MNAME JOB REMARK
----- ---------- ----------- ----------
10 SMITH SALES MANAGER
11 ALLEN.W TECH MANAGER
16 BLAKE HR MANAGER
12 WARD SERVICE MANAGER
13 TURNER SELLS DIRECTOR
15 JAMES HR DIRECTOR
17 MILLER PRESIDENT控制文件提供了多种逻辑判断方式,只要能把逻辑清晰地描述出来,SQL*Loader 就能按照指定的逻辑执行加载。
举个例子,待导入的数据文件如下:
BON SMITH CLEAK 3904
BON ALLEN SALER,M 2891
BON WARD SALER,"S" 3128
BON KING PRESIDENT 2523
MGR 10 SMITH SALES MANAGER
MGR 11 ALLEN.W TECH MANAGER
MGR 16 BLAKE HR MANAGER
TMP SMITH 7369 CLERK 800 20
TMP ALLEN 7499 SALESMAN 1600 30
TMP WARD 7521 SALESMAN 1250 30
TMP JONES 7566 MANAGER 2975 20示例代码保存为数据文件ldr_case9.dat。
需求是将以MGR开头的记录导入MANAGER表,以BON开头的记录导入BONUS表,其他记录存入废弃文件中(不知道啥是废弃文件?向前翻看5.2.4小节)。
创建控制文件如下:
LOAD DATA
INFILE ldr_case9.dat
DISCARDFILE ldr_case9.dsc
TRUNCATE
INTO TABLE BONUS
WHEN TAB= ' BON '
(TAB FILLER POSITION(1:3),
ENAME POSITION(5:9) ,
JOB POSITION(*+1:18),
SAL POSITION(*+1)
)
INTO TABLE MANAGER
WHEN TAB = ' MGR '
(TAB FILLER POSITION(1:3),
MGRNO POSITION(4:5) ,
MNAME POSITION(7:13),
JOB POSITION(*+1))示例代码保存为控制文件ldr_case9.ctl。
虽然这个控制文件看起来比之前的都要复杂,但只有一个新语法,即WHEN关键字,我们这里通过WHEN来实现判断,很容易理解。同时,指定了DISCARDFILE参数,以生成不满足加载条件的废弃文件,如果你有心,不妨等执行完 SQLLDR 命令后查看ldr_case9.dsc文件和ldr_case9.log文件。
另外注意,控制文件中WHEN逻辑判断不支持OR关键字,因此如果你的判断条件有多个,则只能通过AND连接,而不能直接使用OR。
执行 SQLLDR 命令:
F:\oracle\script> SQLLDR SCOTT/TIGER CONTROL=LDR_CASE9.CTL
SQL*Loader: Release 10.2.0.1.0 - Production on 星期四 3月 12 20:50:16 2009
Copyright (c) 1982, 2005, Oracle. All rights reserved.
达到提交点 - 逻辑记录计数 10SQL*Plus 中查看导入结果:
SQL> SELECT * FROM BONUS;
ENAME JOB SAL COMM
---------- ------------- ---------- ----------
SMITH CLEAK 3904
ALLEN SALER,M 2891
WARD SALER,"S" 3128
KING PRESIDENT 2523
SQL> Select * From Manager;
MGRNO MNAME JOB REMARK
------ ---------- -------------------- ----------
10 SMITH SALES MANAGER
11 ALLEN.W TECH MANAGER
16 BLAKE HR MANAGER轻松实现,完全没有难度嘛!
回答完以上两个怎么办后,如果你还能问出提供多个文件怎样导入多张表之类问题,那你就是找上门来让俺BS啊。
假如某天你接到一项数据加载需求,用户提供了一份100万行的数据文件,告诉你只导后50万行,恭喜,你接到了一个正常的需求!
实现的方式较多,比如修改数据文件,只保留后50万行(Windows 下借助 Edit Plus 这类文本工具可以轻松实现,Linux/UNIX 下通过 tail 等命令也可以轻易实现),如果你人很懒,不想修改文件,那正合 SQLLDR 胃口,人家早早地就提供好了SKIP参数专用于满足此类需求。
例如:提供数据文件如下:
SQL> SELECT ENAME,MGR,JOB,SAL FROM EMP;
ENAME MGR JOB SAL
---------- ---------- --------- ----------
SMITH 7902 CLERK 800
ALLEN 7698 SALESMAN 1600
WARD 7698 SALESMAN 1250
JONES 7839 MANAGER 2975
MARTIN 7698 SALESMAN 1250
BLAKE 7839 MANAGER 2850
CLARK 7839 MANAGER 2450
KING PRESIDENT 5000
TURNER 7698 SALESMAN 1500
JAMES 7698 CLERK 950
FORD 7566 ANALYST 3000
MILLER 7782 CLERK 1300示例代码保存为数据文件ldr_case10.dat。
相信不用我说,你也看出要做什么了,前3行不导入,从第4行开始加载,这里创建控制文件如下:
LOAD DATA
INFILE ldr_case10.dat
TRUNCATE INTO TABLE BONUS
(
ENAME position(1:6),
TCOL FILLER position(18:21),
JOB position(23:31),
SAL position(39:42)
)示例代码保存为控制文件ldr_case10.ctl。
执行 SQLLDR 命令:
F:\oracle\script> SQLLDR SCOTT/TIGER CONTROL=LDR_CASE10.CTL SKIP =3
SQL*Loader: Release 10.2.0.1.0 - Production on 星期一 3月 16 13:41:55 2009
Copyright (c) 1982, 2007, Oracle. All rights reserved.
达到提交点 - 逻辑记录计数 11
达到提交点 - 逻辑记录计数 12SQL*Plus 中查看导入结果:
SQL> SELECT * FROM BONUS;
ENAME JOB SAL COMM
---------- --------- ---------- ----------
SMITH CLERK 800
ALLEN SALESMAN 1600
WARD SALESMAN 1250
JONES MANAGER 2975
MARTIN SALESMAN 1250
BLAKE MANAGER 2850
CLARK MANAGER 2450
KING PRESIDENT 5000
TURNER SALESMAN 1500
JAMES CLERK 950
FORD ANALYST 3000
MILLER CLERK 1300如果用户要求较高,明确指定只加载第××~第××行的记录(其实是好事,需求越明确越好),没问题, SQLLDR 还有一个参数叫 LOAD ,配置LOAD参数即可轻松实现。
这里仍使用上述数据文件,需求改为只导入第4~9行的记录,我们连控制文件都不需要修改,只需要在执行 SQLLDR 时再加上 LOAD 参数即可:
F:\oracle\script> SQLLDR SCOTT/TIGER CONTROL=LDR_CASE10.CTL SKIP=4 LOAD=6
SQL*Loader: Release 10.2.0.1.0 - Production on 星期一 3月 16 13:45:38 2009
Copyright (c) 1982, 2007, Oracle. All rights reserved.
达到提交点 - 逻辑记录计数 6SQL*Plus 中查看结果:
SQL> SELECT * FROM BONUS;
ENAME JOB SAL COMM
---------- --------- ---------- ----------
SMITH CLERK 800
ALLEN SALESMAN 1600
WARD SALESMAN 1250
JONES MANAGER 2975
MARTIN SALESMAN 1250
BLAKE MANAGER 2850