【问题标题】:Insert loop from CSV bug using PHP PDO使用 PHP PDO 从 CSV 错误插入循环
【发布时间】:2016-03-27 14:12:15
【问题描述】:

我正在尝试使用 INSERT INTO 和 PHP PDO 插入数据(超过 160,000 行),但我有一个错误。

当我启动 PHP 脚本时,我看到的 CSV 中插入数据库的行数超过了确切的行数。

如果我的循环不正确或其他什么,有人可以告诉我吗?

这是我的代码:

$bdd = new PDO('mysql:host=<myhost>;dbname=<mydb>', '<user>', '<pswd>');

        // I clean the table
        $req = $bdd->prepare("TRUNCATE TABLE lbppan_ticket_reglements;");
        $req->execute();

        // I read and import line by line the CSV file
        $handle = fopen('<pathToMyCsvFile>', "r");

        while (($data = fgetcsv($handle, 0, ',')) !== FALSE) {
            $reqImport = 
                "INSERT INTO lbppan_ticket_reglements 
                (<my31Columns>) 
                VALUES 
                ('$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]','$data[6]','$data[7]','$data[8]',
                    '$data[9]','$data[10]','$data[11]','$data[12]','$data[13]','$data[14]','$data[15]','$data[16]',
                    '$data[17]','$data[18]','$data[19]','$data[20]','$data[21]','$data[22]','$data[23]','$data[24]',
                    '$data[25]','$data[26]','$data[27]','$data[28]','$data[29]','$data[30]')";

             $req = $bdd->prepare($reqImport);
             $req->execute();
        }

        fclose($handle);

该脚本有点作用,因为数据在表中,但我不知道为什么它会出错并插入更多数据。我想也许,由于文件大小(18 Mo),脚本可能会崩溃并尝试重新启动再次插入相同的行。

我无法在我正在使用的服务器上使用 LOAD DATA。

感谢您的帮助。

【问题讨论】:

  • 不太可能,但你有 和 31 个值。
  • 而不是处理 1 个大文件,将其分解,看看是否能捕获错误
  • @NeilMasters 我的错,我有 31 列
  • 您可以在您的服务器上导入.sql 文件吗?
  • @tq 我尝试使用较小的尺寸,效果很好。也许我会寻找解决方案...

标签: php mysql csv pdo while-loop


【解决方案1】:

这不是一个答案,但在 cmets 中添加这么多内容是相当棘手的。

首先提高maximum execution time

如果这不能解决您的问题,请开始逐行处理代码并处理您能想到的所有异常。例如,您正在截断表,但您说执行后加载了更多数据,截断会失败吗?

try {
    $req = $bdd->prepare("TRUNCATE TABLE lbppan_ticket_reglements;");
    $req->execute();
} catch (\Exception $e) {
    exit($e->getMessage()); // Die immediately for ease of reading
}

不是最优雅的 try/catch,但它可以让您轻松发现问题。您也可以将其应用于正在进行的查询...

try {
    $req = $bdd->prepare($reqImport);
    $req->execute();
} catch (\Exception $e) {
    exit($e->getMessage());
}

并且还坚持一些诊断,您是否插入了 160k 行?您可以选择在每个循环中回显 $i 并查看是否可以发现任何中断或异常。

$i  = 0;
while (($data = fgetcsv($handle, 0, ',')) !== FALSE) {
    // ... your stuff
    $i++;
}

echo "Rows inserted " . $i . "\n\n"; 

除此之外,您还可以循环打印出 SQL 内容供您手动查看,也许它在做一些奇怪而富有成果的事情。

希望对您有所帮助。

【讨论】:

  • 我的脚本上有一个全局的 try catch,但是页面没有错误就停止了,这就是我被困住的原因。我想我会生成更小的文件以避免执行时间问题。不是一个完美的解决方案,但它可能会起作用
  • 试一试,看看您是否只发现其中一个较小的文件存在问题;如果您可以缩小范围,它将对您有很大帮助。试图在 160k sql 语句中用 31 个 cols 发现问题是相当残酷的:D
  • 那是当你无话可说并与一个奇怪的老板打交道时,顺便感谢你的帮助,较小的文件可以正常工作
【解决方案2】:

假设 $data[0] 是唯一标识符,那么您可以尝试这样来发现违规行:

$i = 0;

while (($data = fgetcsv($handle, 0, ',')) !== FALSE) {
    echo 'Row #'.++$i.' - '.$data[0];
}

由于您没有使用准备好的语句,$data 数组项之一很可能导致双插入或其他未知问题。

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 1970-01-01
    • 2016-12-22
    相关资源
    最近更新 更多