【问题标题】:A Perl script to import multiple CSV files into a MySQL database将多个 CSV 文件导入 MySQL 数据库的 Perl 脚本
【发布时间】:2016-01-23 12:40:03
【问题描述】:

我有这个 Perl 脚本:

use v5.12;
use strict;
use warnings;
use DBI;


my $dsn = "DBI:mysql:host=localhost;database=testitt";


my $dbh = DBI->connect($dsn,"root","")
    or die "No db connectin: $!";
say "Connected to MySQL.";


my $source_dir = "C:/Users/ST/Desktop/";


opendir my $dirh, $source_dir or die "Unable to open directory: $!";
my @files = grep /\.csv$/i, readdir $dirh;
closedir $dirh;


die "No files found in $source_dir" unless @files;

say 'Importing data from:';
say for @files;

my $load = $dbh->prepare("LOAD DATA INFILE ? INTO TABLE tablea Character Set utf8 FIELDS TERMINATED BY '        ' LINES TERMINATED BY '\n' IGNORE 1 LINES (id, normalized_count)")
                           or die "Prepare failed: " . $dbh->errstr(); 

for my $file (@files) {
    say "Processing $source_dir/$file";
    open my $fh, '<', "$source_dir/$file"
    or die "Unable to open $source_dir/$file: $!\n";
       $load->execute($file)
           or die "Execute failed: " . $dbh->errstr(); 
}
print "Jobs done.\n";

它在$load-&gt;execute($file) 处给了我错误,因为它无法找到该文件,但我已经在代码的早期在@file 上加载了所有内容。

编辑: 感谢马特的建议,我现在更干净了,但我无法找到将当前文件放入查询(令牌)的方法,尝试以下但给出错误:

for my $file (@files) {
        my $statement = $dbh->prepare("LOAD DATA INFILE C:\\Users\\ST\\Desktop\\"$file"INTO TABLE rnaseq Character Set utf8 FIELDS TERMINATED BY '        ' LINES TERMINATED BY '\n' IGNORE 1 LINES (id,normalized_count)");
$statement->execute()

【问题讨论】:

  • 一些事情: 1. 你不需要打开每个文件在循环中读取(MySQL 正在做这部分)。 2. 你甚至可以在那里使用占位符吗? 3.文件名应该使用绝对路径,否则“服务器在默认数据库的数据库目录中查找文件”(source)。

标签: mysql perl csv


【解决方案1】:

主要问题是,当您提供相对路径时,LOAD DATA INFILE 的行为似乎并不直观,您就是这样。

如果未指定LOCAL,则文件必须位于服务器上 主机并由服务器直接读取。服务器使用以下 文件定位规则:

  • 如果文件名是绝对路径名,服务器将使用它。
  • 如果文件名是具有一个或多个前导组件的相对路径名,则服务器搜索相对于服务器的文件 数据目录。
  • 如果给出的文件名没有前导组件,则服务器在默认的数据库目录中查找该文件 数据库。

所以,我建议为每个文件构建一个绝对路径,而不是依赖更神秘的第二个和第三个选项。


关于您的编辑,我注意到了几个问题。您需要引用整个路径,我会坚持使用正斜杠,如下所示:

for my $file (@files) {
    $dbh->do(qq{
        LOAD DATA INFILE 'C:/Users/ST/Desktop/$file' INTO TABLE rnaseq 
        CHARACTER SET utf8 
        FIELDS TERMINATED BY '        ' 
        LINES TERMINATED BY '\\n' 
        IGNORE 1 LINES (id, normalized_count)
    });
}

如果这不起作用,我可能只是 print 语句并将它们传递到 mysql 命令中。

【讨论】:

  • 谢谢。不过,我仍然不能 100% 确定占位符不会引起问题。来自DBI对于大多数驱动程序,占位符不能用于任何会阻止数据库服务器验证语句并为其创建查询执行计划的语句元素。服务器从这里做吗?呃……我不知道。
  • 嗨,马特,感谢您的帮助,非常感谢。不幸的是,我不知道如何应用你的建议,所以如果你能更具体一点,那将对我有很大帮助。谢谢。
  • @BlueStarry 当您在open() 中构建绝对路径时,您已经做对了(顺便说一句,这不是必需的):"$source_dir/$file"。唯一的问题是 Windows 上的 MySQL 是否可以处理正斜杠,但我认为应该。
  • 也许是我的英语不好,但我不明白:首先你说你不需要打开,然后你质疑相对路径,然后你告诉我你使用绝对路径是对的在公开中,但没有必要,但脚本仍然不起作用。
  • 1.您不需要open()。 2. 您应该提供到LOAD DATA INFILE 的绝对路径,就像您在其他 3 个地方所做的那样。
猜你喜欢
  • 2012-01-22
  • 2019-02-21
  • 2017-11-15
  • 1970-01-01
  • 2023-02-14
  • 1970-01-01
  • 1970-01-01
  • 2016-02-26
相关资源
最近更新 更多