15

PHP と MySQLi を使用して一度に大量の行 (約 2000 年) を挿入するための、SQL インジェクションで安全な手法を探しています。
含める必要があるすべての値を含む配列があります。現在、私はそれをやっています:

<?php
$array = array("array", "with", "about", "2000", "values");

foreach ($array as $one) 
{
    $query = "INSERT INTO table (link) VALUES ( ?)";
    $stmt = $mysqli->prepare($query);
    $stmt ->bind_param("s", $one);
    $stmt->execute();
    $stmt->close();
}
?>

call_user_func_array()を試しましたが、スタック オーバーフローが発生しました。

これを行うためのより高速な方法は何ですか (一度にすべてを挿入するなど)、それでも SQL インジェクション (準備されたステートメントなど) やスタック オーバーフローに対して安全ですか?

4

4 に答える 4

35

挿入をトランザクション内に配置することで、速度を大幅に向上できるはずです。また、準備ステートメントとバインド ステートメントをループの外に移動することもできます。

$array = array("array", "with", "about", "2000", "values");
$query = "INSERT INTO table (link) VALUES (?)";
$stmt = $mysqli->prepare($query);
$stmt ->bind_param("s", $one);

$mysqli->query("START TRANSACTION");
foreach ($array as $one) {
    $stmt->execute();
}
$stmt->close();
$mysqli->query("COMMIT");

このコードを Web サーバーで 10,000 回繰り返してテストしました。

トランザクションなし:226 seconds. トランザクションあり:2 seconds. または、two order of magnitude speed increase少なくともそのテストでは。

于 2013-03-01T02:47:25.360 に答える
5

これをもう一度試してみると、元のコードがわずかな変更で機能しない理由がわかりません。

$query = "INSERT INTO table (link) VALUES (?)";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("s", $one);

foreach ($array as $one) {
    $stmt->execute();
}
$stmt->close();
于 2013-03-01T02:07:47.963 に答える
1

はい、次のようなものを使用して、単一の大きなクエリを手動で作成できます。

$query = "";
foreach ($array as $curvalue) {
  if ($query)
    $query .= ",";
  $query .= "('" . $mysqli->real_escape_string($curvalue) . "')";
}
if ($query) {
  $query = "INSERT INTO table (link) VALUES " . $query;
  $mysqli->query($query);
}
于 2013-03-01T02:15:08.137 に答える