经过一些研究后决定在这里提出更多专家答案的问题。我不能找到确切的情景作为我的问题,所以在这里......
我认为我需要几天时间才能开始工作,甚至不能考虑如何向前迈进。
DB:11gR2
操作系统:Unix
我尝试使用perl脚本将多个csv文件加载到Oracle表中。
列出我需要处理的所有csv,因为存在csv文件的目录包含许多其他文件。
打开csv文件并插入表格
如果有任何错误,则回滚该文件的所有插入并移至下一个文件
记录每个文件完成的插入次数
#!/usr/bin/perl
use warnings;
use strict;
use Text::CSV;
use DBD::Oracle;
my $exitStatus = 0;
my $dow = `date +%a`; chomp $dow;
my $csvDow = `date -dd +%a`; chomp $csvDow;
# define logfile
my logFile;
$logFile = "log.dbinserts"
# define csv file directory
my $csvLogDir = "Home/log/$csvDow";
# csv Files in array to list all possible match of file
opendir(my $dh, $csvLogDir ) || die "can't opendir $csvLogDir : $!";
my @csvFile = grep { /csv.*host1/ && -f "$csvLogDir/$_" } readdir($dh); chomp @csvFile;
closedir $dh;
foreach my $i (@csvFile)
{
$logFile (CSV File: $i);
}
foreach my $file (@csvFile)
{
chomp ($item);
$logFile-> ("Working under: $file");
&insertRecords($csvLogDir."/".$file);
}
$logFile-> ("Exit status")
#----------------
sub insertRecords
{
my $filetoInsert=shift;
my $row;
open my $fh, "<" or die "$fileToInsert: $!";
my $csv = Text::CSV->new ({
binary =>1,
auto_diag =>1,
});
while ($row = $csv->getline ($fh))
{
print "first column : $row->[0]\n,";
}
close $fh;
}
========
CSV File
=========
date, host, first, number1, number2
20141215 13:05:08, S1, John, 100, 100.20
20141215 13:06:08, S2, Ray, 200, 200.50
...
...
...
=========
Table - tab1
=========
Sample_Date
Server
First
N1
N2
答案 0 :(得分:1)
第一步取决于您需要选择CSV文件的标准 如果它在这些CSV的名称上,您只需使用opendir并获取readd的文件列表:
my $dirToScan = '/var/data/csv';
opendir(my $dh, $dirToScan ) || die "can't opendir $dirToScan : $!";
my @csvFiles = grep { /.csv$/ && -f "$some_dir/$_" } readdir($dh);
closedir $dh;
在这个例子中,你将检索一个数组,其中包含所有以.csv结尾的文件(在设计目录中) 之后,您需要在阵列上使用foreach。
您可以找到更多示例和解释here
我不知道您的CSV的结构,但我建议使用像Text::CSV这样的模块,它是一个简单的CSV解析器,它将包装 Text :: CSV_PP 或 Text :: CSV_XS ,如果它安装在您的系统上(它比PP版本更快(因为用perl / XS编写)
此模块允许您转换数组中的CSV行,如下所示:
use Text::CSV;
my $file = "listed.csv";
open my $fh, "<", $file or die "$file: $!";
my $csv = Text::CSV->new ({
binary => 1, # Allow special character. Always set this
auto_diag => 1, # Report irregularities immediately
});
while (my $row = $csv->getline ($fh)) {
print "first colum : $row->[0]\n";
}
close $fh;
来自:perlmeme.org
您需要打开()您的文件(在foreach循环中),将其传递给 Text :: CSV 元素(您可以在之外声明您的解析器)循环)
这是您知道CSV列号的最简单情况,如果您需要使用列名,则需要使用 getline_hr()功能(请参阅 Text :: CSV 的CPAN文档 一旦你掌握了你的价值(你应该在你文件列表的foreach循环中,并且在那里列出你的CSV行,你需要在数据库中插入这些数据。
为此,您需要 DBD :: Oracle 模块,以便您连接到数据库。
与每个DBI连接器一样,您需要使用以下语法实现连接:
use DBI;
$dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd);
然后在你的循环中(当你读取CSV行时)你应该能够做到这样的事情:
$SQL = "INSERT INTO yourTable (foobar,baz) VALUES (?,?)";
$sth = $dbh->prepare($SQL);
$sth->execute($row->[0],$row->[1]);
这里有树步骤,您可以在其中准备请求,并将值替换为&#39;?&#39; (如果你有很多列,你也可以使用声明的变量) 在准备之后,您执行具有所需值的请求(再次,您不必使用匿名变量)
要捕获请求是否失败,您只需将RaiseError设置为声明连接时,看起来像这样:
$dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd,
{
PrintError => 1,
PrintWarn => 1,
RaiseError => 1
});
然后在播放请求时:
try
{
$sth->execute($row->[0],$row->[1]);
}
catch
{
warn "INSERT error : $_";
$CSVhasFailures = 1;
};
您需要在每个CSV之前将$ CSVhasFailures的值设置为0 之后,通过在while循环结束时测试CSVhasFailures的值,您可以决定使用集成函数提交和回滚执行提交或回滚。 DBD :: Oracle模块 如果你不计算插入的数量,你只需要在 $ sth-&gt;执行语句之后加上 $ counter ++ 有关DBD :: Oracle的更多信息,我建议您阅读 CPAN 文档页面。
最后一个建议,一步一步地开始:列出您的CSV文件,读取每个CSV的行,读取一列,打印一组列,然后将数据插入临时表中。