【聽海日誌】之Oracle SQL*LOADER

聽海★藍心夢發表於2012-03-20

一、SQL*LOADER簡介

1SQL*LOADER的基本特點

Ø  能裝入不同資料型別檔案及多個資料檔案的資料。

Ø  可裝入固定格式,自由定界以及可度長格式的資料。

Ø  可以裝入二進位制,壓縮十進位制資料。

Ø  一次可對多個表裝入資料。

Ø  連線多個物理記錄裝到一個記錄中。

Ø  對一單記錄分解再裝入到表中。

Ø  可以用 數對制定列生成唯一的KEY

Ø  可對磁碟或磁帶資料檔案裝入製表中。

Ø  提供裝入錯誤報告。

Ø  可以將檔案中的整型字串,自動轉成壓縮十進位制並裝入列表中。

2、控制檔案

控制檔案是用一種語言寫的文字檔案,這個文字檔案能被SQL*LOADER識別。SQL*LOADER根據控制檔案可以找到需要載入的資料。並且分析和解釋這些資料。控制檔案由三個部分組成:

Ø  全域性選件、行、跳過的記錄數等。

Ø  INFILE子句指定的輸入資料。

Ø  資料特性說明。

3、輸入檔案

對於 SQL*Loader, 除控制檔案外就是輸入資料。SQL*Loader可從一個或多個指定的檔案中讀出資料。如果資料是在控制檔案中指定,就要在控制檔案中寫成INFILE * 格式。當資料是固定的格式(長度一樣)時且是在檔案中得到時,要用INFILE "fix n",如:

load data

infile 'example.dat' "fix 11"

into table example

fields terminated by ',' optionally enclosed by '"'

(col1 char(5),

col2 char(7))

example.dat:

001, cd, 0002,fghi,

00003,lmn,

1, "pqrs",

0005,uvwx,

當資料是可變格式(長度不一樣)時且是在檔案中得到時,要用INFILE "var n"。如:

load data

infile 'example.dat' "var 3"

into table example

fields terminated by ',' optionally enclosed by '"'

(col1 char(5),

col2 char(7))

example.dat:

009hello,cd,010world,im,

012my,name is,

4、壞檔案

壞檔案包含那些被SQL*Loader拒絕的記錄。被拒絕的記錄可能是不符合要求的記錄。壞檔案的名字由 SQL*Loader命令的BADFILE 引數來給定。

5、日誌檔案及日誌資訊

當SQL*Loader 開始執行後,它就自動建立日誌檔案。日誌檔案包含有載入的總結,載入中的錯誤資訊等。

二、控制檔案語法

1、控制檔案的格式如下

OPTIONS { [SKIP=integer] [ LOAD = integer ]

[ERRORS = integer] [ROWS=integer]

[BINDSIZE=integer] [SILENT=(ALL|FEEDBACK|ERROR|DISCARD) ] )

LOAD[DATA]

[ { INFILE | INDDN } {file | * }

[STREAM | RECORD | FIXED length [BLOCKSIZE size]|

VARIABLE [length] ]

[ { BADFILE | BADDN } file ]

{DISCARDS | DISCARDMAX} integr ]

[ {INDDN | INFILE} . . . ]

[ APPEND | REPLACE | INSERT ]

[RECLENT integer]

[ { CONCATENATE integer |

CONTINUEIF { [THIS | NEXT] (start[: end])LAST }

Operator { 'string' | X 'hex' } } ]

INTO TABLE [user.]table

[APPEND | REPLACE|INSERT]

[WHEN condition [AND condition]...]

[FIELDS [delimiter] ]

(

column {

RECNUM | CONSTANT value |

SEQUENCE ( { integer | MAX |COUNT} [, increment] ) |

[POSITION ( { start [end] | * [ + integer] }

) ]

datatype

[TERMINATED [ BY ] {WHITESPACE| [X] 'character' } ]

[ [OPTIONALLY] ENCLOSE[BY] [X]'charcter']

[NULLIF condition ]

[DEFAULTIF condotion]

}

[ ,...]

)

[INTO TABLE...]

[BEGINDATA]

2、要載入的資料檔案

Ø  INFILEINDDN是同義詞,它們後面都是要載入的資料檔案。如果用*則表示資料就在控制檔案內。在INFILE後可以跟幾個檔案。

Ø  STRAM 表示一次讀一個位元組的資料。新行代表新物理記錄(邏輯記錄可由幾個物理記錄組成)。

Ø  RECORD 使用宿主作業系統檔案及記錄管理系統。如果資料在控制檔案中則使用這種方法。

Ø  FIXED length 要讀的記錄長度為length位元組。

Ø  VARIABLE 被讀的記錄中前兩個位元組包含的長度,length 記錄可能的長度。預設為8k位元組。

Ø  BADFILE和BADDN同義。Oracle 不能載入資料到資料庫的那些記錄。

Ø  DISCARDFILE和DISCARDDN是同義詞。記錄沒有透過的資料。

Ø  DISCARDS和DISCARDMAX是同義詞。Integer 為最大放棄的檔案個數。

3、載入的方法

Ø  APPEND 給表新增行。

Ø  INSERT 給空表增加行(如果表中有記錄則退出)。

Ø  REPLACE 先清空表在載入資料。

Ø  RECLEN 用於兩種情況:

Ø  SQLLDR不能自動計算記錄長度。

Ø  使用者想看壞檔案的完整記錄時。對於後一種,Oracle只能按常規把壞記錄部分寫到錯誤的地方。如果看整條記錄,則可以將整條記錄寫到壞檔案中。

Ø  指定最大的記錄長度:

CONCATENATE 允許使用者設定一個整數,表示要組合邏輯記錄的數目。

4、建立邏輯記錄

Ø  THIS檢查當前記錄條件,如果為真則連線下一個記錄。

Ø  NEXT檢查下一個記錄條件。如果為真,則連線下一個記錄到當前記錄來。

Ø  Start: end表示要檢查在THISNEXT字串是否存在繼續串的列,以確定是否進行連線。如:continueif next(1-3)='WAG' continueif next(1-3)=X'0d03if'

5、指定要載入的表

INTO TABLE 要加的表名。WHEN select WHERE類似。用來檢查記錄的情況,如:when(3-5)='SSM' and (22)='*"

6、介紹並括起記錄中的欄位

FIELDS給出記錄中欄位的分隔符,FIELDS格式為:

FIELDS [TERMIALED [BY] {WHITESPACE | [X] 'charcter'} ][ [ OPTIONALLY] ENCLOSE [BY] [X]'charcter' ]

TERMINATED 讀完前一個欄位即開始讀下一個欄位直到介紹。WHITESPACE 是指結束符是空格的意思。包括空格、Tab、換行符、換頁符及回車符。如果是要判斷但字元,可以用單引號括起,如X'1B'等。OPTIONALLY ENCLOSED 表示資料應由特殊字元括起來。也可以括在TERMINATED字元內。使用OPTIONALLY要同時用TERMINLATEDENCLOSED 指兩個分界符內的資料。如果同時用 ENCLOSEDTERMINAED ,則它們的順序決定計算的順序。

7、定義列

Ø  column 是表列名。列的取值可以是:

BECHUM 表示邏輯記錄數。第一個記錄為1,2個記錄為2

CONSTANT 表示賦予常數。

SEQUENCE 表示序列可以從任意序號開始,格式為:

SEQUENCE { integer | MAX |COUNT} [,increment]

Ø  POSITION 給出列在邏輯記錄中的位置。可以是絕對的,或相對前一列的值。格式為:

POSITION ( {start[end] | * [+integer] } )

Ø  Start 開始位置

* 表示前欄位之後立刻開始。

+ 從前列開始向後條的位置數。

8、定義資料型別

可以定義14種資料型別:

CHAR

DATE

DECIMAL EXTERNAL

DECIMAL

DOUBLE

FLOAT

FLOAT EXTERNAL

GRAPHIC EXTERNAL

INTEGER

INTEGER EXTERNAL

SMALLINT

VARCHAR

VARGRAPHIC

 

1.字元型別資料

CHAR[ (length)] [delimiter] length預設為 1.

2.日期型別資料

DATE [ ( length)]['date_format' [delimiter],使用to_date函式來限制。

3.字元格式中的十進位制

DECIMAL EXTERNAL [(length)] [delimiter]

用於常規格式的十進位制數(不是二進位制=> 一個位等於一個bit)。

4.壓縮十進位制格式資料

DECIMAL digtial [,precision]

5.雙精度符點二進位制

DOUBLE

6.普通符點二進位制

FLOAT

7.字元格式符點數

FLOAT EXTERNAL [ (length) ] [delimiter]

8.雙位元組字串資料

GRAPHIC [ (legth)]

9.雙位元組字串資料

GRAPHIC EXTERNAL[ (legth)]

10.常規全字二進位制整數

INTEGER

11.字元格式整數

INTEGER EXTERNAL

12.常規全字二進位制資料

SMALLINT

13.可變長度字串

VARCHAR

14.可變雙位元組字串資料

VARGRAPHIC

三、寫控制檔案CTL

資料檔案的內容可以在OS下的一個檔案或跟在控制檔案下的具體資料。資料檔案可以是:

1、二進位制與字元格式:LOADER可以把二進位制檔案讀(當成字元讀)列表中

2、固定格式:記錄中的資料、資料型別、 資料長度固定。

3、可變格式:每個記錄至少有一個可變長資料欄位,一個記錄可以是一個連續的字串。資料段的分界(如姓名、年齡)如用“,”作欄位的 ;用,"’作資料括號等

4 LOADER可以使用多個連續欄位的物理記錄組成一個邏輯記錄,記錄檔案執行情況檔案包括以下內容:

1.) 執行日期:軟體版本號

2.) 全部輸入,輸出檔名;對命令列的展示資訊,補充資訊

3.) 對每個裝入資訊報告:如表名,裝入情況;對初始裝入,加截入或更新裝入的選擇情況,欄資訊

4.) 資料錯誤報告:錯誤碼;放棄記錄報告

5.) 每個裝X報告:裝入行;裝入行數,可能跳過行數;可能拒絕行數;可能放棄行數等

6.) 統計概要:使用空間(包大小,長度);讀入記錄數,裝入記錄數,跳過記錄數;拒絕記錄數,放棄記錄數;執行時間等。

四、sql load的一點小總結

1SQL*LOAD執行命令

sqlldr userid=lgone/tiger control=a.ctl

LOAD DATA

INFILE 't.dat'     --- 要匯入的檔案.

INFILE 'tt.date'     --- 匯入多個檔案

INFILE *     ---  要匯入的內容就在control檔案裡下面的BEGINDATA後面就是匯入的內容

INTO TABLE table_name      --- 指定裝入的表

BADFILE 'c:bad.txt'      ---指定壞檔案地址

24種裝入表的方式

APPEND       ---原先的表有資料 就加在後面

INSERT        ---裝載空表 如果原先的表有資料 sqlloader會停止 預設值

REPLACE      ---原先的表有資料 原先的資料會全部刪除

TRUNCATE     ---指定的內容和replace的相同 會用truncate語句刪除現存資料

指定的TERMINATED可以在表的開頭 也可在表的內部欄位部分

FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'

裝載這種資料: 10,lg,"""lg""","lg,lg"

在表中結果: 10 lg "lg" lg,lg

TERMINATED BY X '09'            --- 以十六進位制格式 '09' 表示的

TERMINATED BY WRITESPACE    --- 裝載這種資料: 10 lg lg

TRAILING NULLCOLS             --- 表的欄位沒有對應的值時允許為空

3表的欄位

(

col_1 , col_2 ,col_filler FILLER       --- FILLER關鍵字此列的數值不會被裝載: lg,lg,not 結果 lg lg

)

當沒宣告FIELDS TERMINATED BY ','

(

col_1 [interger external] TERMINATED BY ',' ,

col_2 [date "dd-mon-yyy"] TERMINATED BY ',' ,

col_3 [char] TERMINATED BY ',' OPTIONALLY ENCLOSED BY 'lg'

)

當沒宣告FIELDS TERMINATED BY ','用位置告訴欄位裝載資料

(

col_1 position(1:2),

col_2 position(3:10),

col_3 position(*:16),            --- 這個欄位的開始位置在前一欄位的結束位置

col_4 position(1:16),

col_5 position(3:10) char(8)      --- 指定欄位的型別

)

BEGINDATA         --- 對應開始的INFILE * 要匯入的內容就在control檔案裡

10,Sql,what

20,lg,show

注意begindata後的數值前面不能有空格

4普通裝載

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'

(DEPTNO,

DNAME,

LOC

)

BEGINDATA

10,Sales,"""USA"""

20,Accounting,"Virginia,USA"

30,Consulting,Virginia

40,Finance,Virginia

50,"Finance","",Virginia     --- loc列將為空

60,"Finance",,Virginia       --- loc列將為空

5Terminated載入

FIELDS TERMINATED BY WHITESPACE FIELDS TERMINATED BY x'09' 的情況

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

FIELDS TERMINATED BY WHITESPACE

-- FIELDS TERMINATED BY x'09'

(DEPTNO,

DNAME,

LOC

)

BEGINDATA

10 Sales Virginia

6指定不裝載那一列

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'

( DEPTNO,

FILLER_1 FILLER,     ---下面的 "Something Not To Be Loaded" 將不會被裝載

DNAME,

LOC

)

BEGINDATA

20,Something Not To Be Loaded,Accounting,"Virginia,USA"

7position的列子

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

( DEPTNO position(1:2),

DNAME position(*:16),        --- 這個欄位的開始位置在前一欄位的結束位置

LOC position(*:29),

ENTIRE_LINE position(1:29)

)

BEGINDATA

10Accounting Virginia,USA

8TRAILING NULLCOLS的使用

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

FIELDS TERMINATED BY ','

TRAILING NULLCOLS      --- 其實下面的ENTIRE_LINEBEGINDATA後面的資料中是沒有直接對應的列的值的如果第一行改為 10,Sales,Virginia,1/5/2000,, 就不用TRAILING NULLCOLS

(DEPTNO,

DNAME "upper(:dname)",     --- 使用函式

LOC "upper(:loc)",

LAST_UPDATED date 'dd/mm/yyyy',

ENTIRE_LINE ":deptno||:dname||:loc||:last_updated"

)

BEGINDATA

10,Sales,Virginia,1/5/2000

20,Accounting,Virginia,21/6/1999

30,Consulting,Virginia,5/1/2000

40,Finance,Virginia,15/3/2001

9使用自定義的函式

create or replace

function my_to_date( p_string in varchar2 ) return date

as

type fmtArray is table of varchar2(25);

l_fmts fmtArray := fmtArray( 'dd-mon-yyyy', 'dd-month-yyyy',

'dd/mm/yyyy',

'dd/mm/yyyy hh24:mi:ss' );

l_return date;

begin

for i in 1 .. l_fmts.count

loop

begin

l_return := to_date( p_string, l_fmts(i) );

exception

when others then null;

end;

EXIT when l_return is not null;

end loop;

if ( l_return is null )

then

l_return :=

new_time( to_date('01011970','ddmmyyyy') + 1/24/60/60 *

p_string, 'GMT', 'EST' );

end if;

return l_return;

end;

/

LOAD DATA

INFILE *

INTO TABLE DEPT

REPLACE

FIELDS TERMINATED BY ','

TRAILING NULLCOLS

(DEPTNO,

DNAME "upper(:dname)",

LOC "upper(:loc)",

LAST_UPDATED "my_to_date( :last_updated )"    --- 使用自定義的函式

)

BEGINDATA

10,Sales,Virginia,01-april-2001

20,Accounting,Virginia,13/04/2001

30,Consulting,Virginia,14/04/2001 12:02:02

40,Finance,Virginia,987268297

50,Finance,Virginia,02-apr-2001

60,Finance,Virginia,Not a date

10合併多行記錄為一行記錄

LOAD DATA

INFILE *

concatenate 3        --- 透過關鍵字concatenate 把幾行的記錄看成一行記錄

INTO TABLE DEPT

replace

FIELDS TERMINATED BY ','

(DEPTNO,

DNAME "upper(:dname)",

LOC "upper(:loc)",

LAST_UPDATED date 'dd/mm/yyyy'

)

BEGINDATA

10,Sales,     --- 其實這3行看成一行10,Sales,Virginia,1/5/2000

Virginia,

1/5/2000

這列子用 continueif list="," 也可以告訴sqlldr在每行的末尾找逗號找到逗號就把下一行附加到上一行

LOAD DATA

INFILE *

continueif this(1:1) = '-'      --- 找每行的開始是否有連線字元 - 有就把下一行連線為一行

-10,Sales,Virginia,

1/5/2000 就是一行 10,Sales,Virginia,1/5/2000其中1:1 表示從第一行開始並在第一行結束還有continueif next continueif list最理想

INTO TABLE DEPT

replace

FIELDS TERMINATED BY ','

(DEPTNO,

DNAME "upper(:dname)",

LOC "upper(:loc)",

LAST_UPDATED date 'dd/mm/yyyy'

)

BEGINDATA // 但是好象不能象右面的那樣使用

-10,Sales,Virginia, -10,Sales,Virginia,

1/5/2000 1/5/2000

-40, 40,Finance,Virginia,13/04/2001

Finance,Virginia,13/04/2001

11載入每行的行號

load data

infile *

into table t

replace

( seqno RECNUM         --- 載入每行的行號

text Position(1:1024))

BEGINDATA

fsdfasj       --- 自動分配一行號給載入表tseqno欄位此行為1

fasdjfasdfl    --- 此行為 2 ...

五、例項

SQL*LOADERORACLE的資料載入工具,通常用來將作業系統檔案遷移到ORACLE資料庫中。SQL*LOADER是大型資料倉儲選擇使用的載入方法,因為它提供了最快速的途徑(DIRECTPARALLEL)。現在,我們拋開其理論不談,用例項來使您快速掌握SQL*LOADER的使用方法。

SQL*LOADER只能匯入純文字,所以我們現在開始以例項來講解其用法。

1整理資料來源

假設表已經存在:

test@ORCL> create table t_sqlload(

resultid varchar2(500),

website varchar2(500),

ipport varchar2(500),

status varchar2(500))

/

資料來源result.txt,欲倒入ORACLEtest使用者下。result.txt內容:

1,預設 Web 站點,192.168.2.254:80:,RUNNING

2,other,192.168.2.254:80:test.com,STOPPED

3,third,192.168.2.254:81:thirdabc.com,RUNNING

從中,我們看出4列,分別以逗號分隔,為變長字串。

2、制定控制檔案

控制檔案result.ctl內容:

load data

infile 'result.txt'

into table t_sqlload

(resultid char terminated by ',',

website char terminated by ',',

ipport char terminated by ',',

status char terminated by whitespace)

說明:

Infile指資料來源檔案,這裡我們省略了預設的 discardfile result.dsc  badfile  result.bad

into table resultxt預設是INSERT,也可以into table resultxt APPEND為追加方式,或REPLACE

terminated by ','指用逗號分隔

terminated by whitespace結尾以空白分隔

注:infileresult.ctl一般就放在sqlldr的當前目錄

3、此時我們執行載入:

[oracle@localhost scripts]$ sqlldr userid=test/admin control=result.ctl log=result.out

SQL*Loader: Release 11.2.0.1.0 - Production on чǚһ 3Ղ 19 16:10:58 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Commit point reached - logical record count 3

已經成功!我們可以透過日誌檔案來分析其過程:resulthis.out內容如下:

[oracle@localhost scripts]$ more result.out

SQL*Loader: Release 11.2.0.1.0 - Production on чǚһ 3Ղ 19 16:10:58 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

 

Control File:   result.ctl

Data File:      result.txt

  Bad File:     result.bad

  Discard File:  none specified

 

 (Allow all discards)

 

Number to load: ALL

Number to skip: 0

Errors allowed: 50

Bind array:     64 rows, maximum of 256000 bytes

Continuation:    none specified

Path used:      Conventional

 

Table T_SQLLOAD, loaded from every logical record.

Insert option in effect for this table: INSERT

 

   Column Name                  Position   Len  Term Encl Datatype

------------------------------ ---------- ----- ---- ---- ---------------------

RESULTID                            FIRST     *   ,       CHARACTER            

WEBSITE                              NEXT     *   ,       CHARACTER           

IPPORT                               NEXT     *   ,       CHARACTER           

STATUS                               NEXT     *  WHT      CHARACTER           

 

Table T_SQLLOAD:

  3 Rows successfully loaded.

  0 Rows not loaded due to data errors.

  0 Rows not loaded because all WHEN clauses were failed.

  0 Rows not loaded because all fields were null.

 

Space allocated for bind array:                  66048 bytes(64 rows)

Read   buffer bytes: 1048576

 

Total logical records skipped:          0

Total logical records read:             3

Total logical records rejected:         0

Total logical records discarded:        0

 

Run began on чǚһ 3Ղ  19 16:10:58 2012

Run ended on чǚһ 3Ղ  19 16:11:01 2012

 

Elapsed time was:     00:00:02.78

CPU time was:         00:00:00.01

4併發操作

sqlldr userid=/ control=result1.ctl direct=true parallel=true

sqlldr userid=/ control=result2.ctl direct=true parallel=true

sqlldr userid=/ control=result2.ctl direct=true parallel=true

當載入大量資料時,最好使用nologging抑制日誌的產生:

SQL>ALTER TABLE RESULTXT nologging;

這樣不產生REDO LOG,可以提高效率。然後在CONTROL檔案中load data上面加一行:unrecoverable此選項必須要與DIRECT共同應用。

在併發操作時,ORACLE聲稱可以達到每小時處理100GB資料的能力!其實,估計能到110G就算不錯了,開始可用結構相同的檔案,但只有少量資料,成功後開始載入大量資料,這樣可以避免時間的浪費。

5有關SQLLDR的問題

控制檔案input.ctl,內容如下:

load data          --1、控制檔案標識

infile 'test.txt'         --2、要輸入的資料檔名為test.txt

append into table test    --3、向表test中追加記錄

fields terminated by X'09'  --4、欄位終止於X'09',是一個製表符(TAB

(id,username,password,sj)  --5定義列對應順序

其中append為資料裝載方式,還有其他選項:

ainsert,為預設方式,在資料裝載開始時要求表為空

bappend,在表中追加新記錄

creplace,刪除舊記錄,替換成新裝載的記錄

dtruncate,同上

6Excel資料導Oracle

EXCEL檔案另存為CSV(逗號分隔)(*.csv)控制檔案就改為用逗號分隔

LOAD DATA

INFILE 'result.csv'

APPEND INTO TABLE t

FIELDS TERMINATED BY ","

(no_id, username, ph_number)

Csv檔案內容:

[oracle@localhost scripts]$ more result.ctl

load data

infile 'result.csv'

into table t

(

no_id char terminated by ',',

username char terminated by ',',

ph_number char terminated by ',')

執行sqlldr開始匯入:

[oracle@localhost scripts]$ sqlldr userid=test/admin control=result.ctl log=result2.out

SQL*Loader: Release 11.2.0.1.0 - Production on чǚһ 3Ղ 19 17:22:39 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Commit point reached - logical record count 14

資料驗證:

test@ORCL> select * from t;

NO_ID             USERNAME            PH_NUMBER

-------------------- -------------------- --------------------

10001               測試01              13562485246

10002               zjaxi02                13562485247

10003               zjaxi03                13562485248

10004               zjaxi04                13562485249

10005               zjaxi05                13562485250

10006               zjaxi06                13562485251

10007               zjaxi07                13562485252

10008               zjaxi08                13562485253

10009               zjaxi09                13562485254

10010               zjaxi10                13562485255

10011               zjaxi11                13562485256

10012               zjaxi12                13562485257

10013               zjaxi13                13562485258

10014               zjaxi14                13562485259

 

14 rows selected.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/751371/viewspace-719156/,如需轉載,請註明出處,否則將追究法律責任。

相關文章