Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MySQLi :Menyisipkan beberapa baris dengan satu pernyataan yang disiapkan

Dimungkinkan untuk menyiapkan kueri pernyataan penyisipan massal dengan membuatnya dengan cepat, tetapi dibutuhkan beberapa trik. Bit yang paling penting menggunakan str_pad() untuk membuat string kueri dengan panjang variabel, dan menggunakan call_user_func_array() untuk memanggil bind_param() dengan sejumlah variabel parameter.

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

Fungsi ini mengambil $db . Anda sebagai mysqli misalnya, nama tabel, larik nama bidang, dan larik datar referensi ke nilai. Ini menyisipkan hingga 500 catatan per kueri, menggunakan kembali pernyataan yang disiapkan jika memungkinkan. Ini mengembalikan true jika semua sisipan berhasil, atau false jika salah satu dari mereka gagal. Peringatan:

  • Nama tabel dan bidang tidak diloloskan; Saya serahkan kepada Anda untuk memastikan bahwa mereka tidak mengandung backticks. Untungnya, mereka tidak boleh datang dari masukan pengguna.
  • Jika panjang $values bukan kelipatan genap dari panjang $fields , potongan terakhir mungkin akan gagal pada tahap persiapan.
  • Demikian pula, panjang $types parameter harus cocok dengan panjang $fields dalam banyak kasus, terutama ketika beberapa di antaranya berbeda.
  • Itu tidak membedakan antara tiga cara untuk gagal. Itu juga tidak melacak berapa banyak penyisipan yang berhasil, juga tidak mencoba untuk melanjutkan setelah kesalahan.

Dengan fungsi ini didefinisikan, kode contoh Anda dapat diganti dengan sesuatu seperti:

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

Ampersand itu penting, karena mysqli_stmt::bind_param mengharapkan referensi, yang tidak disediakan oleh call_user_func_array dalam versi PHP terbaru.

Anda tidak memberi kami pernyataan asli yang disiapkan, jadi Anda mungkin perlu menyesuaikan nama tabel dan bidang. Sepertinya kode Anda juga berada di dalam satu lingkaran di atas $i; dalam hal ini, hanya for loop harus berada di dalam loop luar. Jika Anda mengambil baris lain di luar loop, Anda akan menggunakan sedikit lebih banyak memori untuk membangun $inserts array, sebagai imbalan untuk penyisipan massal yang jauh lebih efisien.

Anda juga dapat menulis ulang insertBulkPrepared() untuk menerima larik multidimensi, menghilangkan satu sumber kesalahan potensial, tetapi itu membutuhkan perataan larik setelah memotongnya.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah ada cara dalam SQL (MySQL) untuk melakukan round robin ORDER BY pada bidang tertentu?

  2. URL dan teks tautan dari basis data

  3. gabungkan satu baris ke semua baris dan kembalikan semua baris

  4. MySQL Fulltext dengan urutan kata tertentu

  5. Beralih ke Pernyataan yang Disiapkan