Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQLi:Вмъкване на множество редове с един подготвен оператор

Възможно е да подготвите групова заявка за оператор за вмъкване, като я конструирате в движение, но това изисква няколко трика. Най-важните битове използват str_pad() за конструиране на низ на заявка с променлива дължина и използване на call_user_func_array() за извикване на bind_param() с променлив брой параметри.

function insertBulkPrepared($db, $table, $fields, $types, $values) {
    $chunklength = 500;
    $fieldcount = count($fields);
    $fieldnames = '`'.join('`, `', $fields).'`';
    $prefix = "INSERT INTO `$table` ($fieldnames) VALUES ";
    $params = '(' . str_pad('', 3*$fieldcount - 2, '?, ') . '), ';
    $inserted = 0;

    foreach (array_chunk($values, $fieldcount*$chunklength) as $group) {
        $length = count($group);
        if ($inserted != $length) {
            if ($inserted) $stmt->close();
            $records = $length / $fieldcount;
            $query = $prefix . str_pad('', 3*$length + 2*($records - 1), $params);
            #echo "\n<br>Preparing '" . $query . "'";
            $stmt = $db->prepare($query);
            if (!$stmt) return false;
            $binding = str_pad('', $length, $types);
            $inserted = $length;
        }

        array_unshift($group, $binding);
        #echo "\n<br>Binding " . var_export($group, true);
        $bound = call_user_func_array(array($stmt, 'bind_param'), $group);
        if (!$bound) return false;
        if (!$stmt->execute()) return false;
    }

    if ($inserted) $stmt->close();
    return true;
}

Тази функция взема вашите $db като mysqli екземпляр, име на таблица, масив от имена на полета и плосък масив от препратки към стойности. Той вмъква до 500 записа на заявка, като използва повторно подготвени изрази, когато е възможно. Връща true ако всички вмъквания са успешни, или false ако някой от тях се провали. Предупреждения:

  • Имената на таблицата и полетата не се екранират; Оставям на вас да се уверите, че те не съдържат обратни точки. За щастие, те никога не трябва да идват от потребителски вход.
  • Ако дължината на $values не е четно кратно на дължината на $fields , последната част вероятно ще се провали на подготвителния етап.
  • По същия начин дължината на $types параметърът трябва да съответства на дължината на $fields в повечето случаи, особено когато някои от тях се различават.
  • Не прави разлика между трите начина за провал. Освен това не следи колко успешни вмъквания, нито се опитва да продължи след грешка.

С тази дефинирана функция вашият примерен код може да бъде заменен с нещо като:

$inserts = array();
for ($j = 0; $j < $abilitiesMax - 2; $j++) {
    $inserts[] = &$abilityArray[$i]['match_id'];
    $inserts[] = &$abilityArray[$i]['player_slot'];
    $inserts[] = &$abilityArray[$i][$j]['ability'];
    $inserts[] = &$abilityArray[$i][$j]['time'];
    $inserts[] = &$abilityArray[$i][$j]['level'];
}

$fields = array('match_id', 'player_slot', 'ability', 'time', 'level');
$result = insertBulkPrepared($db, 'abilities', $fields, 'iiiii', $inserts);
if (!$result) {
    echo "<p>$db->error</p>";
    echo "<p>ERROR: when trying to insert abilities query</p>";
}

Тези амперсанд са важни, защото mysqli_stmt::bind_param очаква препратки, които не са предоставени от call_user_func_array в последните версии на PHP.

Не ни предоставихте оригиналния подготвен отчет, така че вероятно трябва да коригирате имената на таблицата и полетата. Също така изглежда, че вашият код се намира в цикъл над $i; в този случай само for трябва да е вътре във външния цикъл. Ако изведете другите редове извън цикъла, ще използвате малко повече памет за конструиране на $inserts масив, в замяна на много по-ефективни групови вмъквания.

Също така е възможно да пренапишете insertBulkPrepared() за приемане на многоизмерен масив, елиминирайки един източник на потенциална грешка, но това изисква изравняване на масива след разделянето му.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Защо тези 2 MySQL заявки връщат различни резултати

  2. как да създадете 3 зависими падащ списък с помощта на PHP ajax JQUERY?

  3. CONVERT_TZ – Как да промените часовата зона на MySQL в заявка

  4. Таблица, посочена два пъти в процедурата, как да коригирам?

  5. Нуждаете се от помощ за развъртане в mysql с множество колони за дата