SQL*Loader詳解
在 Oracle 數據庫中,在不同數據庫的表間記錄進行復制或遷移時會用以下幾種方法:
1.導出A表的記錄,insert插入到B表中
2.建立dklink create table B from A@dblink where …
Insert into B select * from A@dblink where …
3.exp A, imp B.exp 可加查詢條件(見附頁)
4.程序實現select from A,再insert into B…,也要分批提交
5.Sqlldr
userid -- Oracle 的 username/password[@servicename]
control -- 控制文件,可能包含表的數據
log -- 記錄導入時的日志文件 默認為 控制文件(去除擴展名).log
bad -- 壞數據文件 默認為 控制文件(去除擴展名).bad
data -- 數據文件,一般在控制文件中指定。用參數控制文件中不指定數據文件更適於自動操作
discardmax -- number of discards to allow (Default all)
errors -- 允許的錯誤記錄數,可以用他來控制一條記錄都不能錯(Default 50)
rows -- 多少條記錄提交一次,默認為 64
skip -- 跳過的行數,比如導出的數據文件前面幾行是表頭或其他描述
direct -- use direct path (Default FALSE -多文件插入)
parallel -- do parallel load (Default FALSE-並發操作)
------------------------------------------------------------------
- 並發操作
sqlldr userid=/ control=result1.ctl direct=true parallel=true
sqlldr userid=/ control=result2.ctl direct=true parallel=true
其中:
replace和truncate模式,均不能使用並發(par文件的parallel=true參數)
2.sqlldr 的使用,有兩種使用方法:
只使用一個控制文件,控制文件中包含數據
使用一個控制文件(作為模板) 和一個數據文件。
一般為了利於模板和數據的分離,以及程序的不同分工會使用第二種方式。
3.數據文件:
(1)可以是 CSV 文件或者以其他分割符分隔的數據文件;
(2)可以用 PL/SQL Developer 或者 Toad 導出;
(3)也可以用 SQL *Plus 的 spool 格式化產出,或是 UTL_FILE 包生成;
#! /bin/sh
sqlplus -s hodba/hodba<<EOF
set head off
set linesize 20000
set echo off
set feedback off
set pagesize 0
set termout off
set trimout on
set trimspool on
spool /home/visitor/lxh/test.txt
select empno || ',' || ename || ',' || job || ',' ||
mgr || ',' || hiredate || ',' || sal || ',' ||
comm || ',' || deptno from emp;
spool off;
exit;
EOF
(4)另外,用 Toad 還能直接生成包含數據的控制文件。
Sqlldr步驟:
(1)創建表USER25
create table USER25(
user_id number, --用戶 ID
user_name varchar2(50), --用戶名
login_times number, --登陸次數
last_login date--最后登錄日期
);
(2)插入數據,此時user25有數據了
INS2ERT INTO USER25 VALUES (1, 'Unmi', 3, SYSDATE);
INSERT INTO USER25 VALUES (2, NULL, 5, TO_DATE('2008-10-15', 'YYYY-MM-DD'));
INSERT INTO USER25 VALUES (3, '隔葉黃鶯', 8, TO_DATE('2009-01-02', 'YYYY-MM-DD'));
INSERT INTO USER25 VALUES (4, 'Kypfos', NULL, NULL);
INSERT INTO USER25 VALUES (5, '不知秋', 1, TO_DATE('2008-12-23', 'YYYY-MM-DD'));
(3)查看數據,用plsql導出user25.csv
" ","USER_ID","USER_NAME","LOGIN_TIMES","LAST_LOGIN"
"1","1","Unmi","3","2016/5/25 11:39:02"
"2","2","","5","2008/10/15"
"3","3","隔葉黃鶯","8","2009/1/2"
"4","4","Kypfos","",""
"5","5","不知秋","1","2008/12/23"
(4)把user25.csv復制到測試環境hodev下,這樣才能找到和運行。
(5)在相同路徑下創建user25.ctl,文件內容如下:
OPTIONS(SKIP=1,ROWS=128) --sqlldr 命令顯示的選項可以寫到這里邊來,skip=1 用來跳過數據中的第一行
LOAD DATA
INFILE "user25.csv"
--可以infile多個文件,同時導入一張表,但后面的表格無法返回預定的bad文件
append --追加表user25數據到table use25
INTO TABLE user25
Fields terminated by "," --字段由,分隔
Optionally enclosed by '"' --數據中每個字段用”框起
trailing nullcols
(virtual_column FILLER,
user_id , -- user_id number,number報錯,刪掉編譯通過
user_name,
login_times,
last_login DATE"YYYY-MM-DD HH24:MI:SS"
)
------------------------------------------------------
注:之前append處根據網上教程寫的是truncate,可是報錯,不能同時load和truncate,所以改成了append。
SQL*Loader-926: OCI error while executing delete/truncate (due to REPLACE/TRUNCA
TE keyword) for table USER25
ORA-00054: resource busy and acquire with NOWAIT specified
------------------------------------------------------
說明:在操作類型 truncate 位置可用以下中的一項:
1) insert --為缺省方式,在數據裝載開始時要求表為空
2) append --在表中追加新記錄
3) replace --刪除舊記錄(用 delete from table 語句),替換成新裝載的記錄
4) truncate --刪除舊記錄(用 truncate table 語句),替換成新裝載的記錄
其中:
replace和truncate模式,均不能使用並發(par文件的parallel=true參數)
------------------------------------------------------
如果沒聲明FIELDS TERMINATED BY ',' 時,可以用下面兩種方式實現同樣功能:
1.為每一列指定分隔符
(
col_1 [interger external] TERMINATED BY ',' ,
col_2 [date "dd-mon-yyy"] TERMINATED BY ',' ,
col_3 [char] TERMINATED BY ',' OPTIONALLY ENCLOSED BY 'lg'
)
2.用位置告訴字段裝載數據
(
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) // 指定字段的類型
resultid char terminated by ',',
website char terminated by ',',
ipport char terminated by ',',
status char terminated by whitespace)
數據傳輸過程極大的依靠網絡的穩定,假使中途斷了零點幾秒也會導致記錄丟失,丟失的記錄會在.bad文件中找到。
(6)執行命令導入數據
sqlldr hodba/hodba control=user25.ctl
SQL*Loader: Release 10.2.0.5.0 - Production on Wed May 25 11:59:38 2016
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Commit point reached - logical record count 5
(7)查看表數據
------------------------------------------------------
1 1 Unmi 3 2016/5/25 11:39:02
2 2 5 2008/10/15
3 3 隔葉黃鶯 8 2009/1/2
4 4 Kypfos
5 5 不知秋 1 2008/12/23
6 1 Unmi 3 2016/5/25 11:11:05
7 2 5 2008/10/15
8 3 隔葉黃鶯 8 2009/1/2
9 4 Kypfos
10 5 不知秋 1 2008/12/23
至此,把user25.csv的數據append(sqlldr)到表user25成功。
Way2:.ctl中加入data
OPTIONS(SKIP=1,ROWS=128)
LOAD DATA INFILE *
append
INTO TABLE user25
Fields terminated by ","
Optionally enclosed by '"' -- 數據中每個字段用”框起
trailing nullcols
(
virtual_column FILLER,
user_id,
user_name,
login_times,
last_login DATE"YYYY-MM-DD HH24:MI:SS"
)
BEGINDATA
" ","USER_ID","USER_NAME","LOGIN_TIMES","LAST_LOGIN"
"1","1","Unmi","3","2016/5/25 11:39:02"
"2","2","","5","2008/10/15"
"3","3","隔葉黃鶯","8","2009/1/2"
"4","4","Kypfos","",""
"5","5","不知秋","1","2008/12/23"
-------------------------------------
"4","4","Kypfos","",""不能寫成"4","4","Kypfos",NULL,NULL
否則,無法轉化,該條數據不能插入表中
login_times terminated by",", NULLIF(login_times='NULL') --可為列單獨指定分隔符
last_login DATE"YYYY-MM-DD HH24:MI:SS"NULLIF (last_login="NULL") -- 當字段為"NULL"時就是 NULL)
該函數無效
---------------------------------------------------------------------
impdp\expdp和imp\exp
EXP和IMP:客戶端工具程序,可在客戶端+服務端使用。缺點:速度慢
EXPDP和IMPDP:服務端的工具程序,只能在ORACLE服務端使用,不能在客戶端使用。
IMP只適用於EXP導出的文件,不適用於EXPDP導出文件;IMPDP只適用於EXPDP導出的文件,而不適用於EXP導出文件。
expdp或impdp命令時,可暫不指出用戶名/密碼@實例名 as 身份,然后根據提示再輸入,如:
expdp schemas=scott dumpfile=expdp.dmp DIRECTORY=dpdata1;
一、創建邏輯目錄,該命令不會在操作系統創建真正的目錄,最好以system等管理員創建。
create directory dpdata1 as 'd:\test\dump';
二、查看管理理員目錄(同時查看操作系統是否存在,因為Oracle並不關心該目錄是否存在,如果不存在,則出錯)
select * from dba_directories;
三、給scott用戶賦予在指定目錄的操作權限,最好以system等管理員賦予。
grant read,write on directory dpdata1 to scott;
四、導出數據
1)按用戶導
expdp scott/tiger@orcl schemas=scott dumpfile=expdp.dmp DIRECTORY=dpdata1;
2)並行進程parallel
expdp scott/tiger@orcl directory=dpdata1 dumpfile=scott3.dmp parallel=40 job_name=scott3
3)按表名導
expdp scott/tiger@orcl TABLES=emp,dept dumpfile=expdp.dmp DIRECTORY=dpdata1;
4)按查詢條件導
expdp scott/tiger@orcl directory=dpdata1 dumpfile=expdp.dmp Tables=emp query='WHERE deptno=20';
5)按表空間導
expdp system/manager DIRECTORY=dpdata1 DUMPFILE=tablespace.dmp TABLESPACES=temp,example;
6)導整個數據庫
expdp system/manager DIRECTORY=dpdata1 DUMPFILE=full.dmp FULL=y;
******************************************************************
$ORACLE_HOME/bin/expdp $1 full=y directory=nr_dump_dir ESTIMATE=STATISTICS dumpfile=$dmp
parallel=4 logfile=$log
導出整個數據庫到directory這個目錄下面
ESTIMATE=STATISTICS,dumpfile=$dmp,並行進程parallel,logfile=$log,directory=nr_dump_dir
> SELECT * FROM DBA_DIRECTORIES WHERE DIRECTORY_NAME = 'NR_DUMP_DIR' ;
DIRECTORY_PATH:/u3/BACKUP/export
在使用expdp導出數據時,可以使用estimate參數控制並且估算導出文件大小,estimate取值分為blocks 和statistics兩種
五、還原數據
1)導到指定用戶下
impdp scott/tiger DIRECTORY=dpdata1 DUMPFILE=expdp.dmp SCHEMAS=scott;
2)改變表的owner
impdp system/manager DIRECTORY=dpdata1 DUMPFILE=expdp.dmp TABLES=scott.dept
REMAP_SCHEMA=scott:system;
3)導入表空間
impdp system/manager DIRECTORY=dpdata1 DUMPFILE=tablespace.dmp TABLESPACES=example;
4)導入數據庫
impdb system/manager DIRECTORY=dump_dir DUMPFILE=full.dmp FULL=y;
5)追加數據
impdp system/manager DIRECTORY=dpdata1 DUMPFILE=expdp.dmp SCHEMAS=system TABLE_EXISTS_ACTION
---------------------------------------------------------------------