본문 바로가기

개발

[DB] 오라클(Oracle) SQL Loader사용방법(bulk insert)


============
SQL * Loader
============

이 툴을 만지리라 생각하셨다면..이미 테이블에 대한 설계가 끝난 상태일 것입니다..
난 아닌디....하시는 분은...
머..기냥 보시구여..

SQL*Loader라는 툴은 테이블에 데이타를 집어 넣는 것입니다...
문자형에서 숫자형...이미지 까지 집어 넣을 수 있습니다..
집어 넣는거야..insert문을 쓰거나 해서 집어 넣을 가 있습니다..
그러나 1만건...10만건 또는 그 이상의 데이타를 집어 넣으려면....
테이블은 만들었는데...데이타는 엑셀파일로 되어있다...쩝..
보통의 노가다로는 해결할 수 없습니다...
그래서 등장한 툴이 바로 SQL*Loader입니다...
아주 멋진 툴입니다...막바로..기냥 테이블에 데이타를 때려 부울수가 있게 해주는 툴입니다..

이것도 기냥하는 것은 아닙니다..
5가지 파일을 만들어 주어야 합니다...
다음은 그 파일과 설명입니다..

control file : 데이타 적재를 위한 제어 파일
data file    : 데이타를 담고 있는 파일
log file     : 로그 파일
bad file     : 적재되지 못한 데이타들
discard file : 적재되지 못한 데이타들에 대한 정보를 저장


일단..대량의 데이타를 넣는 다는 것도 상당히 문제를 일으킬 수 있습니다...
만약 시스템이 어떤 서비스를 가동중인 상태에서 이런 대량의 데이타를 적재시키는 작업을 한다면..
여러가지를 고려해 주어야합니다...
근데...일반적인 이미지나..큰 텍스트가 아닌 데이타를 적재시킬때...그렇게 오래 걸리지는 않더군여...
약...2만건을 적재시키는데...15초 정도 걸리더라구여...일반 pc에서 말입니다..
헐헐~

암튼...여러가지 고려사항이 있습니다..
그 고려상항에 맞추라고 오라클에서는 두가지의 데이타 로드 방법을 제공하고 있습니다..

- 일반 경로를 이용한 방법

-인덱스화된 테이블의 데이타 로드시 사용
-인덱스화 되지 않은 테이블에 대한 로드시 사용
-클러스트화된 테이블의 데이타 로드시 사용
-NET*에 의해 로더할 때 사용
-SQL 함수를 데이타 필드에 적용할 때 사용

- 직접 경로를 이용한 방법

-내부적으로 처리되기 때문에 SQL문이 사용되지 않는다.
-오직 한번만 테이블과 인덱스에 잠금이 발생
-버퍼를 사용하지 않아 일반경로를 이용한 방법보다 빠르게 실행
-노아카이브로그 모드에서 사용할때 테이블에 발생하는 모든 로그 정보를 저장하지 않는다.

두가지 방법의 비교

일반경로                              직접경로
----------------------------------    -------------------------------------------
committ문으로 데이타 저장       하나의 블록이 모두 사용되면 저장

리두로그 정보가 항상 생성             노아카이브로그 --> 리두로그 정보 생성안됩
                                      아카이브로그   --> 리두로그 정보 생성

테이블의 모든 제약조건 적용       기본키, 유일키, not null 제약만 적용

클러스트도 로드 가능                  클러스트 로드 불가능

로드중에도 insert 트리거 사용 가능    로더중에 insert 트리거 사용 불가능

다른 사용자가 로드되는 테이블       다른 사용자가 로드되는 테이블 사용할 수 없음
사용가능

자...이제는 SQL*Loader 를 사용해 봅시다...

========================================================================================

C:\>sqlldr

SQL*Loader: Release 8.1.6.0.0 - Production on 화 Jan 29 15:49:42 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.


사용법: SQLLOAD 키워드=값 [,키워드=값,...]

적절한 키워드:

    userid -- ORACLE username/password
   control -- Control file name
       log -- Log file name
       bad -- Bad file name
      data -- Data file name
   discard -- Discard file name
discardmax -- Number of discards to allow          (기본값 all)
      skip -- Number of logical records to skip    (기본값 0)
      load -- Number of logical records to load    (기본값 all)
    errors -- Number of errors to allow            (기본값 50)
      rows -- Number of rows in conventional path bind array or between direct p
ath data saves
               (기본값: 규약 경로 64, 직접 경로 전체)
  bindsize -- Size of conventional path bind array in bytes  (기본값 65536)
    silent -- Suppress messages during run (header,feedback,errors,discards,partitions)
    direct -- use direct path                      (기본값 FALSE)
   parfile -- parameter file: name of file that contains parameter specifications
  parallel -- do parallel load                     (기본값 FALSE)
      file -- File to allocate extents from
skip_unusable_indexes -- disallow/allow unusable indexes or index partitions  (기본값 FALSE)
skip_index_maintenance -- do not maintain indexes, mark affected indexes as unusable  (기본값 FALSE)
commit_discontinued -- commit loaded rows when load is discontinued  (기본값 FALSE)
  readsize -- Size of Read buffer                  (기본값 1048576)

주: 명령줄 매개변수는 위치 혹은 키워드로 지정될 수 있습니다
전자의 경우의 예는 'sqlload scott/tiger foo';
후자의 경우의 예는 'sqlload control=foo userid=scott/tiger'.
하나는 이전 위치에 의해 매개변수를 지정할 수 있으나 매개변수가
키워드에 의해 지정한 이후에는 할 수 없습니다.  예를 들어,
'sqlload scott/tiger control=foo logfile=log'는 허용되지만,
'sqlload scott/tiger control=foo log'는 매개변수 'log'의
위치가 맞더라도 허용되지 않습니다      

========================================================================================


그냥 명령 프롬프트에서 sqlldr라구만 쳐보면 이런 설명이 나옵니다..
유닉스도 마찬가지구여...
유닉스도 함 볼까요??

========================================================================================

/data2/lgeds>sqlldr

SQL*Loader: Release 8.1.6.0.0 - Production on Tue Jan 29 15:48:24 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.


Usage: SQLLOAD keyword=value [,keyword=value,...]

Valid Keywords:

    userid -- ORACLE username/password
   control -- Control file name
       log -- Log file name
       bad -- Bad file name
      data -- Data file name
   discard -- Discard file name
discardmax -- Number of discards to allow          (Default all)
      skip -- Number of logical records to skip    (Default 0)
      load -- Number of logical records to load    (Default all)
    errors -- Number of errors to allow            (Default 50)
      rows -- Number of rows in conventional path bind array or between direct path data saves
               (Default: Conventional path 64, Direct path all)
  bindsize -- Size of conventional path bind array in bytes  (Default 65536)
    silent -- Suppress messages during run (header,feedback,errors,discards,partitions)
    direct -- use direct path                      (Default FALSE)
   parfile -- parameter file: name of file that contains parameter specifications
  parallel -- do parallel load                     (Default FALSE)
      file -- File to allocate extents from
skip_unusable_indexes -- disallow/allow unusable indexes or index partitions  (Default FALSE)
skip_index_maintenance -- do not maintain indexes, mark affected indexes as unusable  (Default FALSE
)
commit_discontinued -- commit loaded rows when load is discontinued  (Default FALSE)
  readsize -- Size of Read buffer                  (Default 1048576)

PLEASE NOTE: Command-line parameters may be specified either by
position or by keywords.  An example of the former case is 'sqlload
scott/tiger foo'; an example of the latter is 'sqlload control=foo
userid=scott/tiger'.  One may specify parameters by position before
but not after parameters specified by keywords.  For example,
'sqlload scott/tiger control=foo logfile=log' is allowed, but
'sqlload scott/tiger control=foo log' is not, even though the
position of the parameter 'log' is correct.                            

========================================================================================

아차차차차차~~!!
빼먹을 뻔했슴다...
나중에 로더를 사용해서 데이타를 적재시키는데...
sqlldr userid=scott/tiger control='C:\control.ctl' 의 식으로 하게 되는데..
주의할 것은 errors 라는 옵션을 충분히 주라는 얘기입니다..
기본값으로 50으로 설정되어 있어서 데이타 파일의 적절하지 않은 데이타가 50건이 넘으면
데이타 적재를 하다가 멈춰버리니까여...
제가 이걸 몰라서 엄청난 삽질을 한 경험이 있답니다..
대량의 데이타 적재시 반드시  errors의 값을 충분히 설정해 주시기 바랍니다..

자...이제 실제로 해봅시다...
먼저 컨트롤 파일을 하나 만들기 전에...
테스트를 위한 사용자를 하나 생성해 봅시다....

SQL> create user loader identified by loader
  2  default tablespace users;

사용자가 생성되었습니다.

SQL> grant connect, resource to loader;

권한이 부여되었습니다.


다음으로 오라클 셋업할때 샘플로 주어진 것으로 실습할꺼니까...
scott.emp파일에 대한 똑같은 구조를 가지는 테이블을 만들어 봅시다..

SQL> connect scott/tiger
연결되었습니다.
SQL> grant select on emp to loader;

권한이 부여되었습니다.

SQL> create table emp
  2  as
  3  select * from scott.emp
  4  where 1=0;                 ------------> 여기서 where 1=0 한것은 테이블의 구조만 복사하기 위한 것이다..

테이블이 생성되었습니다.


예제는 $ORACLE_HOME/rdbms/demo에 있습니다...
ulcase.* 들이 로더와 관련된 것들입니다...
겅부하기 편하게 해놨지여??? 헐헐~ 물론 mssql보다는 편하지는 않지만..쩝..

앗~ 된장...첨에 dept테이블이 군요...
쩝...
아래 sql 스크립트를 실행합니다..쩝..

create table dept
       (deptno number(2),
        dname char(14) ,
        loc char(13) ) ;


ulcase1.ctl의 내용입니다..

LOAD DATA
INFILE *
INTO TABLE DEPT
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(DEPTNO, DNAME, LOC)
BEGINDATA
12,RESEARCH,"SARATOGA"
10,"ACCOUNTING",CLEVELAND
11,"ART",SALEM
13,FINANCE,"BOSTON"
21,"SALES",PHILA.
22,"SALES",ROCHESTER
42,"INT'L","SAN FRAN"       

이 컨트롤 파일의 내용을 살펴보자면....

LOAD DATA       ----> 개나 소나 컨트롤 파일에는 첨에 다 들어 갑니다..
INFILE *        ----> '*' 표시는 컨트롤 파일안에 적재할 데이타가 들어있다는 소리입니다..
                      여기에 데이타파일과 컨트롤 파일이 분리 되어 있다면..데이타 파일의 경로를 입력할 도 있다..
INTO TABLE DEPT ----> dept 테이블에 적재하것다는 소리..
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'     -----> 각 필드가 ',' 로 구분하고 옵션으로 '""로 둘러 쌓고 있다는 소리..
                                                               즉, '"'는 적재되지 않는다..
(DEPTNO, DNAME, LOC)    -----> 데이타가 들어갈 컬럼명
BEGINDATA            ------> 데이타가 시작된다는 의미

나머지는 데이타입니다..
이 파일을 간단하게 c:\으로 복사하것슴다..

============================================================================================

C:\>sqlldr userid=loader/loader control='C:\ulcase1.ctl'

SQL*Loader: Release 8.1.6.0.0 - Production on 화 Jan 29 16:14:44 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.

커밋 시점에 도달 - 논리 레코드 개수 7                                                             

============================================================================================

SQL> select count(*) from dept;

  COUNT(*)
----------
         7       ------------> 데이타가 들어 갔습니다..
        
헐헐~
절라 좋습니다...편리함돠...헐헐~
여기서 알은 것은...상당히 많습니다...
일단...컨트롤 파일과 데이타만 있다면 로더의 실행은 가능합니다...
그러나...10만건..100만건 되는 데이타에 오류가 없을 수는 없는 노릇입니다..
        
ulcase1.ctl의 내용을 살짝 수정해 봅시다....

LOAD DATA
INFILE *
APPEND               ---------> APPEND 라는 키워드 추가...
INTO TABLE DEPT
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
(DEPTNO, DNAME, LOC)
BEGINDATA
12,RESEARCH,"SARATOGA"
100,"ACCOUNTING",CLEVELAND          -------> 10을 100으로 고쳤음..
11,"ART",SALEM
13,FINANCE,"BOSTON"
21,"SALES",PHILA.
22,"SALES",ROCHESTER
42,"INT'L","SAN FRAN"       

< 참고 사항 >

replace                 테이블의 기존 행을 모두 삭제(delete)하고 insert

append                  새로운 행을 기존의 데이타에 추가

insert                  비어 있는 테이블에 넣을 때

truncate                테이블의 기존 데이타를 모두 truncate 하고 insert

================================================================================

C:\>sqlldr userid=loader/loader control='C:\ulcase1.ctl'

SQL*Loader: Release 8.1.6.0.0 - Production on 화 Jan 29 16:20:18 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.

커밋 시점에 도달 - 논리 레코드 개수 7

================================================================================

SQL> RUN
  1* select count(*) from dept

  COUNT(*)
----------
        13       --------------> 13개입니다..

물론 필수적으로 컨트롤 파일과 데이타가 있으면 되지만....
데이타에 오류가 있는 경우는 문제가 됩니다..
그러므로 다음과 같이 5가지의 파일을 모두 나열해 줍니다...

================================================================================

C:\>sqlldr userid=loader/loader control='C:\ulcase1.ctl' log='c:\ulcase1.log' ba
d='c:\ulcase1.bad' discard='c:\ulcase1.dsc'

SQL*Loader: Release 8.1.6.0.0 - Production on 화 Jan 29 16:23:46 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.

커밋 시점에 도달 - 논리 레코드 개수 7

================================================================================

SQL> run
  1* select count(*) from dept

  COUNT(*)
----------
        19
       
자..이제 데이타가 안들어간 것에 대한 로그와 데이타를 살펴보도록 합니다..


ulcase1.log
================================================================================

SQL*Loader: Release 8.1.6.0.0 - Production on 화 Jan 29 16:23:46 2002

(c) Copyright 1999 Oracle Corporation.  All rights reserved.

제어 파일:    C:\ulcase1.ctl
데이터 파일:    C:\ulcase1.ctl
  잘못된 파일: c:\ulcase1.bad
  폐기 파일:   c:\ulcase1.dsc
(모든 폐기된 레코드 허용)

로드할 건수: ALL
생략 건수:  0
허용 오류수:  50
바인드 배열:  64 행, 최대 65536 바이트
계속:    지정 사항 없음
사용된 경로:      규약

테이블 DEPT, 로드되었습니다 개개의 논리 레코드로부터
이 테이블에 적당한 Insert 옵션: APPEND

   열 이름                        위치    Len   Term Encl 데이터유형
------------------------------ ---------- ----- ---- ---- ---------------------
DEPTNO                              FIRST     *   ,  O(") CHARACTER           
DNAME                                NEXT     *   ,  O(") CHARACTER           
LOC                                  NEXT     *   ,  O(") CHARACTER           

레코드 2: 기각됨 - 테이블 DEPT, 열 DEPTNO에 오류
ORA-01438: 지정한 정도를 초과한 값이 열에 지정되었습니다

테이블 DEPT:
  6 행들 로드되었습니다.
  데이터 오류 때문에 1 행(이)가 로드되지 않았습니다
  모든 WHEN절이 실패하여 0 행들(이)가 로드되지 않았습니다
  모든 필드가 NULL이어서 0 행들(이)가 로드되지 않았습니다


바인드 배열에 할당된 영역:             49536바이트(64 행)
바인드 배열외에 메모리에 할당된 영역:        0 바이트

생략된 논리 레코드의 합계:         0
읽어낸 논리 레코드의 합계:         7
거부된 논리 레코드의 합계:         1
폐기된 논리 레코드의 합계:         0

화 Jan 29 16:23:46 2002에 실행 개시
화 Jan 29 16:23:48 2002에 실행 종료

경과 시간:        00:00:02.49
CPU 시간:         00:00:00.07   
================================================================================

ulcase1.bad
================================================================================

100,"ACCOUNTING",CLEVELAND  

================================================================================

로그를 살펴보면...

'ORA-01438: 지정한 정도를 초과한 값이 열에 지정되었습니다'

라는 것이 보입니다..
10이 들어가야 하는 것이 100이 들어가서 컬럼에 들어갈 수 없다는 뜻이지여...헐헐~

자...이제 기초를 알았으니...
나머지는 컨트롤 파일에 대해서만 설명하고 SQL*Loader를 마치도록 하겠슴다..

ulcase2.ctl
================================================================================
LOAD DATA
INFILE 'ulcase2.dat'      --------> 데이타가 들어 있는 파일의 경로
INTO TABLE EMP

( EMPNO    POSITION(01:04) INTEGER EXTERNAL,
  ENAME    POSITION(06:15) CHAR,
  JOB      POSITION(17:25) CHAR,
  MGR      POSITION(27:30) INTEGER EXTERNAL,
  SAL      POSITION(32:39) DECIMAL EXTERNAL,
  COMM     POSITION(41:48) DECIMAL EXTERNAL,
  DEPTNO   POSITION(50:51) INTEGER EXTERNAL)

EMPNO    POSITION(01:04) INTEGER EXTERNAL의 의미는 empno 커럼의 데이타는
01열에서 04열 까지이다라는 것과 integer형으로 운영체제의 파일에 컬럼의 데이타형을
맞춘다는 의미입니다...

ulcase2.dat
================================================================================
7782 CLARK      MANAGER   7839  2572.50          10
7839 KING       PRESIDENT       5500.00          10
7934 MILLER     CLERK     7782   920.00          10
7566 JONES      MANAGER   7839  3123.75          20
7499 ALLEN      SALESMAN  7698  1600.00   300.00 30
7654 MARTIN     SALESMAN  7698  1312.50  1400.00 30
7658 CHAN       ANALYST   7566  3450.00          20


ulcase3.ctl
================================================================================
LOAD DATA
INFILE *
APPEND          ----------> 기존의 컬럼에 데이타 추가....

INTO TABLE EMP
FIELDS TERMINATED BY "," OPTIONALLY ENCLOSED BY '"'
(empno, ename, job, mgr,
hiredate DATE(20) "DD-Month-YYYY",       -------> 날짜 형식
sal, comm,
deptno   CHAR TERMINATED BY ':',     -------> 이 컬럼 구분의 종결자입니다...즉, 다음부터는 ':' 으로 컬럼 구분
projno,
loadseq  SEQUENCE(MAX,1) )          ---------> 자동생성 컬럼으로 시퀀스입니다..

BEGINDATA
7782, "Clark", "Manager", 7839, 09-June-1981, 2572.50,, 10:101
7839, "King", "President", , 17-November-1981, 5500.00,, 10:102
7934, "Miller", "Clerk", 7782, 23-January-1982, 920.00,, 10:102
7566, "Jones", "Manager", 7839, 02-April-1981, 3123.75,, 20:101
7499, "Allen", "Salesman", 7698, 20-February-1981, 1600.00, 300.00, 30:103
7654, "Martin", "Salesman", 7698, 28-September-1981, 1312.50, 1400.00, 30:103
7658, "Chan", "Analyst", 7566, 03-May-1982, 3450,, 20:101


SQL> run                    ---------> 데이타 적재후 결과...
  1* select * from emp

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO     PROJNO    LOADSEQ
---------- ---------- --------- ---------- -------- ---------- ---------- ---------- ---------- ----
      7782 Clark      Manager         7839 81/06/09     2572.5                    10        101          1
      7839 King       President            81/11/17       5500                    10        102          2
      7934 Miller     Clerk           7782 82/01/23        920                    10        102          3
      7566 Jones      Manager         7839 81/04/02    3123.75                    20        101          4
      7499 Allen      Salesman        7698 81/02/20       1600        300         30        103          5
      7654 Martin     Salesman        7698 81/09/28     1312.5       1400         30        103          6
      7658 Chan       Analyst         7566 82/05/03       3450                    20        101          7

7 개의 행이 선택되었습니다.


ulcase4.ctl
================================================================================

LOAD DATA
INFILE "ulcase4.dat"
DISCARDFILE "ulcase4.dis"
DISCARDMAX 999             ----------> 디스카드 파일은 최대 999까지 허용
REPLACE
CONTINUEIF (1) = '*'        -----------> 널값은 '*'로 대체한다...
INTO TABLE EMP

( EMPNO    POSITION(01:04) INTEGER EXTERNAL,
  ENAME    POSITION(06:15) CHAR,
  JOB      POSITION(17:25) CHAR,
  MGR      POSITION(27:30) INTEGER EXTERNAL,
  SAL      POSITION(32:39) DECIMAL EXTERNAL,
  COMM     POSITION(41:48) DECIMAL EXTERNAL,
  DEPTNO   POSITION(50:51) INTEGER EXTERNAL,
  HIREDATE POSITION(52:60) INTEGER EXTERNAL)
 
ulcase5.ctl
================================================================================

LOAD DATA
INFILE 'ulcase5.dat'
BADFILE 'ulcase5.bad'
DISCARDFILE 'ulcase5.dis'
REPLACE

INTO TABLE EMP
  (EMPNO    POSITION(1:4)   INTEGER EXTERNAL,
   ENAME    POSITION(6:15)  CHAR,
   DEPTNO   POSITION(17:18) CHAR,
   MGR      POSITION(20:23) INTEGER EXTERNAL)

INTO TABLE PROJ
-- PROJ has two columns, both not null: EMPNO and PROJNO
WHEN PROJNO != '   '
  (EMPNO    POSITION(1:4)   INTEGER EXTERNAL,
   PROJNO   POSITION(25:27) INTEGER EXTERNAL)   -- 1st proj

INTO TABLE PROJ
WHEN PROJNO != '   '
  (EMPNO    POSITION(1:4)   INTEGER EXTERNAL,
   PROJNO   POSITION(29:31) INTEGER EXTERNAL)   -- 2nd proj

INTO TABLE PROJ
WHEN PROJNO != '   '
  (EMPNO    POSITION(1:4)   INTEGER EXTERNAL,
   PROJNO   POSITION(33:35) INTEGER EXTERNAL)   -- 3rd proj
 
ulcase5.dat
================================================================================ 
1234 BAKER      10 9999 101 102 103
1234 JOKER      10 9999 777 888 999
2664 YOUNG      20 2893 425 abc 102
5321 OTOOLE     10 9999 321  55  40
2134 FARMER     20 4555 236 456
2414 LITTLE     20 5634 236 456  40
6542 LEE        10 4532 102 321  14
2849 EDDS       xx 4555     294  40
4532 PERKINS    10 9999  40
1244 HUNT       11 3452 665 133 456
123 DOOLITTLE  12 9940         132
1453 MACDONALD  25 5532     200 

결국 두개의 테이블에 하나의 데이타 파일가지고 데이타를 적재 시킨 것입니다..
눈여겨 볼 것은 when 을 사용한 것인데...
이것으로...데이타 파일에 있는 마지막에서 5번째 컬럼의 데이타에서부터...
7번째 컬럼의 데이타까지 모두 proj 테이블의 projno 컬럼에 적재 시킨것이 보입니다...

데이타 적재 결과.........

SQL> select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      1234 BAKER                      9999                                        10
      1234 JOKER                      9999                                        10
      5321 OTOOLE                     9999                                        10
      2134 FARMER                     4555                                        20
      2414 LITTLE                     5634                                        20
      6542 LEE                        4532                                        10
      4532 PERKINS                    9999                                        10
      1244 HUNT                       3452                                        11
       123 DOOLITTLE                  9940                                        12
      1453 MACDONALD                  5532                                        25

10 개의 행이 선택되었습니다.

SQL> select * from proj;

     EMPNO     PROJNO
---------- ----------
      1234        101
      1234        777
      5321        321
      2134        236
      2414        236
      6542        102
      4532         40
      1244        665
      1234        102
      1234        888
      5321         55
      2134        456
      2414        456
      6542        321
      1244        133
      1453        200
      1234        103
      1234        999
      5321         40
      2414         40
      6542         14
      1244        456
       123        132

23 개의 행이 선택되었습니다. 

ulcase6.dat
================================================================================ 

load data
infile 'ulcase6.dat'
replace
into table emp
sorted indexes (empix)      -----------> 인덱스로 정렬하여 적재합니다...직접경로일때만 사용가능..
(empno position(1:4),
ename position(6:15),
job position(17:25),
mgr position(27:30) nullif mgr=blanks,    --------> 널값이면 공백으로 넣는다..(공백은 널과 틀리다..)
sal position(32:39) nullif sal=blanks,
comm position(41:48) nullif comm=blanks,
deptno position(50:51) nullif empno=blanks)


머...이정도 까지 하겠슴다...

아래는....오라클의 Bulletin 에 있는 내용입니다..
참고하시기 바랍니다...

IMAGE FILE 을 LOAD하기
======================

300,000 byte의 binary(image)file을 load하기 위해서는 아래와 같은 control
file을 작성한다.

options (bindsize=350000)
load data
infile image.gif  "fix 60000"
replace
concatenate 5
into table xx
(f1 raw(300000))

* bindsize option은 SQL*Loder가 보통 64K인 buffer를 더 크게 잡게 해 준다.

* "fix 60000"은 o/s에 연관된 명령으로서 SQL*Loder가 data file에서   60,000 bytes를 읽게 하고,
  이것을 하나의 physical record로 취급하게
  한다. 이것은 보통 record delimiter로 사용되는 linefeed character를
  찾지 않게 한다.
* concatenate 5는 SQL*Loder가 다섯 개의 physical record로서 한개의 database
record를 만드는 것을 말한다. 이 logical record가 database 안에 long raw
column으로 직접 들어가게 된다.

SQL*Loder가 한번에 file을 single record처럼( "fix 300000"을 사용해서)
읽게 할 수는 없다. 왜냐하면 이것은 file로 부터 읽어내는 record size에
대해서 operating system이 가지는 한계인 64K에 걸릴 수 있기 때문이다.
만약 이와 같은 작업을 할 경우에는 SQL*Loder-510 error가 발생된다.

"fix n" option은 UNIX, PC 모두에서 사용될 수 있다. VMX에서는 "fix=n"즉
"fix=60000"이다.

300,000 byte을 한 record로 지정하였기 때문에 모든 image의 크기가 같기
전에는한 file에 하나의 image를 load할 수 있을 뿐이다. 이것은 원하는 image 마다
적절한 option을 가진 서로 다른 control file을 가지고 있어야 한다는 것이다.
그리고 실제 data보다 control file의 raw 길이를 명시해준 값이 크다면 남는 길이
만큼 SQL*Loder가 쓰레기 값을 채워 넣게 될 것이다.


LOADER 를 통한 LONGRAW DATA 올리는 예제
=======================================

CREATE TABLE MYPICS
(image long raw);

Table created.


LOAD DATA
INFILE  NX6.jpg "fix 65535"
CONCATENATE 10
INTO TABLE MYPICS
fields terminated by ':'
(IMAGE raw (120000))

The command line would look like this

sqlldr userid=scott/tiger control=image.ctl bindsize=250000 logfile=logimg


이미 Row 가 존재하는 Table 인 경우 Append 를 사용하여 추가한다.

(IMAGE2.CTL)

LOAD DATA
INFILE  NX6.jpg "fix 65535"
APPEND
CONCATENATE 10
INTO TABLE MYPICS
fields terminated by ':'
(IMAGE raw (120000))


sqlldr userid=scott/tiger control=image2.ctl bindsize=250000 log=log2imp

==================================================================
SQL*LOADER(8i) variable size field를 여러 table에 load하기 (FILLER)
==================================================================

SQL*LOADER 에서 variable length record와 variable size field를 가진 data file
을 여러 table에 load하는 방법을 소개하고자 한다.
( 8i new feature인 FILLER 절 사용)

SQL*LOADER SYNTAX
------------------
여러 table에 load하고자 할때에는 control file에 아래와 같이 하면 된다.
     ...
     INTO TABLE emp
         ...
     INTO TABLE emp1
         ...

fixed length field을 가진 data file을 여러 table에 같은 data을 load하고자
한다면 아래와 같다.

     ...
     INTO TABLE emp
        (empno   POSITION(1:4)  INTEGER EXTERNAL,
         ...        
     INTO TABLE emp1
        (empno   POSITION(1:4)  INTEGER EXTERNAL,
         ...

위와 같이 양쪽 table의 empno field에 각각의 load할 data로부터 1-4까지를 load
할수 있다. 그러나 field의 길이가 가변적이라면 위와 같이 POSITION절을 각 field에 사용할 수 없다.

예제 1>

     create table one (
        field_1  varchar2(20),
        field_2  varchar2(20),
        empno    varchar(10) );

     create table two (
        field_3  varchar2(20),
        empno    varchar(10) );

load할 record가 comma로 나누어지며 길이가 가변적이라고 가정하자.

<< data.txt >> - load할 data file

"this is field 1","this is field 2",12345678,"this is field 4"

<< test.ctl >> - control file

     load data infile 'data.txt'
     discardfile 'discard.txt'

     into table one
     replace
     fields terminated by ","
     optionally enclosed by  '"' (
     field_1,
     field_2,
     empno )

     into table two
     replace
     fields terminated by ","
     optionally enclosed by  '"' (
     field_3,
     dummy1 filler position(1),
     dummy2 filler,
     empno )

dummy1 field는 filler로 선언되었다. filler로 선언하면 table에 load하지 않는다.
two라는 table에는 dummy1이라는 field는 없으며 position(1)은 current record의
처음부터 시작해서 첫번째 field을 dummy1 filler item에 load한다는 것을 말한다.
그리고 두번째 field을 dummy2 filler item에 load한다. 세번째 field인, one이라는
table에 load되었던 employee number는 two라는 table에도 load되는 것이다,

<< 실행 >>

$sqlload scott/tiger control=test.ctl data=data.txt log=test.log bindsize=300000

$sqlplus scott/tiger
SQL> select * from one;

FIELD_1              FIELD_2              EMPNO
-------------------- -------------------- ----------
this is field 1      this is field 2      12345678

SQL> select * from two;

FIELD_3              EMPNO
-------------------- ----------
this is field 4      12345678 

예제 2>

create table testA (c1 number, c2 varchar2(10), c3 varchar2(10));

<< data1.txt >> - load할 data file

7782,SALES,CLARK
7839,MKTG,MILLER
7934,DEV,JONES

<< test1.ctl >>

  LOAD DATA
  INFILE 'data1.txt'

  INTO TABLE testA
  REPLACE
  FIELDS TERMINATED BY ","
  (
    c1        INTEGER EXTERNAL,
    c2 FILLER CHAR,
    c3        CHAR
  )

<< 실행 >>

$ sqlload scott/tiger control=test1.ctl data=data1.txt log=test1.log

$ sqlplus scott/tiger
SQL> select * from testA;

        C1 C2         C3
---------- ---------- ----------
      7782            CLARK
      7839            MILLER
      7934            JONES     


아~~
머...퍼서 하고..이미 만들어진 예제로 했지만...
이것도 정말 눈알 빠지것슴다...헐헐~~

출처: http://databaser.net/moniwiki/wiki.php/SQLLoader%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95