php PDO 使用占位符插入批处理多行

2022-08-30 18:29:41

我希望使用PHP PDO进行多次插入。

我找到的最接近的答案是这个

如何插入数组到单个 mysql 准备语句中

但是,给出的示例使用??而不是真正的占位符。

我已经查看了PHP文档站点上的占位符示例

php.net pdo.prepared-statement

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);

现在假设我想实现上述目标,但使用数组

$valuesToInsert = array(
  0 => array('name' => 'Robert', 'value' => 'some value'),
  1 => array('name' -> 'Louise', 'value' => 'another value')
);

我该如何使用PDO和每个事务的多个插入来实现它?

我想它会从循环开始吗?

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");

foreach($valuesToInsert as $insertRow){

    // now loop through each inner array to match binded values
    foreach($insertRow as $column => value){
        $stmt->bindParam(":{$column}", value);
    }
}
$stmt->execute();

然而,上述内容不起作用,但希望能证明我试图实现的目标


答案 1

首先,符号真正的占位符(大多数驱动程序允许同时使用语法,位置和命名占位符)。其次,预准备语句只不过是将原始输入注入 SQL 语句的工具 — SQL 语句本身的语法不受影响。您已经拥有所需的所有元素:?

  • 如何使用单个查询插入多行
  • 如何动态生成 SQL
  • 如何将预准备语句与命名占位符一起使用。

将它们全部组合在一起是相当微不足道的:

$sql = 'INSERT INTO table (memberID, programID) VALUES ';
$insertQuery = [];
$insertData = [];
$n = 0;
foreach ($data as $row) {
    $insertQuery[] = '(:memberID' . $n . ', :programID' . $n . ')';
    $insertData['memberID' . $n] = $memberid;
    $insertData['programID' . $n] = $row;
    $n++;
}

if (!empty($insertQuery)) {
    $sql .= implode(', ', $insertQuery);
    $stmt = $db->prepare($sql);
    $stmt->execute($insertData);
}

答案 2

我假设你正在使用InnoDB,所以这个答案只对该引擎有效(或任何其他支持事务的引擎,这意味着MyISAM不包括在内)。

默认情况下,InnoDB以自动提交模式运行。这意味着每个查询都被视为其自己的包含事务。

为了将其转换为我们凡人可以理解的东西,这意味着您发出的每个INSERT查询都将通过确认它写下查询信息来强制硬盘提交它。考虑到机械硬盘的超慢程度,因为它们每秒的输入输出操作很低(如果我没有记错的话,平均值是300ish IO),这意味着你的50 000个查询将是 - 好吧,超级慢。

那你该怎么办?您可以在单个事务中提交所有 50k 查询。它可能不是各种目的的最佳解决方案,但它会很快。

你这样做是这样的:

$dbh->beginTransaction();

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");

foreach($valuesToInsert as $insertRow)
{    
    // now loop through each inner array to match bound values
    foreach($insertRow as $column => value)
    {
        $stmt->bindParam(":$column", value);
        $stmt->execute();
    }
}


$dbh->commit();

推荐