使用SQL Loader和perl导入csv错误

时间:2012-08-14 11:29:20

标签: sql perl oracle sql-loader

大家好,我有一个问题,希望你们能帮助我。我试图包含所有相关信息。我正在构建一个perl脚本,它最终将循环通过不同的sqlloader控制文件,并将它们各自的csv数据导入到oracle sql数据库表中。我在循环它们之前测试多个控制负载。 问题是我收到错误,即使脚本连接到数据库并上传所有csv数据没有任何我能看到的问题。所有行都被考虑在内,日志并没有真正帮助:

 ================================================================================
 [root@sanasr06 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 control = @ control_pools log = $ log silent = all”)或$ logger-> logdie(“错误:无法打开导入控制数据到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 control=@control_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 control=@control_pools log=$log silent=all ") or $logger->logdie("Error: Can't open import control data to SQL DB :$!");

system ("sqlldr $userid\@$sid/$passwd control=@control_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 control=@control_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,
)

4 个答案:

答案 0 :(得分:1)

Logdie应为logdie,AFAIU

答案 1 :(得分:1)

system()返回wait调用的返回值,其中包含您执行的程序的返回值。如果一切顺利,这将是0。这与Perl中的几乎所有其他funktions不同,您希望它们返回一些在布尔上下文中计算为True的Value。因此,使用或运算符的常用错误处理不能正常工作。你可能想尝试这样的事情:

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

您可以在perldoc -f system

下的文档中详细了解如何处理system()的返回值

答案 2 :(得分:1)

问题是系统调用期望返回值0为“成功”。你的sqlldr作业,如果它跳过或丢弃一条记录,将不会返回0(我看到它返回2,检查文档是否确定)。因此,除非您成功加载所有记录,否则您的perl脚本(如所写)将退出。

perl system
sqlldr return codes

答案 3 :(得分: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能够正确解释它。