Мне интересно, работают ли подготовленные операторы так же, как и обычная mysql_query с несколькими значениями VALUES.
INSERT INTO table (a,b) VALUES ('a','b'), ('c','d');
В.С.
$sql = $db->prepare('INSERT INTO table (a,b) VALUES (?, ?);
Если я использую подготовленный оператор в цикле, то MySQL оптимизирует вставку в фоновом режиме, чтобы работать так, как в первой части кода, или это просто как запуск первого фрагмента кода внутри цикла с одним значением каждый раз ?
Я пошел вперед и проверил тест, в котором один запрос использует подготовленный оператор, а другой выполняет весь запрос, а затем выполняет это. Я, вероятно, не делаю то, что хочу знать легко понять.
Вот мой тестовый код. Я думал, что готовые заявления вроде сдерживают выполнение до тех пор, пока не будет вызван $ stmt-> close () для его оптимизации или чего-то еще. Это, похоже, не так, потому что тест, который строит запрос с использованием real_escape_string, по крайней мере в 10 раз быстрее.
<?php $db = new mysqli('localhost', 'user', 'pass', 'test'); $start = microtime(true); $a = 'a'; $b = 'b'; $sql = $db->prepare('INSERT INTO multi (a,b) VALUES(?, ?)'); $sql->bind_param('ss', $a, $b); for($i = 0; $i < 10000; $i++) { $a = chr($i % 1); $b = chr($i % 2); $sql->execute(); } $sql->close(); echo microtime(true) - $start; $db->close(); ?>
Если вы используете подготовленный оператор в цикле, он будет более эффективным, чем запуск необработанного запроса каждый раз из-за анализа, который нужно выполнить только один раз с помощью подготовленного оператора. Так что нет, это не одно и то же.
public function insertMulti($table, $columns = array(), $records = array(), $safe = false) { self::$counter++; //Make sure the arrays aren't empty if (empty($columns) || empty($records)) { return false; } // If set safe to true: set records values to html real escape safe html if($safe === true){ $records = $this->filter($records); } //Count the number of fields to ensure insertion statements do not exceed the same num $number_columns = count($columns); //Start a counter for the rows $added = 0; //Start the query $sql = "INSERT INTO " . $table; $fields = array(); //Loop through the columns for insertion preparation foreach ($columns as $field) { $fields[] = '`' . $field . '`'; } $fields = ' (' . implode(', ', $fields) . ')'; //Loop through the records to insert $values = array(); foreach ($records as $record) { //Only add a record if the values match the number of columns if (count($record) == $number_columns) { $values[] = '(\'' . implode('\', \'', array_values($record)) . '\')'; $added++; } } $values = implode(', ', $values); $sql .= $fields . ' VALUES ' . $values; //echo $sql; $query = $this->dbConnection->query($sql); if ($this->dbConnection->error) { $this->errorLog($this->dbConnection->error, $sql); return false; } else { return $added; } }
Эта функция сначала подготовит один запрос INSERT с несколькими значениями строк и вставляет его один раз. Но это не для объемной вставки сразу.