2016-05-10 9 views
1

私はPerlにはかなり新しく、xlsからデータを読み込んで結果をMySQL DBに挿入するPerlスクリプトを書いていますが、問題があります。 ここは私のコードです:私は、スクリプトを実行するときPerlからxls insert from mysql

#!/usr/local/bin/perl 
use strict; 
use warnings; 
use diagnostics; 
use Spreadsheet::ParseExcel; 
use DBI; 
use Data::Dumper qw(Dumper); 
my $parser = Spreadsheet::ParseExcel->new(); 
my $workbook = $parser->parse('test.xls'); 
my $dbh = DBI->connect("dbi:mysql:parser", "root", "123qwe", { RaiseError => 1}) or die $DBI::errstr; 
my $query = 'INSERT INTO parser (Name,Country) VALUES (?,?)'; 
my $sth = $dbh->prepare($query) or die "Prepare failed: " . $dbh->errstr(); 

if (!defined $workbook) { 
     die $parser->error(), ".\n"; 
} 
for my $worksheet ($workbook->worksheets()) { 
     my ($row_min, $row_max) = $worksheet->row_range(); 
     my ($col_min, $col_max) = $worksheet->col_range(); 

     for my $row ($row_min .. $row_max) { 
       for my $col ($col_min .. $col_max) { 

         my $cell = $worksheet->get_cell($row, $col); 
         next unless $cell; 
         my $results = $cell->value(); 
         open(my $fh, '>>', "test"); 
         print $fh "$results\t"; 
         close $fh; 
       } 
     } 
} 

open my $fh, "<", "test" or die $!; 
while (<$fh>) 
{ 
     chomp; 
     my @vals = split; 
     $sth->execute(@vals); 
} 
close $fh; 

は、だから、次のエラーで終了します。

私が実際に出力の6つの変数があるため、自然である
DBD::mysql::st execute failed: called with 6 bind variables when 2 are needed at ./parser.pl line 39, <$fh> line 1. 
Uncaught exception from user code: 
    DBD::mysql::st execute failed: called with 6 bind variables when 2 are needed at ./parser.pl line 39, <$fh> line 1. 

John Smith USA Ognyan Penkov Egypt 

だから問題は、Spreadsheet :: ParseExcelがすべての日付を1行として読み込むため、すべての列/行の結果を分割してMySQLテーブルに格納する方法を見つけることができないように見えることです(たとえば、

 A   B 
1. John Smith  USA 
2. Ognyan Penkov Egypt 
...etc... 

私のMySQLテーブル:

私のXLSファイルには、次のようになります)、テーブル名とテーブルの国への国に行かなければならない

+--------+--------------+------+-----+---------+----------------+ 
| Field | Type   | Null | Key | Default | Extra   | 
+--------+--------------+------+-----+---------+----------------+ 
| id  | int(6)  | NO | PRI | NULL | auto_increment | 
| Name | varchar(255) | YES |  | NULL |    | 
|Country | varchar(255) | YES |  | NULL |    | 
+--------+--------------+------+-----+---------+----------------+ 
+0

"My XML file"と言うと、XLS(X)を意味するのでしょうか? – simbabque

+0

最初にファイルに書き込むのはなぜですか?そして、あなたは 'Name'テーブルと' Country'テーブルについて話していますが、_columns_ 'id'、' Name'と 'Country'を持つテーブルを1つ表示します。私はここであなたの言葉が混ざっていると思います。あなたは何をしようとしているのですか?あなたの質問を編集して明確にしてください。 – simbabque

+0

私はXLSファイルの結果をMySQLテーブルに読み込んで挿入しようとしていますが、idテーブルはauto_incrementフィールドの問題ではないはずです。XLSファイルから名前と国を挿入するだけです。 – user2642601

答えて

1

あなたはAPPENDためtestと呼ばれるファイルを開いていますwriドキュメント内のすべての単一セルについてとしてください。次に、現在のセルの値を追加し、続いてタブレーター\t文字を追加します。その後、同じファイルを1行ずつ開きますが(行は1行しかありません)、chompは行末にありません(入れていないため)、splitは空白にbecause split without a delimiter uses \sです。これはです。空白

If omitted, PATTERN defaults to a single space, " " , triggering the previously described awk emulation.

そして、あなたのファイルはこのようになりますので、それは、まさに問題だ:

John\tSmith\tUSA\tOgnyan\tPenkov\tEgypt 

\t、単一の空白あるので、あなたは@valがそれらのすべてのものになってしまいます。クエリに渡すと失敗します。

名前のテーブルと国のテーブルを持っているのではなく、エクセルファイルのデータを単一のMySQLテーブル行に入れて行にすることができますあなたの$rowループでそれを行うだけです。

for my $worksheet ($workbook->worksheets()) { 
    my ($row_min, $row_max) = $worksheet->row_range(); 
    my ($col_min, $col_max) = $worksheet->col_range(); 

    for my $row ($row_min .. $row_max) { 
     my @values; 
     for my $col ($col_min .. $col_max) { 
      my $cell = $worksheet->get_cell($row, $col); 
      next unless $cell; 
      push @values, $cell->value(); 
     } 
     $sth->execute(@values) or die $dbh->errstr; 
    } 
} 
+1

私は自分の間違いを理解しました。今は正しく機能しています。ありがとうございました ! – user2642601