Неправильно ли поставить запрос MySQL в цикл PHP?

У меня часто возникают большие массивы или большие объемы динамических данных в PHP, которые мне нужны для выполнения запросов MySQL.

Есть ли лучший способ запускать многие процессы, такие как INSERT или UPDATE, без перебора информации, которая должна быть введена или UPDATE-ed?

Пример (я не использовал подготовленный оператор для краткости):

$myArray = array('apple','orange','grape');

foreach($myArray as $arrayFruit) {
$query = "INSERT INTO `Fruits` (`FruitName`) VALUES ('" . $arrayFruit . "')";
mysql_query($query, $connection);
}

Ответ 1

ВАРИАНТ 1 Вы можете запускать сразу несколько запросов.

$queries = '';

foreach(){
    $queries  .= "INSERT....;";  //notice the semi colon
}

mysql_query($queries, $connection);

Это позволит сэкономить на вашей обработке.

ВАРИАНТ 2

Если ваша вставка такая же простая для одной и той же таблицы, вы можете сделать несколько вставок в ОДНОМ запросе

$fruits = "('".implode("'), ('", $fruitsArray)."')";
mysql_query("INSERT INTO Fruits (Fruit) VALUES $fruits", $connection);

В результате запрос выглядит примерно так:

$query = "INSERT INTO Fruits (Fruit)
  VALUES
  ('Apple'),
  ('Pear'),
  ('Banana')";

Это, вероятно, так, как вы хотите.

Ответ 2

Если у вас есть класс mysqli, вы можете перебирать значения, которые нужно вставить, используя подготовленный оператор.

$sth = $dbh->prepare("INSERT INTO Fruits (Fruit) VALUES (?)");
foreach($fruits as $fruit)
{
    $sth->reset(); // make sure we are fresh from the previous iteration
    $sth->bind_param('s', $fruit); // bind one or more variables to the query
    $sth->execute(); // execute the query
}

Ответ 3

Одно замечание о вашем оригинальном решении по методу имплозии jerebear (который я использовал раньше и любил) - это то, что его легче читать. Имплозия требует больше циклов мозгов программиста, чтобы понять, что может быть дороже, чем процессорные циклы. преждевременная оптимизация, бла, бла, бла...:)

Ответ 4

Одна вещь, чтобы отметить jerebear ответ с несколькими VALUE-блоками в одном INSERT:

Это может быть довольно опасно для действительно больших объемов данных, поскольку большинство СУБД имеют верхний предел размера команд, которые они могут обрабатывать. Если вы превысите это со слишком большим количеством VALUE-блоков, ваша вставка не удастся. В MySQL, например, предел обычно составляет 1 МБ AFAIK.

Итак, вы должны выяснить, какой максимальный размер (в идеале во время выполнения, может быть доступен из метаданных базы данных), и убедитесь, что вы не превышаете его, распространяя ваши списки значений на несколько INSERT.

Ответ 5

Я был вдохновлен jerebear ответом на создание чего-то вроде его второго варианта для одного из моих текущих проектов. Из-за объема сдвига записей я не смог сохранить и сделать все данные сразу. Поэтому я построил этот для импорта. Вы добавляете свои данные, а затем вызываете метод, когда каждая запись завершена. После определенного, настраиваемого, количества записей данные в памяти будут сохранены с помощью массовой вставки, такой как второй вариант jerebear.

// CREATE TABLE example ( Id INT, Field1 INT, Field2 INT, Field3 INT);
$import=new DataImport($dbh, 'example', 'Id, Field1, Field2, Field3');
foreach ($whatever as $row) {
  // add data in the order of your column definition
  $import->addValue($Id);
  $import->addValue($Field1);
  $import->addValue($Field2);
  $import->addValue($Field3);
  $import->nextRow();
}
$import->lastRow();

Ответ 6

foreach ($userList as $user) {
$query = 'INSERT INTO users (first_name,last_name)  VALUES("'.$user['first_name'].'",        "' . $user['last_name'] . '")';
mysql_query($query);

}

Insted Используя вышеприведенное, попробуйте следующее. Вместо использования цикла вы можете объединить данные в один запрос базы данных.

$userData = array();
foreach ($userList as $user) {
$userData[] = '("' . $user['first_name'] . '", "' . $user['last_name'] . '")';
}
$query = 'INSERT INTO users (first_name,last_name) VALUES' . implode(',', $userData);
mysql_query($query);

Produces:

INSERT INTO users (first_name,last_name) VALUES("John", "Doe"),("Jane", "Doe")...