10

mysqli でこのクエリを挿入するにはどうすればよいですか?...

INSERT INTO table (field1, field2, field3) VALUES ('value', 'value', 'value'), ('value', 'value', 'value'), ('value', 'value', 'value');

通常、mysql では、このクエリは簡単で、3 行を挿入します。mysqli で、プリペアド ステートメントを使用せずに、またはプリペアド ステートメントを使用しても複雑になりすぎないようにするにはどうすればよいでしょうか。PHPで余分なファンキーなことをせずにそのようなクエリを実行する方法があるかどうか知りたいだけです。

本質的に、挿入ごとに約 10 行の抽出データがあり (複数の行があるだけでなく、複数の挿入も必要です)、これが必要です。通常mysqlで行っているように、クエリでこれを行うだけで、複数の挿入を各行に1つずつ追加することはありません。

4

3 に答える 3

20

mysqli クラスは、挿入を実行するさまざまな方法を提供し、それぞれに独自の利点があります。確かに、そのうちの 1 つがニーズに合うはずです。

次の例では、指定されていない「抽出されたデータ」が配列の配列に格納されていると想定しています: $bigArray[0...datasetsize][0...2]。

mysqli データベースは $db であると想定されます。

方法 1 - オールドスクール

クエリ文字列を作成し、それを使用してデータベースにクエリを実行するだけで、慣れているように簡単に実行できます。ご指定のとおり、インサートは一度に10個同梱されます。次のコードは、そのようなバンドルの 1 つを示しており、データ セット全体 (bigArray) に自明に拡張されています。データは、おそらく mysqli::escape_string を使用してエスケープする必要があります (ここでは実行しません)。

挿入されるデータは、すべての例で整数であると想定されています。

$sql = "INSERT INTO testTable (fieldA, fieldB, fieldC) VALUES ";
for ($i = 0; $i < 10; ++$i)
{
    if ($i > 0) $sql .= ", ";
    $sql .= "({$bigArray[$i][0]}),({$bigArray[$i][1]}),({$bigArray[$i][2]})";
}
$db->query($sql);

方法 2 - できるだけ簡単に

プリペアド ステートメントとパラメーター バインディングを使用する場合、最初の作業は次のようになります。最適ではありませんが、ステートメントは 1 回だけ準備されます。ただし、変数は挿入ごとにバインドされるため、無駄です (ただし単純です)。挿入はバンドルされていないため、この例は 10 回ループします。

$statement = $db->prepare("INSERT INTO testTable (fieldA, fieldB, fieldC) VALUES (?,?,?)");
for ($i = 0; $i < 10; ++$i)
{
    $statement->bind_param("iii",$bigArray[$i][0],$bigArray[$i][1],$bigArray[$i][2]);
    $statement->execute();
}

方法 3 - 最適化

プリペアド ステートメントと複数の挿入を組み合わせることで、方法 1 の生の挿入クエリとほぼ同じパフォーマンスが実現します。実際の結果は設定によって異なりますが、ローカル データベースとリモート データベースの両方を使用した私のシステムでの簡単なテストでは、数パーセントのパフォーマンスが示されました。最適化された方法でポイントが速くなり、方法 1 のデータをエスケープする必要がある場合はさらに数ポイント増加します。

以下では call_user_func_array を使用していますが、毎回バンドルする挿入の数がわかっている場合は、それを回避して、直接 bind_param 呼び出しを構築できます。これにより、パフォーマンスがわずかに向上します。

わかりやすくするために、この例には外側のループが含まれており、合計 10k 行が挿入されると想定しています (つまり、bigArray[0..9999][0..2])。

$sql = "INSERT INTO testTable (fieldA,fieldB,fieldC) VALUES (?,?,?)".str_repeat(",(?,?,?)",9);
$statement = $db->prepare($sql);

// This is the type string used by statement::bind_param. 
// Example assumes all INTs.
$types = (array)str_repeat("i",30);

$values = array_fill(0,30,0); // A bit of unneeded variable init.

// * See notes following code snippet on why the intermediate array is used.
$intermediate = array();
for ($n = 0; $n < 30; ++$n)
{
    $intermediate[$n] = &$values[$n];
}

call_user_func_array(array(&$statement, "bind_param"), array_merge($types,$f));

for ($j = 0; $j < 1000; ++$j)
{
    for ($i = 0; $i < 10; ++$i)
    {
        $values[$i*3] = $bigArray[$i][0];
        $values[$i*3+1] = $bigArray[$i][1];
        $values[$i*3+2] = $bigArray[$i][2];
    }
    $statement->execute();
}

// call_user_func_array with bind_param requires the values be 
// passed by reference which is evaluated only on the initial 
// call. Using $values[...] = &$bigArray[...] below won't work
// and an intermediate array referencing $values is used. This 
// bit of "extra funky stuff" can be avoided at a very slight 
// performance penalty by setting $values[...] = $bigArray[...] 
// AND EVALUATING EACH TIME (move call_user_func_array
// inside the outer loop, i.e. right above $statement->execute()).
于 2013-11-05T01:22:22.483 に答える
-3

mysqli は独自のデータベースではなく、古い mysql でクエリを送信する関数のセットにすぎません。

したがって、mysqli を使用すると、任意の mysql クエリを実行できます。

ただし、動的に提供される値の場合、そのために準備されたステートメントを使用することになっているため、「PHP の余分なファンキーなもの」を避けることはできません。そして残念なことに、生の mysqli はそれらを扱うのはそれほど簡単ではありません。

したがって、そのような挿入を実行するには、最初にプレースホルダーを使用してクエリを作成する必要があります

INSERT INTO table (field1,field2,field3) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?);

call_user_func_array()
そして最後にすべての値をバインドしますexecute

于 2013-10-22T08:18:17.553 に答える