10

パラメータ化された入力を使用するようにハードコードされたクエリを切り替えようとしていますが、問題が発生しました。パラメータ化された一括挿入の入力をどのようにフォーマットしますか?

現在、コードは次のようになっています。

$data_insert = "INSERT INTO my_table (field1, field2, field3) ";
$multiple_inserts = false;
while ($my_condition)
{
    if ($multiple_inserts)
    {
        $data_insert .= " UNION ALL ";
    }

    $data_insert .= " SELECT myvalue1, myvalue2, myvalue3 ";
}

$recordset = sqlsrv_query($my_connection, $data_insert);

考えられる解決策(PHPとPDOを使用して単一のMySQLプリペアドステートメントに配列を挿入する方法から変更)は次のようになります。

$sql = 'INSERT INTO my_table (field1, field2, field3) VALUES ';
$parameters = array();
$data = array();
while ($my_condition)
{
    $parameters[] = '(?, ?, ?)';
    $data[] = value1;
    $data[] = value2;
    $data[] = value3;
}

if (!empty($parameters)) 
{
    $sql .= implode(', ', $parameters);
    $stmt = sqlsrv_prepare($my_connection, $sql, $data);
    sqlsrv_execute($stmt);
}

パラメータ化されたクエリを使用して一括挿入を実行するためのより良い方法はありますか?

4

2 に答える 2

6

さて、あなたには3つの選択肢があります。

  1. 一度ビルド - 複数実行。基本的に、1 つの行に対して 1 回挿入を準備してから、それを実行する行をループします。SQLSERVER 拡張機能は、クエリが準備された後のクエリの再バインドをサポートしていないため (参照を使用して汚いハックを行う必要があります)、これは最適なオプションではない可能性があります。

  2. 1 回ビルド - 1 回実行します。基本的に、例で言ったように1つの巨大な挿入を作成し、それを1回バインドして実行します。これは少し汚れており、準備されたクエリが提供する利点の一部が失われています。ただし、オプション 1 からの参照が必要なため、これを行います。変数参照に依存するよりも、巨大なクエリを作成する方がクリーンだと思います。

  3. 複数ビルド - 複数実行。基本的に、あなたがやっている方法を取り、それを微調整して、非常に多くのレコードごとにクエリを再準備します。これにより、過度に大きなクエリが回避され、クエリが「バッチ処理」されます。だから、このようなもの:

    $sql = 'INSERT INTO my_table (field1, field2, field3) VALUES ';
    $parameters = array();
    $data = array();
    
    $execute = function($params, $data) use ($my_connection, $sql) {
        $query = $sql . implode(', ', $parameters);
        $stmt = sqlsrv_prepare($my_connection, $query, $data);
        sqlsrv_execute($stmt);
    }
    
    while ($my_condition) {
        $parameters[] = '(?, ?, ?)';
        $data[] = value1;
        $data[] = value2;
        $data[] = value3;
        if (count($parameters) % 25 == 0) {
            //Flush every 25 records
            $execute($parameters, $data);
            $parameters = array();
            $data = array();
        }
    }
    if (!empty($parameters))  {
        $execute($sql, $parameters, $data);
    }
    

どちらの方法でも十分です。あなたの要件に最も合っていると思うことをしてください...

于 2011-01-11T16:02:07.700 に答える
2

「一度準備して複数実行する」方法を使用しないのはなぜですか。すべてが失敗するか、すべてが機能することを望んでいることは知っていますが、トランザクションでそれを処理するのはそれほど難しくありません。

http://www.php.net/manual/en/pdo.begintransaction.php

http://www.php.net/manual/en/pdo.commit.php

http://www.php.net/manual/en/pdo.rollback.php

于 2011-01-11T16:33:13.940 に答える