SPOOL、SQLLOADER數據導出導入的一點小總結

一、SQLLOADER的CONTROL文件 sql

基本格式: 數據庫

OPTIONS (ERRORS=1000)
LOAD DATA
INFILE 'T.DAT' // 要導入的數據文件(格式1)
//INFILE 'TT.DAT' // 導入多個文件(能夠和格式1並列使用)
//INFILE * // 要導入的內容就在CONTROL文件裏 下面的BEGINDATA後面就是導入的內容(和格式1互斥使用)

APPEND INTO TABLE TABLE_NAME // 指定裝入的表(這裏有幾種加載方式)

//如下是4種裝入表的方式
//APPEND // 原先的表有數據就加在後面
// INSERT // 裝載空表,若是原先的表有數據SQLLOADER會中止默認值
// REPLACE // 原先的表有數據 原先的數據會所有刪除
// TRUNCATE // 指定的內容和REPLACE的相同 會用TRUNCATE語句刪除現存數據

BADFILE 'C:BAD.TXT' // 指定壞文件地址

FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
// 裝載這種數據: "10","20","30","40","50"
// TERMINATED BY X'09' // 以十六進制格式'09'表示文本文件用TAB鍵分隔
// 示例文本數據: "10" "20" "30" "40" "50"
// TERMINATED BY WHITESPACE // 裝載這種數據: "10" "lg" "lg"

TRAILING NULLCOLS ************* 表的字段沒有對應的值時容許爲空

************* 下面是表的字段
(COL_1 , COL_2 ,COL_FILLER FILLER // FILLER 關鍵字 此列的數值不會被裝載)

//指定的TERMINATED能夠在表的開頭 也可在表的內部字段部分
// 當沒聲明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 '"'
// )
// 當沒聲明FIELDS TERMINATED BY ','用位置告訴字段裝載數據
// (
// COL_1 POSITION(1:2),
// COL_2 POSITION(3:10),
// COL_3 POSITION(*:16), // 這個字段的開始位置在前一字段的結束位置
// COL_4 POSITION(3:10) CHAR(8), // 指定字段的類型
// COL_5 POSITION(3:10) "TRIM(:COL_5)", // 擠壓兩端空格
// COL_6 POSITION(3:10) "SEQ.NEXTVAL", // 取SEQUENCE值
// )

BEGINDATA // 對應開始的 INFILE * 要導入的內容就在CONTROL文件裏
10,20,30
20,30,40
//********************************************************************************//
CONTROL文件示例:
//注意BEGINDATA後的數值前面不能有空格

1 ***** 普通裝載
LOAD DATA
INFILE *
REPLACE INTO TABLE DEPT
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 列將爲空

2 ***** FIELDS TERMINATED BY WHITESPACE 和 FIELDS TERMINATED BY X'09' 的狀況
LOAD DATA
INFILE *
REPLACE INTO TABLE DEPT
FIELDS TERMINATED BY WHITESPACE
-- FIELDS TERMINATED BY X'09'
(DEPTNO,
DNAME,
LOC
)
BEGINDATA
10 Sales Virginia

3 ***** 指定不裝載那一列
LOAD DATA
INFILE *
REPLACE INTO TABLE DEPT
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"

4 ***** POSITION的列子
LOAD DATA
INFILE *
REPLACE INTO TABLE DEPT
( DEPTNO POSITION(1:2),
DNAME POSITION(*:16), // 這個字段的開始位置在前一字段的結束位置
LOC POSITION(*:29),
ENTIRE_LINE POSITION(1:29)
)
BEGINDATA
10ACCOUNTING VIRGINIA,USA

5 ***** 使用函很多天期的一種表達 TRAILING NULLCOLS的使用
LOAD DATA
INFILE *
REPLACE INTO TABLE DEPT
FIELDS TERMINATED BY ','
TRAILING NULLCOLS // 其實下面的ENTIRE_LINE在BEGINDATA後面的數據中是沒有直接對應
// 的列的值 若是第一行改成 10,Sales,Virginia,1/5/2000,, 就不用TRAILING NULLCOLS了
(DEPTNO,
DNAME "UPPER(NAME)", // 使用函數
LOC "UPPER(:LOC)",
LAST_UPDATED DATE 'DD/MM/YYYY', // 日期的一種表達方式 還有'DD-MON-YYYY' 等
ENTIRE_LINE "EPTNO||NAME||: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

6 ***** 使用自定義的函數 // 解決的時間問題
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 *
REPLACE INTO TABLE DEPT
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
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

7 ***** 合併多行記錄爲一行記錄
LOAD DATA
INFILE *
CONCATENATE 3 // 經過關鍵字CONCATENATE 把幾行的記錄當作一行記錄
INTO TABLE DEPT
REPLACE //注意這個例子格式與前邊有些不一樣
FIELDS TERMINATED BY ','
(DEPTNO,
DNAME "UPPER(NAME)",
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

8 ***** 載入每行的行號
LOAD DATA
INFILE *
INTO TABLE T
REPLACE
( SEQNO RECNUM //載入每行的行號
TEXT POSITION(1:1024))
BEGINDATA
fsdfasj //自動分配一行號給載入 表t 的seqno字段 此行爲 1
fasdjfasdfl // 此行爲 2 ...

9 ***** 載入有換行符的數據
注意: UNIX 和 WINDOWS 不一樣 n & /n
< 1 > 使用一個非換行符的字符
LOAD DATA
INFILE *
INTO TABLE DEPT
REPLACE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
LOC "UPPER(:LOC)",
LAST_UPDATED "MY_TO_DATE( :LAST_UPDATED )",
COMMENTS "REPLACE(:COMMENTS,'N',CHR(10))" // REPLACE 的使用幫助轉換換行符
)
BEGINDATA
10,Sales,Virginia,01-april-2001,This is the SalesnOffice in Virginia
20,Accounting,Virginia,13/04/2001,This is the AccountingnOffice in Virginia
30,Consulting,Virginia,14/04/2001 12:02:02,This is the ConsultingnOffice in Virginia
40,Finance,Virginia,987268297,This is the FinancenOffice in Virginia

< 2 > 使用fix屬性
LOAD DATA
INFILE DEMO17.DAT "FIX 101"
INTO TABLE DEPT
REPLACE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
LOC "UPPER(:LOC)",
LAST_UPDATED "MY_TO_DATE( :LAST_UPDATED )",
COMMENTS
)
BEGINDATA
10,Sales,Virginia,01-april-2001,This is the Sales
Office in Virginia
20,Accounting,Virginia,13/04/2001,This is the Accounting
Office in Virginia
30,Consulting,Virginia,14/04/2001 12:02:02,This is the Consulting
Office in Virginia
40,Finance,Virginia,987268297,This is the Finance
Office in Virginia

// 這樣裝載會把換行符裝入數據庫,下面的方法就不會,但要求數據的格式不一樣

LOAD DATA
INFILE DEMO18.DAT "FIX 101"
INTO TABLE DEPT
REPLACE
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
LOC "UPPER(:LOC)",
LAST_UPDATED "MY_TO_DATE( :LAST_UPDATED )",
COMMENTS
)
BEGINDATA
10,Sales,Virginia,01-april-2001,"This is the Sales
Office in Virginia"
20,Accounting,Virginia,13/04/2001,"This is the Accounting
Office in Virginia"
30,Consulting,Virginia,14/04/2001 12:02:02,"This is the Consulting
Office in Virginia"
40,Finance,Virginia,987268297,"This is the Finance
Office in Virginia"

< 3 > 使用var屬性
LOAD DATA
INFILE DEMO19.DAT "VAR 3"
// 3 告訴每一個記錄的前3個字節表示記錄的長度 如第一個記錄的 071 表示此記錄有 71 個字節
INTO TABLE DEPT
REPLACE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
LOC "UPPER(:LOC)",
LAST_UPDATED "MY_TO_DATE( :LAST_UPDATED )",
COMMENTS
)
BEGINDATA
07110,Sales,Virginia,01-april-2001,This is the Sales
Office in Virginia
07820,Accounting,Virginia,13/04/2001,This is the Accounting
Office in Virginia
08730,Consulting,Virginia,14/04/2001 12:02:02,This is the Consulting
Office in Virginia
07140,Finance,Virginia,987268297,This is the Finance
Office in Virginia

< 4 > 使用STR屬性
// 最靈活的一中 可定義一個新的行結尾符 WIN 回車換行 : CHR(13)||CHR(10)

此列中記錄是以 A|RN 結束的
SELECT UTL_RAW.CAST_TO_RAW('|'||CHR(13)||CHR(10)) FROM DUAL;
結果 7C0D0A

LOAD DATA
INFILE DEMO20.DAT "STR X'7C0D0A'"
INTO TABLE DEPT
REPLACE
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(DEPTNO,
DNAME "UPPER(NAME)",
LOC "UPPER(:LOC)",
LAST_UPDATED "MY_TO_DATE( :LAST_UPDATED )",
COMMENTS
)
BEGINDATA
10,Sales,Virginia,01-april-2001,This is the Sales
Office in Virginia|
20,Accounting,Virginia,13/04/2001,This is the Accounting
Office in Virginia|
30,Consulting,Virginia,14/04/2001 12:02:02,This is the Consulting
Office in Virginia|
40,Finance,Virginia,987268297,This is the Finance
Office in Virginia|

10 *****象這樣的數據 用 nullif 子句 10-jan-200002350Flipper seemed unusually hungry today. 10510-jan-200009945Spread over three meals. ID POSITION(1:3) NULLIF ID=BLANKS // 這裏能夠是BLANKS 或者別的表達式 // 下面是另外一個列子 第一行的 1 在數據庫中將成爲 NULL LOAD DATA INFILE * INTO TABLE T REPLACE (N POSITION(1:2) INTEGER EXTERNAL NULLIF N='1', V POSITION(3:8) ) BEGINDATA 1 10 20lg //********************************************************************************// SQLLOADER的命令: SQLLDR USERID=SYS/SYS@DB_SERVICE CONTROL=XXXX.CTL LOG=XXXX.LOG BINDSIZE=1048576 ROWS=100 ERRORS=10000 READSIZE=2097152 SILENT=(HEADER,FEEDBACK) 關於這些參數的幫助在命令行直接執行SQLLDR能夠獲得,這裏指出BINDSIZE不該該大於READSIZE的值。 關於SPOOL導出文本數據的一些格式建議: SQL*PLUS環境設置SET NEWPAGE NONE HEADING OFF SPACE 0 PAGESIZE 0 TRIMOUT ON TRIMSPOOL ON LINESIZE 2500 注:LINESIZE要稍微設置大些,省得數據被截斷,它應和相應的TRIMSPOOL結合使用防止導出的文本有太多的尾部空格。 可是若是LINESIZE設置太大,會大大下降導出的速度,另外在WINDOWS下導出最好不要用PLSQL導出,速度比較慢, 直接用COMMEND下的SQLPLUS命令最小化窗口執行。 對於SPOOL數據的SQL,最好要本身定義格式,以方便咱們的導入,如例子以下: SELECT JBSJ.JSJDM||CHR(9)|| JBSJ.ZZJGDM||CHR(9)|| JBSJ.YYZZH||CHR(9)|| REPLACE(REPLACE(JBSJ.NSRMC,CHR(10)),CHR(13))||CHR(9)|| QYRY.ZJLXDM||CHR(9)|| REPLACE(REPLACE(QYRY.ZJHM,CHR(10)),CHR(13))||CHR(9)|| REPLACE(REPLACE(QYRY.XM,CHR(10)),CHR(13))||CHR(9)|| REPLACE(REPLACE(JBSJ.ZCDZ,CHR(10)),CHR(13))||CHR(9)|| REPLACE(REPLACE(JBSJ.JYDZ,CHR(10)),CHR(13))||CHR(9)|| REPLACE(REPLACE(JBSJ.JYFW,CHR(10)),CHR(13))||CHR(9)|| REPLACE(REPLACE(JBSJ.JYDZYB,CHR(10)),CHR(13))||CHR(9)|| ZCLX.DJZCLXDM||CHR(9)|| TO_CHAR(JBSJ.KYDJRQ,'YYYY-MM-DD')||CHR(9)|| JBSJ.SWJGZZJGDM||CHR(9)|| REPLACE(REPLACE(SWJGZZJG.SWJGZZJGMC,CHR(10)),CHR(13))||CHR(9)|| JBSJ.ZCZBJE||CHR(9)|| JBSJ.NSRZT||CHR(9)|| NSRZT.NSRZTMC FROM DJDB.DJ_JL_JBSJ JBSJ, DJDB.DJ_JL_QYRY QYRY, DMDB.GY_DM_SWJGZZJG SWJGZZJG, DMDB.DJ_DM_DJZCLX ZCLX, DMDB.DJ_DM_NSRZT NSRZT WHERE JBSJ.DJZCLXDM=ZCLX.DJZCLXDM AND JBSJ.JSJDM=QYRY.JSJDM AND QYRY.ZWDM='01' AND JBSJ.SWJGZZJGDM=SWJGZZJG.SWJGZZJGDM AND JBSJ.NSRZT=NSRZT.NSRZTDM AND JBSJ.NSRZT!=90 AND JBSJ.KYDJRQ < TO_DATE('20040701','YYYYMMDD') 對於字段內包含不少回車換行符的應該給與過濾,造成比較規矩的文本文件。 一般狀況下,咱們使用SPOOL方法,將數據庫中的表導出爲文本文件的時候會採用兩種方法,以下述: 方法一:採用如下格式腳本  set colsep '' ------設置列分隔符   set trimspool on   set linesize 120   set pagesize 2000   set newpage 1   set heading off   set term off   spool 路徑+文件名   select * from tablename;   spool off 方法二:採用如下腳本 set trimspool on   set linesize 120   set pagesize 2000   set newpage 1   set heading off   set term off     set verify off   --不顯示原值,新值   spool 路徑+文件名   select col1||','||col2||','||col3||','||col4||'..' from tablename;   spool off 比較以上方法,即方法一採用設定分隔符而後由sqlplus本身使用設定的分隔符對字段進行分割,方法二將分隔符拼接在SELECT語句中,即手工控制輸出格式。 在實踐中,我發現經過方法一導出來的數據具備很大的不肯定性,這種方法導出來的數據再由sql ldr導入的時候出錯的可能性在95%以上,尤爲對大批量的數據表,如100萬條記錄的表更是如此,並且導出的數據文件狂大。 而方法二導出的數據文件格式很規整,數據文件的大小多是方法一的1/4左右。經這種方法導出來的數據文件再由sqlldr導入時,出錯的可能性很小,基本均可以導入成功。 所以,實踐中我建議你們使用方法二手工去控制spool文件的格式,這樣能夠減少出錯的可能性,避免走不少彎路。
相關文章
相關標籤/搜索