2014-02-19 51 views
1

我試圖從CSV一些數據上傳到MySQL數據庫 - 但它不工作從CSV到MySQL數據庫使用Perl

下面一個是我的代碼

#!/usr/bin/perl -w 
use DBI; 
use strict; 
use TEXT::CSV; 
use warnings; 

my $driver  = "mysql"; 
my $database  = "test"; 
my $host   = "localhost" 
my $databaseport = "3306"; 
my $userid  = "root"; 
my $password  = "password"; 
my $csv   = "C:/Perl/scripts/table.csv"; 

my $dsn   = "dbi:mysql:dbname=$databasename;host=$dbhost;port=$dbport;"; 

open (CSV, "$csv") or die "Couldn't open csvfile: $!"; 
my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1}) 
or die "Could not connect to database! $DBI::errstr"; 
{ 
local $/ = undef; 
    $dbh->do("INSERT INTO student (stud_id,stud_name,dept_id,stud_mark,stud_address) 

    values (?, ?, ?, ?, ?)", undef, <CSV>); 
} 
$dbh->disconnect; 
close CSV; 
+0

您根本沒有使用Text :: CSV。你現在所擁有的將一個完整的CSV行作爲一個字符串,包括作爲MySQL的第一個'?'的換行符。你應該得到一個錯誤,如*期望5個參數,但用1 *調用。 – simbabque

+0

錯誤類似於:在@INC(@INC包含:C:/ Perl/site/lib C:/ Perl/lib。)中找不到TEXT/CSV.pm 位於C:\ Perl \ scripts \ upload。 pl line 4. BEGIN失敗 - 編譯在C:\ Perl \ scripts \ upload.pl第4行中止。 – Benny

+2

這是因爲沒有這樣的模塊。 Perl的模塊名稱區分大小寫。請參閱我的回答以獲取關於此的解釋,等等。 – simbabque

回答

5

有一些問題在這裏。我會列出那些會首先給你錯誤信息的人。

  • 沒有模塊TEXT :: CSV。雖然有一個叫做Text::CSV
  • 您在查詢中使用了5個佔位符,但您要通過鑽石運算符<CSV>傳遞csv文件的第一行。這會給出錯誤信息。

然後你的邏輯有問題。您將完整的文件傳遞給數據庫(作爲第一個參數)。那沒有意義。您需要輸入split或使用Text :: CSV來執行此操作並逐行讀取文件。

此外,現在使用帶有三個參數的open並使文件句柄爲詞法是一種很好的做法。

我已經把所有這些都寫成了自制CSV處理的例子。如果您的文件更復雜,請閱讀Text :: CSV並使用它。

use DBI; 
use strict; 
use warnings; 

my $csv   = "C:/Perl/scripts/table.csv"; 
# omitted settings here ... 

my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1}) 
    or die "Could not connect to database! $DBI::errstr"; 
open (my $fh, '<', $csv) 
    or die "Couldn't open csvfile: $!"; 

# prepare statement handle for reuse in the loop 
my $sth = $dbh->prepare(qq{ 
    INSERT INTO student(stud_id,stud_name,dept_id,stud_mark,stud_address) 
    VALUES (?, ?, ?, ?, ?)}); 

# read the file line by line 
while (my $line = <$fh>) { 
    chomp $line; # remove newline 
    $sth->execute(split /;/, $line); # assuming the separator is a semicolon 
} 

close $fh; 
# DB handle will disconnect implicitly on end of program 

正如你所看到的,我決定先用prepare the statement重新使用它。這在循環中節省了大量時間,因爲DB會記住該語句。

+0

你會告訴我關於這個錯誤的信息:全局符號「$ userid」需要在D:\ Perl程序中顯式包名\ uploa d1.pl行11. – Benny

+0

這意味着該變量沒有聲明。我說我因長度而遺漏了一些變數。你需要重新添加它們。 – simbabque

+0

非常感謝你。它的運行成功.. – Benny

5

從列表上下文中的文件句柄(即代碼中的<CSV>位)讀取從文件中讀取所有行並將它們作爲列表返回。因此,您的?, ?, ?, ?佔位符每個都會從文件中獲得整行(包括最後的換行符)。對於某些字段(可能是dept_id?),這可能不是有效值,因此INSERT語句失敗。

雖然實際上,您也將$/設置爲undef,這使得它更加令人尷尬。 $/在閱讀文本文件時改變了Perl新概念。將它設置爲undef意味着Perl會將整個文件視爲單行。

我們猜測,您要做的是一次讀取一行CSV文件,並將每個文件抽入數據庫。

#!/usr/bin/perl 
use strict; 
use warnings; 
use DBI; 
use Text::CSV; # case-sensitive! 

my $driver  = "mysql"; 
my $database  = "test"; 
my $host   = "localhost" 
my $databaseport = "3306"; 
my $userid  = "root"; 
my $password  = "password"; 
my $csv   = "C:/Perl/scripts/table.csv"; 

# Connect to database. 
my $dsn = "dbi:mysql:dbname=$databasename;host=$dbhost;port=$dbport;"; 
my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1}) 
    or die "Could not connect to database! $DBI::errstr"; 

# DBI can be more efficient if you prepare the SQL query once, and then 
# execute it multiple times, rather than calling `do` for each insert. 
my $sth = $dbh->prepare(<<'SQL'); 
    INSERT INTO student (stud_id,stud_name,dept_id,stud_mark,stud_address) 
    VALUES (NULL, ?, ?, ?, ?)" 
SQL 

# Open the CSV file.A 
open my $CSV, '<', $csv 
    or die "Couldn't open csvfile: $!"; 

# Create an instance of Text::CSV. 
my $reader = Text::CSV->new; 

# Use Text::CSV to read a line. 
while (my $row = $reader->getline($CSV)) 
{ 
    # Insert into database. 
    $sth->execute(@$row); 
} 

# Clean up (optional; Perl will do this when your script ends anyway). 
$dbh->disconnect; 
close $CSV; 
+0

謝謝你的回答... – Benny

相關問題