2012-08-14 44 views
2

你好,我有一個問題,我希望你們可以幫助我。我試圖包含所有相關信息。我構建了一個perl腳本,最終將通過不同的sqlloader控制文件循環,並將它們各自的csv數據導入到oracle sql數據庫表中。我在測試多個控制負載之前循環它們。 問題是,即使腳本連接到數據庫並上傳了所有csv數據,但沒有發現任何問題,我仍然得到一個錯誤。所有行被佔和日誌並不能真正幫助:使用SQL Loader和perl導入csv錯誤

================================================================================ 
[[email protected] scripts]# perl db_upload.pl 
connection made! Starting database upload... 
Error: Can't open import control_general to SQL DB : at db_upload.pl line 44 
================================================================================ 

線44是系統連接:

system ("sqlldr $userid\@$sid/$passwd [email protected]_pools log=$log silent=all ") or $logger->logdie("Error: Can't open import control data to SQL DB :$!");

我包括控制文件輸出,Perl腳本和控制文件。 (提到的跳過的文件是用於csv標題:)

SQL*Loader: Release 11.2.0.1.0 - Production on Tue Aug 14 12:32:36 2012 
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. 
Control File: /despliegue/san/project/sql_ctrl/general.ctl 
Character Set UTF8 specified for all input. 

Data File:  /despliegue/san/project/csv/Pools.csv 
Bad File:  /despliegue/san/project/logs/sql_error.bad 
Discard File: /despliegue/san/project/logs/sql_discard.dsc 
(Allow all discards) 

Number to load: ALL 
Number to skip: 1 
Errors allowed: 50 
Bind array:  64 rows, maximum of 256000 bytes 
Continuation: none specified 
Path used:  Conventional 
Silent options: FEEDBACK, ERRORS and DISCARDS 

Table I_GENERAL, loaded from every logical record. 
Insert option in effect for this table: TRUNCATE 
TRAILING NULLCOLS option in effect 
Column Name     Position Len Term Encl Datatype 
------------------------------ ---------- ----- ---- ---- --------------------- 
OBJECTID (FILLER FIELD)   FIRST  *  , O(") CHARACTER 

DESCRIPTION (FILLER FIELD)   NEXT  *  , O(") CHARACTER 

SERIALNUMBER       NEXT  *  , O(") CHARACTER 

PRODUCT_NAME       NEXT  *  , O(") CHARACTER 

CONTROLLER_VERSION     NEXT  *  , O(") CHARACTER  

NUMBER_OF_CONTROLLERS    NEXT  *  , O(") CHARACTER  

CAPACITY_GB       NEXT  *  , O(") CHARACTER  

PRODUCT_CODE       NEXT  *  , O(") CHARACTER    

value used for ROWS parameter changed from 64 to 15 

Table I_GENERAL: 
2512 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:     247680 bytes(15 rows) 
Read buffer bytes: 1048576 
Total logical records skipped:   1 
Total logical records read:   2512 
Total logical records rejected:   0 
Total logical records discarded:  0 

Run began on Tue Aug 14 12:32:36 2012 
Run ended on Tue Aug 14 12:32:38 2012 

=============================== ================================================== =

上述文件當然縮短了,但包含了所有相關信息。 這裏是perl腳本。

#!/usr/bin/perl 
use strict; 
use warnings; 
use DBI; 
use Log::Log4perl; 
#this script loads multiple saved csv files into the database using the control files 

################ Initialization ############################################# 
my $homepath = "/despliegue/san/project"; 

my $log_conf = "$homepath/logs/log.conf"; 
Log::Log4perl->init($log_conf)or die("Error: Can't open log.config Does it exist? $!"); 
my $logger = Log::Log4perl->get_logger(); 

################ database connection variables#### 
my ($serial, $model); 
my $host="me.notyou33.safety"; 
my $port="1426"; 
my $userid="user"; 
my $passwd="pass"; 
my $sid="sid"; 
my $log="$homepath/logs/sql_import.log"; 

#Control file location 
my @control_pools= "$homepath/sql_ctrl/pools.ctl"; 
my @control_general = "$homepath/sql_ctrl/general.ctl"; 
my @control_ports= "$homepath/sql_ctrl/ports.ctl"; 
my @control_replication = "$homepath/sql_ctrl/replication.ctl"; 

#######################Database connection and data upload ################# 
my $dbh = DBI->connect("dbi:Oracle:host=$host;sid=$sid;port=$port", "$userid", "$passwd", 
{ RaiseError => 1}) or $logger->logdie ("Database connection not made: $DBI::errstr"); 

print " connection made! Starting database upload...\n"; 

system ("sqlldr $userid\@$sid/$passwd [email protected]_general log=$log silent=all") or $logger->logdie("Error: Can't open import control_general to SQL DB :$!"); 

print "one done moving to next one\n"; 

system ("sqlldr $userid\@$sid/$passwd [email protected]_pools log=$log silent=all ") or $logger->logdie("Error: Can't open import control data to SQL DB :$!"); 

system ("sqlldr $userid\@$sid/$passwd [email protected]_ports log=$log ") or $logger->logdie("Error: Can't open import control data to SQL DB :$!"); 

print "three done moving to last one\n"; 

system ("sqlldr $userid\@$sid/$passwd [email protected]_replication log=$log silent=feedback ") or $logger->logdie("Error: Can't open import control data to SQL DB :$!"); 

print "................Done\n"; 
############################################################################ 
$dbh->disconnect; 

=========================================== ======================================= 控制文件:

OPTIONS (SKIP=1) 
LOAD DATA 
CHARACTERSET UTF8 
INFILE  '/despliegue/san/project/csv/Pools.csv' 
BADFILE  '/despliegue/san/project/logs/sql_error.bad' 
DISCARDFILE '/despliegue/san/project/logs/sql_discard.dsc' 
TRUNCATE INTO TABLE I_GENERAL 
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY "\"" 
TRAILING NULLCOLS 
( 
OBJECTID FILLER, 
DESCRIPTION FILLER, 
SERIALNUMBER, 
PRODUCT_NAME, 
CONTROLLER_VERSION, 
NUMBER_OF_CONTROLLERS, 
CAPACITY_GB, 
PRODUCT_CODE, 
) 

回答

1

system()返回wait通話,其中包括你執行的程序的返回值的返回值。如果一切順利,這將是0。這與Perl中幾乎所有其他的函數都不同,您希望它們返回一些在布爾上下文中計算爲True的Value。因此,使用or運算符常用的錯誤處理方式無法正常工作。你可能會想嘗試這樣的,而不是什麼:

system ("sqlldr $userid\@$sid/$passwd [email protected]_pools log=$log silent=all") == 0 
    or $logger->logdie("Error: Can't open import control data to SQL DB :$?"); 

你可以閱讀更多關於下perldoc -f system

+0

就是這樣!非常感謝Tauli。我會讀更多關於系統調用吧! – Comocho00 2012-08-14 12:19:05

1

Logdie這應該是logdie,AFAIU

+0

謝謝,但這是一個錯字。固定! – Comocho00 2012-08-14 12:05:24

1

處理文檔中的system()返回值的問題是系統調用預期的0到返回值成功的」。你的sqlldr工作,如果它跳過或丟棄了一條記錄,不會返回0(我已經看到它返回2,檢查文檔是肯定的)。因此,除非您成功加載所有記錄,否則您的perl腳本(如所寫)將會退出。

perl的system
SQLLDR return codes

+0

返回代碼的好鏈接謝謝! – Comocho00 2012-08-14 13:20:08

+0

@ Comocho00 np,你可以通過點擊那個向上的箭頭來感謝我;-) – tbone 2012-08-14 13:32:40

+0

我想我太過分了。我需要15點聲望,對不起! – Comocho00 2012-08-14 13:39:05

1

在我來說,我執行與反引號(類似於系統)的SQLLDR,可以幫助我得到一個變量的任何反饋。

my $sqlldr = "sqlldr userid=usr/pss\@TNS control=\'$controlfile\' log=\'$logfile\' silent=header,feedback"; 
$execution = `$sqlldr 2>&1`; 

訣竅是perl中的返回值不是0,你必須向右移動8位值,以確保你得到0。在我來說,我做如下:

# Get the returned code from the last execution 
my $ret = $? >> 8; 

if ($ret == 0) { 
    $logger->info("Class DLA_Upload: All rows were successfully loaded"); 
} 
elsif ($ret == 1) { 
    die("Class DLA_Upload: Executing sqlldr returned the following error:\n$execution"); 
} 
elsif ($ret == 2) { 
    $logger->info("Class DLA_Upload: SQL*Loader was executed but some or all rows were rejected or discarded, please check $logfile for further information"); 
} 
else { 
    die("Class DLA_Upload: FATAL ERROR: sqlldr corrupted or not found"); 
} 

爲什麼,here you have a link from Perl monks,妥善解釋它。

+0

謝謝,看起來也很有趣,我喜歡你生成錯誤的方式,類似於下面的返回代碼示例。我現在正在研究它! – Comocho00 2012-08-14 13:20:45

+0

Thanks @ Comocho00,事情是sqlldr有一些退出代碼(他們有他們記錄)取決於上傳的方式,在我的情況是非常重要的,要知道是否一切都上傳或我們有任何拒絕 – 2012-08-14 13:28:06