【问题标题】:How to insert multiple rows in a mysql database at once with prepared statements?如何使用准备好的语句一次在 mysql 数据库中插入多行?
【发布时间】:2012-01-11 19:37:54
【问题描述】:

我正在尝试在 this question 中使用 staticsan 的答案来准备语句。 让我们举个例子:

$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)");
$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();

在 staticsan 的回答中,内爆数组是将所有值添加到 mysql 语句中,以便最后我们可以只用一个语句将多个数据插入数据库。 在我的示例中如何做到这一点?

【问题讨论】:

  • 你的例子有固定数量的参数,所以已经解决了。你能详细说明你的问题吗?你都尝试了些什么?它应该基本上工作相同,但添加更多参数,例如在foreach 循环中。
  • 你可以使用这里提到的代码形成准备好的语句,stackoverflow.com/questions/1176352/…

标签: php mysql prepared-statement


【解决方案1】:

这是完全有效的:

$stmt = $mysqli->prepare("INSERT INTO something (userid, time, title) VALUES (?, ?, ?)");

$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();

$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();

$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();

$stmt->bind_param('iis', $userid, time(), $title);
$stmt->execute();

您可以对值数组进行 foreach 插入、绑定和每次执行。它不会像您链接的示例中的批量插入那样快,但会更安全。

【讨论】:

  • 谢谢,这行得通。但是execute()会针对每个数组元素执行,所以每一行都会单独插入数据库,而不是同时插入。我对吗?我希望看到一个解决方案,您首先 bind_param 所有值,最后执行一次。
  • 是的,没错,但主要优点是prepared statement提供的速度提升——一次准备statement并多次运行比每次prepare要快得多。
  • 这仍然比一个好的旧静态INSERT 查询慢很多,不是吗?我的意思是,在循环中执行查询会在每个查询之间产生约 2 毫秒的延迟。对于大数组,这将花费很长时间,不是吗?
【解决方案2】:

您可以使用此处提到的代码构建准备好的语句,

PDO Prepared Inserts multiple rows in single query

PHP 逻辑有点像,

/**
 * Insert With Ignore duplicates in Mysql DB.
 */
public static function insertWithIgnore($em, $container, $tableName, $fields, $rows)
{
    $query = "INSERT IGNORE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES ";
    $placeHolr = array_fill(0, count($fields), "?");
    $qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")");
    $query .= implode(",", $qPart);

    $pdo = self::getPDOFromEm($em, $container);
    $stmt = $pdo->prepare($query);
    $i = 1;
    foreach ($rows as $row) {
        $row['created_at'] = date("Y-m-d H:i:s");
        foreach ($fields as $f) {
            if (!isset($row[$f])) {
                $row[$f] = null;
            }
            $stmt->bindValue($i++, $row[$f]);
        }
    }

    $result = $stmt->execute();

    if ($result == false) {
        $str = print_r($stmt->errorInfo(), true);
        throw new \Exception($str);
    }

    $stmt->closeCursor();
    $pdo = null;
}

/**
 * Replace old rows in Mysql DB.
 */
public static function replace($em, $container, $tableName, $fields, $rows, $extraFieldValues = null)
{
    if ($extraFieldValues != null) {
        $fields = array_unique(array_merge($fields, array_keys($extraFieldValues)));
    }

    $query = "REPLACE INTO $tableName (`" . implode('`,`', $fields) . "`) VALUES ";
    $placeHolr = array_fill(0, count($fields), "?");
    $qPart = array_fill(0, count($rows), "(" . implode(',', $placeHolr) . ")");
    $query .= implode(",", $qPart);

    $pdo = self::getPDOFromEm($em, $container);
    $stmt = $pdo->prepare($query);
    $i = 1;
    foreach ($rows as $row) {            
        if ($extraFieldValues != null) {
            $row = array_merge($row, $extraFieldValues);
        }
        foreach ($fields as $f) {
            $stmt->bindValue($i++, $row[$f]);
        }                        
    }
    $stmt->execute();
    if (!$stmt) {
        throw new \Exception("PDO::errorInfo():" . print_r($stmt->errorInfo(), true));
    }
    $stmt->closeCursor();
    $pdo = null;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 1970-01-01
    • 2016-03-07
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多