Массовые параметризованные вставки

Я пытаюсь переключить некоторые жестко запрограммированные запросы для использования параметризованных входов, но у меня возникла проблема: как вы отформатируете вход для параметризованных объемных вставок?

В настоящее время код выглядит так:

$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); 

Потенциальное решение (измененное с тем, как вставить массив в одно заявление MySQL Prepared с PHP и PDO ) выглядит следующим образом:

 $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); } 

Есть ли лучший способ выполнить массовую вставку с параметризованными запросами?

Ну, у вас есть три варианта.

  1. Сборка один раз – выполнить несколько. В принципе, вы готовите вставку один раз для одной строки, а затем выполняете цикл над строками, выполняющими ее. Поскольку расширение SQLSERVER не поддерживает повторное связывание запроса после его подготовки (вам нужно делать грязные хаки со ссылками ), это может быть не самый лучший вариант.

  2. Сборка один раз – выполнить один раз. В принципе, вы строите одну гигантскую вставку, как вы сказали в вашем примере, привяжите ее один раз и выполните ее. Это немного грязно и не хватает некоторых преимуществ, которые дают подготовленные запросы. Однако из-за требования ссылок из Варианта 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); } 

Любой метод будет достаточным. Сделайте то, что, по вашему мнению, лучше всего соответствует вашим требованиям …

Почему бы просто не использовать метод «подготовить один раз, выполнить несколько». Я знаю, что вы хотите, чтобы все либо не работали, либо работали, но с транзакциями это не совсем сложно:

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