在 Oracle 数据库中,我们通常在不同数据库的表间记录进行复制或迁移时会用以下几种方法:
1. 逐条insert -- 只适用少量数据更新
ALTER TABLE order_items DISABLE CONSTRAINT fk_order_items_products;
alter table OT.ORDER_ITEMS nologging; --关闭日志可提高性能
REM INSERTING into OT.ORDER_ITEMS
SET DEFINE OFF;
Insert /* +APPEND */ into OT.ORDER_ITEMS (ORDER_ID,ITEM_ID,PRODUCT_ID,QUANTITY,UNIT_PRICE) values (70,7,32,132,469.99);
Insert /* +APPEND */ into OT.ORDER_ITEMS (ORDER_ID,ITEM_ID,PRODUCT_ID,QUANTITY,UNIT_PRICE) values (73,5,192,124,519.99);
ALTER TABLE order_items ENABLE CONSTRAINT fk_order_items_products;
2. 建立数据库间的 dblink
create table B as select * from A@dblink where ...
insert into B select * from A@dblink where ...
3. exp A表(可加查询条件),再imp到B表
imp操作导入dmp文件时表空间问题 1.创建表空间, 2.indexfile并运行,再执行导入, 3.修改默认表空间
create user myhuang identified by myhuang default tablespace myhuang;
grant resource,connect to myhuang;
grant dba to myhuang; //赋DBA权限
revoke unlimited tablespace from myhuang; //撤销此权限
alter user myhuang quota 0 on system; //将用户在System表空间的配额置为0
alter user myhuang quota unlimited on myhuang; //设置在用户在myhuang表空间配额不受限。
exp test/test@ip:1521/ORCL file=D:\360Downloads\test.dmp tables=(BMB,HCK_1018,ZC_CGDD_1018)
imp test/test@ip:1521/ORCL file=D:\360Downloads\test.dmp tables=(HCK_1018,ZC_CGDD_1018) ignore=y
数据导出:
1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中
exp system/manager@TEST file=d:\daochu.dmp full=y
2 将数据库中system用户与sys用户的表导出
exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)
3 将数据库中的表table1 、table2导出
exp system/manager@TEST file=d:\daochu.dmp tables=(table1,table2)
4 将数据库中的表table1中的字段filed1以"00"打头的数据导出
exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\"
上面是常用的导出,对于压缩我不太在意,用winzip把dmp文件可以很好的压缩。不过在上面命令后面 加上 compress=y 就可以了
数据导入:
1 将D:\daochu.dmp 中的数据导入 TEST数据库中。
imp system/manager@TEST file=d:\daochu.dmp
上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。
在后面加上 ignore=y 就可以了。
2 将d:\daochu.dmp中的表table1 导入
imp system/manager@TEST file=d:\daochu.dmp tables=(table1)
4. 程序分批执行
select from A ..
insert into B ...
5. Sql Loader(sqlldr / sqluldr2)
实例:
1) 数据文件+建表
2) ctl文件-
--不包含数据文件
OPTIONS (skip=1,rows=128)
unrecoverable-- 关闭数据库的日志,此选项必须要与DIRECT共同应用
LOAD DATA
INFILE "users_data.csv" -- 可以 INFILE "another_data_file.csv" 指定多个数据文件,还可以使用 BADFILE、DISCARDFILE 来指定坏数据和丢弃数据的文件, "fix n" "var n"
truncate -- 操作类型,truncate=清除表中原有记录,还可insert
INTO TABLE users -- 要插入记录的表
Fields terminated by "," -- 数据中每行记录用 "," 分隔
Optionally enclosed by '"' -- 数据中每个字段用 '"' 框起,比如字段中有 "," 分隔符时
trailing nullcols -- 表的字段没有对应的值时允许为空
(
virtual_column FILLER, -- FILLER 指定虚拟字段,用来跳过序号等
user_id number, -- 指定字段类型,默认 CHARACTER 类型, log 中有显示
user_name,
login_times,
last_login DATE "YYYY-MM-DD HH24:MI:SS" -- 指定接受日期的格式,相当用 to_date() 函数转换
)
--包含数据文件
OPTIONS (skip=1,rows=128)
LOAD DATA
INFILE * -- 因为数据同控制文件在一起,所以用 * 表示
append -- append 操作表示在表 users 中附加记录
INTO TABLE users
when LOGIN_TIMES<>'8' -- 还可以用 when 子句筛选符合条件的记录
Fields terminated by ","
trailing nullcols
(
virtual_column FILLER,
--prod_id char(32) "trim(:prod_id)",
--acc_num char(20) "replace(:acc_num,chr(13),'')"
user_id "user_seq.nextval", --这一列直接取序列的下一值,而不用数据中提供的值
user_name "'Hi '||upper(:user_name)",-- 还能用SQL函数或运算对数据进行加工处理
login_times terminated by ",", NULLIF(login_times='NULL'),--可为列单独指定分隔符
last_login DATE "YYYY-MM-DD HH24:MI:SS" NULLIF (last_login="NULL") -- 当字段为"NULL"时就是 NULL
)
BEGINDATA --数据从这里开始
,USER_ID,USER_NAME,LOGIN_TIMES,LAST_LOGIN
1,1,Unmi,3,2009-1-5 20:34
2,2,Fantasia,5,2008-10-15
3,3,隔叶黄莺,8,2009-1-2
4,4,Kypfos,NULL,NULL
5,5,不知秋,1,2008-12-23
sqluldr2自动生成的ctl文件
--
-- SQL*UnLoader: Fast Oracle Text Unloader (GZIP), Release 3.0.1
-- (@) Copyright Lou Fangxin (AnySQL.net) 2004 - 2010, all rights reserved.
--
-- CREATE TABLE qmcb_ls_100 (
-- AAC002 VARCHAR2(18),
-- AAB301_AC02 VARCHAR2(6),
-- AAB301_ZCA1 VARCHAR2(12),
-- BAB004 VARCHAR2(20),
-- AAC300 VARCHAR2(20),
-- AAC301 VARCHAR2(6),
-- AAC012 VARCHAR2(12),
-- AAC049 NUMBER(6),
-- AAE030 NUMBER(8),
-- AAE031 NUMBER(8),
-- AAC004 VARCHAR2(40),
-- AAC005 VARCHAR2(5),
-- AAC006 NUMBER,
-- AAC011 VARCHAR2(2),
-- AAC017 VARCHAR2(1),
-- AAC058 VARCHAR2(2),
-- AAC161 VARCHAR2(3),
-- AAC009 VARCHAR2(2),
-- AAC154 VARCHAR2(1),
-- AAC204 VARCHAR2(1),
-- BAC020 VARCHAR2(1),
-- BAC015 VARCHAR2(1),
-- BAE185 VARCHAR2(1),
-- NUM_OF_EMPS NUMBER,
-- IS_ZD VARCHAR2(1),
-- IS_REG_POPU VARCHAR2(1),
-- LABEL VARCHAR2(1)
-- );
--
OPTIONS(BINDSIZE=2097152,READSIZE=2097152,SKIP=1,ERRORS=-1,ROWS=50000)
LOAD DATA
INFILE 'c:\oracle\sqluldr2\qmcb_ls_100.csv' "STR X'0a'"
INSERT INTO TABLE qmcb_ls_100
FIELDS TERMINATED BY X'2c' TRAILING NULLCOLS
(
"AAC002" CHAR(18) NULLIF "AAC002"=BLANKS,
"AAB301_AC02" CHAR(6) NULLIF "AAB301_AC02"=BLANKS,
"AAB301_ZCA1" CHAR(12) NULLIF "AAB301_ZCA1"=BLANKS,
"BAB004" CHAR(20) NULLIF "BAB004"=BLANKS,
"AAC300" CHAR(20) NULLIF "AAC300"=BLANKS,
"AAC301" CHAR(6) NULLIF "AAC301"=BLANKS,
"AAC012" CHAR(12) NULLIF "AAC012"=BLANKS,
"AAC049" CHAR(8) NULLIF "AAC049"=BLANKS,
"AAE030" CHAR(10) NULLIF "AAE030"=BLANKS,
"AAE031" CHAR(10) NULLIF "AAE031"=BLANKS,
"AAC004" CHAR(40) NULLIF "AAC004"=BLANKS,
"AAC005" CHAR(5) NULLIF "AAC005"=BLANKS,
"AAC006" CHAR(46) NULLIF "AAC006"=BLANKS,
"AAC011" CHAR(2) NULLIF "AAC011"=BLANKS,
"AAC017" CHAR(1) NULLIF "AAC017"=BLANKS,
"AAC058" CHAR(2) NULLIF "AAC058"=BLANKS,
"AAC161" CHAR(3) NULLIF "AAC161"=BLANKS,
"AAC009" CHAR(2) NULLIF "AAC009"=BLANKS,
"AAC154" CHAR(1) NULLIF "AAC154"=BLANKS,
"AAC204" CHAR(1) NULLIF "AAC204"=BLANKS,
"BAC020" CHAR(1) NULLIF "BAC020"=BLANKS,
"BAC015" CHAR(1) NULLIF "BAC015"=BLANKS,
"BAE185" CHAR(1) NULLIF "BAE185"=BLANKS,
"NUM_OF_EMPS" CHAR(46) NULLIF "NUM_OF_EMPS"=BLANKS,
"IS_ZD" CHAR(1) NULLIF "IS_ZD"=BLANKS,
"IS_REG_POPU" CHAR(1) NULLIF "IS_REG_POPU"=BLANKS,
"LABEL" CHAR(1) NULLIF "LABEL"=BLANKS
)
3)执行
导出:
D:\oracle\sqluldr2>sqluldr264 scott/s123 query="select * from qmcb_ls_100" table=qmcb_ls_100 head=yes file=d:\oracle\sqluldr2\qmcb_ls_100.csv
D:\oracle\sqluldr2>sqluldr264 scott/s123@xxx:1521/xxx sql=d:\oracle\sqluldr2\qmcb_ls.sql table=qmcb_ls head=yes file=d:\oracle\sqluldr2\qmcb_ls.csv
导入:
C:\Users\epsoft>sqlldr userid=scott/s123 control=d:\oracle\sqluldr2\qmcb_ls_100.ctl data=d:\oracle\sqluldr2\qmcb_ls_100.csv direct=true parallel=true
sqlldr dbuser/dbpass@dbservice control=users.ctl
当加载大量数据时(大约超过10GB),最好抑制日志的产生, 这样不产生REDO LOG,可以提高效率。
SQL>ALTER TABLE RESULTXT nologging;
然后在 CONTROL 文件中 load data 上面加一行:unrecoverable,此选项必须要与DIRECT共同应用。
parallel并不是让一个sqlldr语句起多个进程来加载数据,而是不锁住加载表,允许别的直接路径加载. 所以要使parallel起作用,应该先将要加载的数据文件分成多个,用多个sqlldr语句同时加载,如下例:
并行
sqlldr userid=/ control=result1.ctl direct=true parallel=true
sqlldr userid=/ control=result2.ctl direct=true parallel=true
参数说明
userid -- ORACLE的 username/password[@servicename]
control -- 控制文件名(可包含数据)
log -- 日志文件名
bad -- 错误文件名
data -- 数据文件名
discard -- 废弃文件名
discardmax -- 允许废弃的文件的数目 (全部默认)
skip -- 要跳过的逻辑记录的数目 (默认 0)
load -- 要加载的逻辑记录的数目 (全部默认)
errors -- 允许的错误的数目 (默认 50)
rows -- 常规路径绑定数组中或直接路径保存数据间的行数
(默认: 常规路径 64, 所有直接路径)
bindsize -- 常规路径绑定数组的大小 (以字节计) (默认 256000)
silent -- 运行过程中隐藏消息 all|(HEADER, FEEDBACK,ERROR,废弃,DISCARD)
direct -- 使用直接路径(默认 FALSE),导入时跳过数据库的相关逻辑,风险:如果主键重复的话会使索引的状态变成UNUSABLE
parfile -- 参数文件: 包含参数说明的文件的名称
parallel -- 执行并行加载 (默认 FALSE)
file -- 要从以下对象中分配区的文件
readsize -- 读取缓冲区的大小 (默认 1048576)
table -- 用于快速模式加载的表
optionally_enclosed_by -- (可选) 由用于快速模式加载的字符封闭
skip_unusable_indexes -- 不允许/允许使用无用的索引或索引分区 (默认 FALSE)
skip_index_maintenance -- 没有维护索引, 将受到影响的索引标记为无用 (默认 FALSE)
commit_discontinued -- 提交加载中断时已加载的行 (默认 FALSE)
external_table -- 使用外部表进行加载; NOT_USED, GENERATE_ONLY, EXECUTE
columnarrayrows -- 直接路径列数组的行数 (默认 5000)
streamsize -- 直接路径流缓冲区的大小 (以字节计) (默认 256000)
multithreading -- 在直接路径中使用多线程
resumable -- 对当前会话启用或禁用可恢复 (默认 FALSE)
resumable_name -- 有助于标识可恢复语句的文本字符串
resumable_timeout -- RESUMABLE 的等待时间 (以秒计) (默认 7200)
date_cache -- 日期转换高速缓存的大小 (以条目计) (默认 1000)
no_index_errors -- 出现任何索引错误时中止加载 (默认 FALSE)
partition_memory -- 开始溢出的直接路径分区内存限制 (kb) (默认 0)
date_format -- 用于快速模式加载的日期格式
timestamp_format -- 用于快速模式加载的时间戳格式
terminated_by -- 由用于快速模式加载的字符终止
enclosed_by -- 由用于快速模式加载的字符封闭
characterset -- 用于快速模式加载的字符集
degree_of_parallelism -- 用于快速模式加载和外部表加载的并行度
trim -- 用于快速模式加载和外部表加载的截取类型
csv -- 用于快速模式加载的 csv 格式数据文件
nullif -- 用于快速模式加载的表级 nullif 子句
field_names -- 用于快速模式加载的数据文件第一条记录字段名设置
dnfs_enable -- 启用或禁用输入数据文件 Direct NFS (dNFS) 的选项 (默认 FALSE)
dnfs_readbuffers -- Direct NFS (dNFS) 读缓冲区数 (默认 4)
control选项:
-------------------------------------------------------------------------------------------------------
log-- 记录导入时的日志文件,默认为 控制文件(去除扩展名).log
bad -- 坏数据文件,默认为 控制文件(去除扩展名).bad
data -- 数据文件,一般在控制文件中指定。用参数控制文件中不指定数据文件更适于自动操作
errors -- 允许的错误记录数,可以用他来控制一条记录都不能错
rows -- 多少条记录提交一次,默认为 64
skip -- 跳过的行数,比如导出的数据文件前面几行是表头或其他描述
操作类型
1) insert--为缺省方式,在数据装载开始时要求表为空
2) append--在表中追加新记录
3) replace--删除旧记录(用 delete from table 语句),替换成新装载的记录
4) truncate--删除旧记录(用 truncate table 语句),替换成新装载的记录