Как правильно выполнить один insert с множеством строк?

Рейтинг: 0Ответов: 1Опубликовано: 24.02.2023

У меня есть такой массив (на самом деле данных в нем намного больше):

    array (
    'table_name' => 
        array (
            0 => array (
                0 => 1,
                1 => 1,
                2 => 'платье',
            ),
            1 => array (
                0 => 1,
                1 => 1,
                2 => 'колготки хлопок',
            )
        )
    )

Мне нужно из этого массива записать все данные в таблицу table_name.

Если я буду делать по 1 запросу (insert) на каждую запись - вероятнее всего я сильно нагружу сервер и бд перестанет отвечать (max_connections - увеличивать этот лимит тоже не вариант).

Поэтому, если я буду делать 1 INSERT и в него добавлю сразу все строки, я думаю, это облегчит работу базе данных.

Мне нужно построить запрос таким образом:

INSERT INTO `table_name` (row1, row2, row3) VALUES (1, 1, платье), (1, 1, колготки хлопок)

Тогда будет всего один запрос к базе, который сделает сразу 2 записи.

Мне нужна помощь с формированием строки запроса. Сейчас я это делаю так:

foreach ($array as $table => $rows) {
    $all_rows = [];
   
    foreach ($rows as $row) {
        $all_rows[] = '('.implode(', ', $row).')';
    }

    $sql = "INSERT INTO `$table` (`row1`, `row2`, `row3`) VALUES ".implode(', ', $all_rows);
}

И в итоге я получаю готовый запрос который я могу выполнять в SQL, но проблема в следующем:

  1. в запросе все значения (наверное кроме int) нужно обернуть в одинарные ковычки.
  2. что если в значении уже будут ковычки? как с ними работать правильно чтобы не навредить базе?

Буду очень благодарен за полезный ответ! Хотелось бы увидеть как преобразовать мой код формирование запроса с учетом описанных мною проблем, и возможно я еще что-то не учел, просьба и об этом сообщить.

UPD. В итоге у меня получилось сделать все вот такой функцией: (огромная просьба, указать на недостатки такого решения и на способы его оптимизации с целью ускорения выполнения)

function inserts($table, $rows, $values) {
    global $mysqli;

    $all_rows = [];

    $get_types = ''; $get_values = [];
    foreach ($values as $row) {

        $for_values = [];
        foreach ($row as $value) {
            $for_values[] = '?';

            $type = gettype($value);
            if ($type == 'integer') {
                $_p = 'i';
            }else if ($type == 'double') {
                $_p = 'd';
            }else{
                $_p = 's';
            }

            $get_types .= $_p;
            $get_values[] = $value;
        }

        $all_rows[] = '('.implode(',', $for_values).')';
    }

    $sql = "INSERT INTO `$table` (".implode(', ', $rows).") VALUES ".implode(', ', $all_rows);      

    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($get_types, ...$get_values);
    $stmt->execute();
}
 
foreach ($array as $table => $rows) {
    inserts($table, ['row1', 'row2', 'row3'], $rows);
}

Ответы

▲ 0

В итоге у меня получилось сделать все вот такой функцией: (огромная просьба, указать на недостатки такого решения и на способы его оптимизации с целью ускорения выполнения)

function inserts($table, $rows, $values) {
    global $mysqli;

    $all_rows = [];

    $get_types = ''; $get_values = [];
    foreach ($values as $row) {

        $for_values = [];
        foreach ($row as $value) {
            $for_values[] = '?';

            $type = gettype($value);
            if ($type == 'integer') {
                $_p = 'i';
            }else if ($type == 'double') {
                $_p = 'd';
            }else{
                $_p = 's';
            }

            $get_types .= $_p;
            $get_values[] = $value;
        }

        $all_rows[] = '('.implode(',', $for_values).')';
    }

    $sql = "INSERT INTO `$table` (".implode(', ', $rows).") VALUES ".implode(', ', $all_rows);      

    $stmt = $mysqli->prepare($sql);
    $stmt->bind_param($get_types, ...$get_values);
    $stmt->execute();
}
 
foreach ($array as $table => $rows) {
    inserts($table, ['row1', 'row2', 'row3'], $rows);
}