使用内爆或准备好的陈述插入?

时间:2015-08-19 11:07:18

标签: php mysql arrays insert prepared-statement

我有一个数组$ authors,其中包含一些我希望插入表中的数字。

我可以准备一个语句来为数组中的每个元素执行多次:

$stmt = $pdo->prepare('INSERT INTO authors (article_id, user_id) VALUES(?, ?)');
$stmt->bindParam(1, $article_id);
$stmt->bindParam($author);
foreach($authors as $author) {
    $stmt->execute();
}

但是,我可以使用implode()做一个技巧,只执行一次语句:

// here probably $authors = array_map('intval', $authors);
$stmt = $pdo->prepare(
    'INSERT INTO authors (article_id, user_id)
     VALUES ('.implode(', :article_id), (', $authors).', :article_id)');

$stmt->execute([':article_id' => $article_id]);
  1. 第一种解决方案更传统,看起来更安全。
  2. 第二个(我认为)更快,因为数据库只有一个查询。 (并且更短 - 除了implode之外没有循环)
    • 我没有看到任何安全问题,但在查询中没有字符串连接时看起来更安全(对我而言)。
  3. 在这种情况下哪种方法正确?

    编辑:第二个查询的echo给出了这个:

    INSERT INTO authors (article_id, student_id)
         VALUES (121, :article_id), (50, :article_id)
    

    执行时没有错误。

1 个答案:

答案 0 :(得分:1)

根据PDO的文档"除非启用仿真模式,否则不能在预准备语句中多次使用同名的命名参数标记。"。因此,仅此一点就会使你的内心发生内爆。解决方案不好。

话虽如此,我会回答这个理论。准备语句的要点是只编译一次查询,因此重复执行的速度更快。如此准备好的陈述应该用在你的第一个例子中:一个简单的"模板"查询,重复多次。

在第二个示例中,您创建了一个自定义查询,几乎不会重复(因为它基于$ authors数组的内容)。因此,在这种情况下准备好的语句完全没用,你有PREPARE的开销而没有重复执行的好处。 它不应该被使用。

扩展插入是一个非常有效的解决方案,并且是一个很好的解决方案,但使用普通查询(即exec()),并确保使用quote()来防止SQL注入!