2

こんにちは、質問があります。皆さんが私を助けてくれることを願っています。私はすべての関連情報を含めようとしました。最終的にさまざまなsqlloader制御ファイルをループし、それぞれのcsvデータをoracle sqlデータベーステーブルにインポートするperlスクリプトを作成しています。複数の制御負荷をループする前にテストしています。問題は、スクリプトがデータベースに接続し、すべての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

4 に答える 4

1

問題は、システム コールが戻り値 0 を「成功」と想定していることです。あなたの sqlldr ジョブは、レコードをスキップまたは破棄した場合、0 を返しません (2 を返すのを見たことがあります。ドキュメントを確認してください)。したがって、すべてのレコードを正常にロードしない限り、perl スクリプト (書かれているとおり) は終了します。

perlシステム
の sqlldrリターン コード

于 2012-08-14T12:26:07.053 に答える
1

system()wait実行したプログラムの戻り値を含む呼び出しの戻り値を返します。すべてがうまくいけば、これは になります0。これは、ブール値のコンテキストで True と評価される値を返すことが期待される Perl の他のほとんどすべての関数とは異なります。そのため、 or 演算子を使用した一般的なエラー処理は正しく機能しません。代わりに、次のようなことを試してみてください。

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 systemsystem()の下のドキュメントで、戻り値の処理について詳しく読むことができます

于 2012-08-14T12:07:21.043 に答える
1

Logdieあるべきものがあります、logdieAFAIU

于 2012-08-14T12:00:50.690 に答える
1

私の場合、(システムと同様に) バックティックを使用して sqlldr を実行すると、変数でフィードバックを取得するのに役立ちます。

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

秘訣は、返される値が perl では 0 ではないことです。確実に 0 を取得するには、その値を 8 ビット右にシフトする必要があります。私の場合、次のようにします。

# 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");
}

なぜ、ここに適切に説明する Perl 修道士からのリンクがあります。

于 2012-08-14T12:47:26.137 に答える