【问题标题】:Is it bad to put a MySQL query in a PHP loop?将 MySQL 查询放在 PHP 循环中是不是很糟糕?
【发布时间】:2010-10-18 11:53:45
【问题描述】:

我经常在 PHP 中有大型数组或大量动态数据,我需要运行 MySQL 查询来处理这些数据。

有没有更好的方法来运行诸如 INSERT 或 UPDATE 之类的许多进程,而无需遍历要进行 INSERT-ed 或 UPDATE-ed 的信息?

示例(为简洁起见,我没有使用准备好的语句):

$myArray = array('苹果','橙子','葡萄'); foreach($myArray as $arrayFruit) { $query = "INSERT INTO `Fruits` (`FruitName`) VALUES ('" . $arrayFruit . "')"; mysql_query($query, $connection); }

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    选项 1 实际上,您可以一次运行多个查询。

    $queries = '';
    
    foreach(){
        $queries  .= "INSERT....;";  //notice the semi colon
    }
    
    mysql_query($queries, $connection);
    

    这将节省您的处理时间。

    选项 2

    如果你的插入对于同一个表来说很简单,你可以在一个查询中进行多次插入

    $fruits = "('".implode("'), ('", $fruitsArray)."')";
    mysql_query("INSERT INTO Fruits (Fruit) VALUES $fruits", $connection);
    

    查询最终看起来像这样:

    $query = "INSERT INTO Fruits (Fruit)
      VALUES
      ('Apple'),
      ('Pear'),
      ('Banana')";
    

    这可能是你想走的路。

    【讨论】:

    • 对...所以一个大的有效负载(可能捆绑了 100 个插入语句)而不是单独的。有道理...谢谢:)
    • 选项 #2 确实是更好的方法,如果你可以摆动它。
    • 是的......那天我向一些同事展示它打开了新的大门
    • 当然,不要忘记转义 $fruitsArray,否则当有人试图插入“bunch o'grapes”时它会咬你
    • 请注意选项 1 不起作用,因为 mysql_query() 在其 $query 参数中不支持多个查询。这对于 mysqli::query() [mysqli_query()] 和 PDO::query() 是一样的。处理多个查询的唯一函数是 mysqli::multi_query() [mysqli_multi_query()]
    【解决方案2】:

    如果您有 mysqli 类,则可以使用准备好的语句遍历要插入的值。

    $sth = $dbh->prepare("INSERT INTO Fruits (Fruit) VALUES (?)");
    foreach($fruits as $fruit)
    {
        $sth->reset(); // make sure we are fresh from the previous iteration
        $sth->bind_param('s', $fruit); // bind one or more variables to the query
        $sth->execute(); // execute the query
    }
    

    【讨论】:

      【解决方案3】:

      关于您对 jerebear 的内爆方法(我以前使用过,并且很喜欢)的原始解决方案需要注意的一点是,它更易于阅读。内爆需要更多的程序员大脑周期来理解,这可能比处理器周期更昂贵。过早的优化,等等,等等,等等...... :)

      【讨论】:

      • 当然,您可以将所有内爆和其他更丑陋的部分隐藏在函数或类后面,使其更易于阅读并仍然受益。
      • 我仍然认为该函数需要做一个可预测和可理解的事情,原始的 php 循环非常易于阅读,我敢打赌在以下方面没有太多收获表现。我不得不承认在这个问题上我有点像魔鬼的拥护者,因为我喜欢“聪明”的解决方案。
      【解决方案4】:

      关于 jerebear 在一个 INSERT 中使用多个 VALUE 块的回答需要注意的一点:

      对于真正大量的数据来说,这可能是相当危险的,因为大多数 DBMS 对它们可以处理的命令的大小都有上限。如果您超过了太多的 VALUE 块,您的插入将失败。例如,在 MySQL 上,限制通常是 1MB AFAIK。

      因此,您应该弄清楚最大大小是多少(理想情况下是在运行时,可能从数据库元数据中获得),并通过将值列表分布在多个 INSERT 上来确保不会超过它。

      【讨论】:

      • 在这种情况下,实现 array_chunk 和循环的组合以避免达到限制可能是明智的。
      【解决方案5】:

      我受到 jerebear 的回答的启发,为我当前的一个项目构建了类似于他的第二个选项的东西。由于记录的剪切量,我无法一次保存和处理所有数据。所以我建立了this 来做进口。您添加数据,然后在每条记录完成后调用一个方法。在达到一定数量的可配置记录后,内存中的数据将通过大量插入(如 jerebear 的第二个选项)保存。

      // CREATE TABLE example ( Id INT, Field1 INT, Field2 INT, Field3 INT);
      $import=new DataImport($dbh, 'example', 'Id, Field1, Field2, Field3');
      foreach ($whatever as $row) {
        // add data in the order of your column definition
        $import->addValue($Id);
        $import->addValue($Field1);
        $import->addValue($Field2);
        $import->addValue($Field3);
        $import->nextRow();
      }
      $import->lastRow();
      

      【讨论】:

        猜你喜欢
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-25
        • 1970-01-01
        • 1970-01-01
        • 2019-12-06
        • 2011-09-20
        相关资源
        最近更新 更多