SQL*Loader 从文本文件向数据库导入数据
之前我的一遍 blog 写了怎样使用 Toad 这个工具从 excel 或者 csv 文件向数据库导入数据. 其实 Oracle 自己提供了这样一个工具, 叫做 SQL*Loader. 这个工具使用起来没有那么直接, 也比较容易出错, 但是它非常适合导入大数据量的文本. 执行效率非常高, 号称一小时能导入100 G (听说).
这里给出一个简单的例子, 怎么去使用它.
比方说, 有个客户想要从他之前使用的 ERP 软件里面, 把数据导入到 Oracle 的 EBS. 当然他不可能直接表对表的复制过来, 毕竟两个软件的表结构不一样. 那么他就需要把数据导入到 EBS 的接口表里面. 现在他想要把数据导入到 INV 模块的接口表 MTI 里面. 这是他需要两个文件. 一个文件是 .dat 文件, 里面存放的是所有需要导入的数据, 这个文件可能非常大. 另一个是控制文件, .ctl 文件, 里面存放的是导入法则. 当这两个文件都准备好了, 运行下面的命令:
sqlldr apps/apps control=***.ctl data=***.dat
sqlldr 命令就是调用 SQL*Loader 的实用程序, 它会根据 .ctl 控制文件定义的规则有选择的导入 .dat 文件中的数据.
数据文件可能是这样的:
INVENTORY_RECEIPT_IFD DCS INV-RCV 0000000000003791368058627 WN OA133-1-141113 OA133-1-141113 WLN AVAILABLE 0000000018 EAWLG 000200010000000018 395 X0 0.00WMD120141113142153INTRANSIT FGI 395
里面有很多空格, 每个空格占用一个字符, 这是必要的, 因为在控制文件中是这么写的:
load data append into table inv.MTL_TRANSACTIONS_INTERFACE when (1:21 = 'INVENTORY_RECEIPT_IFD') and (35:41 = 'INV-RCV') and (372:372 = 'X') (TRANSACTION_INTERFACE_ID "MTL_MATERIAL_TRANSACTIONS_S.nextval", TRANSACTION_HEADER_ID CONSTANT '0', CREATION_DATE SYSDATE, CREATED_BY CONSTANT '1198', LAST_UPDATE_DATE SYSDATE, LAST_UPDATED_BY CONSTANT '1198', SOURCE_CODE CONSTANT 'WMS WI MRECL', SOURCE_LINE_ID CONSTANT '0', SOURCE_HEADER_ID CONSTANT '0', PROCESS_FLAG CONSTANT '1', TRANSACTION_MODE CONSTANT '3', TRANSACTION_TYPE_ID CONSTANT '2', TRANSACTION_ACTION_ID CONSTANT '27' , TRANSACTION_SOURCE_TYPE_ID CONSTANT '13' , ORGANIZATION_ID POSITION (492:501), TRANSFER_ORGANIZATION POSITION (362:371), TRANSACTION_SOURCE_NAME POSITION (95:104), VENDOR_LOT_NUMBER POSITION (129:148) "replace(:VENDOR_LOT_NUMBER, '-')", TRANSACTION_DATE POSITION (418:431) DATE 'YYYYMMDDHH24MISS', TRANSACTION_QUANTITY POSITION (254:263), TRANSFER_SUBINVENTORY POSITION (462:471), SUBINVENTORY_CODE POSITION (432:441), LOC_SEGMENT1 POSITION (149:168) "substr(:LOC_SEGMENT1, 1,instr (:LOC_SEGMENT1 , '-')-1) ", ITEM_SEGMENT1 POSITION (65:94), TRANSACTION_UOM POSITION (298:299) NULLIF (TRANSACTION_UOM = BLANKS), ATTRIBUTE1 POSITION (300:303), ATTRIBUTE3 POSITION (125:128), SHIPMENT_NUMBER POSITION (169:203), TRANSACTION_REFERENCE POSITION (45:64) "ltrim(:transaction_reference,'0')" )
它是使用字符位置去获取数据文件中的数据的.
如果不通过字符位置, 那么在数据文件中就需要分隔符, 一般使用逗号. csv 文件就是典型的使用逗号作为分隔符的文件, 所以非常适合作为数据文件的格式.
写控制文件是一个非常复杂的事情, 如果像上面的例子那样使用字符位置去定位, 非常容易出错. Oracle 提供了一个脚本, 可以自动产生控制文件. 可以参考 Note 1019523.6
set echo off set heading off set verify off set feedback off set show off set trim off set pages 0 set concat on set lines 300 set trimspool on set trimout on spool &1..ctl select 'LOAD DATA'||chr (10)|| 'INFILE '''||lower (table_name)||'.dat'''||chr (10)|| 'INTO TABLE '||table_name||chr (10)|| 'FIELDS TERMINATED BY '','''||chr (10)|| 'TRAILING NULLCOLS'||chr (10)||'(' from all_tables where table_name = upper ('&1'); select decode (rownum, 1, ' ', ' , ')|| rpad (column_name, 33, ' ')|| decode (data_type, 'VARCHAR2', 'CHAR NULLIF ('||column_name||'=BLANKS)', 'FLOAT', 'DECIMAL EXTERNAL NULLIF('||column_name||'=BLANKS)', 'NUMBER', decode (data_precision, 0, 'INTEGER EXTERNAL NULLIF ('||column_name||'=BLANKS)', decode (data_scale, 0, 'INTEGER EXTERNAL NULLIF ('||column_name||'=BLANKS)', 'DECIMAL EXTERNAL NULLIF ('||column_name||'=BLANKS)')), 'DATE', 'DATE "MM/DD/YY" NULLIF ('||column_name||'=BLANKS)', null) from user_tab_columns where table_name = upper ('&1') order by column_id; select ')' from sys.dual; spool off
使用 SQL*plus 运行这个脚本, 会在当前目录产生一个 .ctl 文件, 就是控制文件了, 文件分隔符是逗号.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。