如何使用预处理语句一次性在MySQL数据库中插入多行数据?

11

我正在尝试在这个问题中使用staticsan的答案来准备语句。假设以下示例:

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

在staticsan的答案中,implode函数将数组的所有值添加到MySQL语句中,这样最终我们就可以使用一个语句将多个数据插入数据库。

在我的例子中应该如何实现?


您的示例已经有固定数量的参数,因此它已经解决了。您能详细说明一下您的问题吗?到目前为止,您尝试了什么?基本上应该是相同的,但可以添加更多的参数,例如在 foreach 循环中。 - hakre
您可以按照此处的代码,使用预处理语句来生成语句,https://dev59.com/oXM_5IYBdhLWcg3w43pt - Hemant Thorat
2个回答

9

这是完全有效的:

$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循环,每次插入、绑定和执行。虽然它不如您链接示例中的批量插入快,但它更加安全。

3
谢谢,那个方法可行。但是execute()将会被每个数组元素执行一次,所以每行都将被单独插入到数据库中,而不是同时插入所有行。我理解的对吗? 我希望看到一个解决方案,它首先绑定所有的值,然后在最后一次性执行。 - Chris
是的,那是正确的,但主要优势在于准备语句提供的速度增加 - 准备一次语句并多次运行比每次准备都要快得多。 - Jonathan Rich
4
相对于一个好的静态 INSERT 查询来说,这仍然慢了很多,不是吗?我的意思是,在循环中执行查询会在每个查询之间创建约2毫秒的延迟。对于大型数组来说,这将花费很长时间,对吧? - NoobishPro

3
你可以按照此处提到的代码构建预处理语句, 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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接