Saya tahu bahwa Anda dapat memasukkan beberapa baris sekaligus, apakah ada cara untuk memperbarui beberapa baris sekaligus (seperti dalam, dalam satu permintaan) di MySQL?
Sunting: Misalnya saya punya yang berikut ini
Name id Col1 Col2
Row1 1 6 1
Row2 2 2 3
Row3 3 9 5
Row4 4 16 8
Saya ingin menggabungkan semua Pembaruan berikut ke dalam satu permintaan
UPDATE table SET Col1 = 1 WHERE id = 1;
UPDATE table SET Col1 = 2 WHERE id = 2;
UPDATE table SET Col2 = 3 WHERE id = 3;
UPDATE table SET Col1 = 10 WHERE id = 4;
UPDATE table SET Col2 = 12 WHERE id = 4;
mysql
sql
sql-update
Teifion
sumber
sumber
Karena Anda memiliki nilai dinamis, Anda perlu menggunakan IF atau KASUS untuk kolom yang akan diperbarui. Agak jelek, tapi itu harusnya berhasil.
Dengan menggunakan contoh Anda, Anda bisa melakukannya seperti:
sumber
$commandTxt = 'UPDATE operations SET chunk_finished = CASE id '; foreach ($blockOperationChecked as $operationID => $operationChecked) $commandTxt .= " WHEN $operationID THEN $operationChecked "; $commandTxt .= 'ELSE id END WHERE id IN ('.implode(', ', array_keys(blockOperationChecked )).');';
Pertanyaannya sudah lama, namun saya ingin memperluas topik dengan jawaban lain.
Maksud saya adalah, cara termudah untuk mencapainya adalah dengan membungkus beberapa kueri dengan transaksi. Jawaban yang diterima
INSERT ... ON DUPLICATE KEY UPDATE
adalah hack yang bagus, tetapi orang harus menyadari kelemahan dan keterbatasannya:"Field 'fieldname' doesn't have a default value"
peringatan MySQL bahkan jika Anda tidak memasukkan satu baris sama sekali. Ini akan membuat Anda mendapat masalah, jika Anda memutuskan untuk ketat dan mengubah peringatan mysql menjadi pengecualian runtime di aplikasi Anda.Saya membuat beberapa tes kinerja untuk tiga varian yang disarankan, termasuk
INSERT ... ON DUPLICATE KEY UPDATE
varian, varian dengan klausa "case / when / then" dan pendekatan naif dengan transaksi. Anda dapat memperoleh kode python dan hasil di sini . Kesimpulan keseluruhan adalah bahwa varian dengan pernyataan kasus ternyata dua kali lebih cepat dari dua varian lainnya, tetapi cukup sulit untuk menulis kode yang benar dan aman untuknya, jadi saya pribadi tetap menggunakan pendekatan yang paling sederhana: menggunakan transaksi.Sunting: Temuan Dakusan membuktikan bahwa estimasi kinerja saya tidak cukup valid. Silakan lihat jawaban ini untuk penelitian lain yang lebih rumit.
sumber
Tidak yakin mengapa opsi lain yang bermanfaat belum disebutkan:
sumber
Semua hal berikut ini berlaku untuk InnoDB.
Saya merasa mengetahui kecepatan dari 3 metode yang berbeda itu penting.
Ada 3 metode:
Saya baru saja menguji ini, dan metode INSERT 6,7x lebih cepat untuk saya daripada metode TRANSAKSI. Saya mencoba serangkaian 3.000 dan 30.000 baris.
Metode TRANSACTION masih harus menjalankan setiap permintaan secara individual, yang membutuhkan waktu, meskipun batch hasil dalam memori, atau sesuatu, saat mengeksekusi. Metode TRANSACTION juga cukup mahal untuk replikasi dan log permintaan.
Lebih buruk lagi, metode CASE adalah 41.1x lebih lambat dari metode INSERT dengan 30.000 catatan (6.1x lebih lambat dari TRANSACTION). Dan 75x lebih lambat di MyISAM. Metode INSERT dan CASE mencapai titik ~ 1.000 catatan Bahkan pada 100 catatan, metode KASUS BARELY lebih cepat.
Jadi secara umum, saya merasa metode INSERT adalah yang terbaik dan termudah untuk digunakan. Kueri lebih kecil dan lebih mudah dibaca dan hanya mengambil 1 kueri tindakan. Ini berlaku untuk InnoDB dan MyISAM.
Barang bonus:
Solusi untuk INSERT masalah non-default-bidang adalah untuk mematikan sementara mode SQL yang relevan:
SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
. Pastikan untuk menyimpan yangsql_mode
pertama jika Anda berencana untuk mengembalikannya.Adapun komentar lain saya telah melihat bahwa mengatakan auto_increment naik menggunakan metode INSERT, ini tampaknya menjadi kasus di InnoDB, tetapi bukan MyISAM.
Kode untuk menjalankan tes adalah sebagai berikut. Ini juga menampilkan file .SQL untuk menghapus overhead penerjemah php
sumber
Gunakan tabel sementara
sumber
Ini seharusnya bekerja untukmu.
Ada referensi dalam manual MySQL untuk beberapa tabel.
sumber
Mengapa tidak ada yang menyebutkan banyak pernyataan dalam satu permintaan ?
Di php, Anda menggunakan
multi_query
metode instance mysqli.Dari manual php
Berikut adalah hasil perbandingan dengan 3 metode lainnya dalam memperbarui 30.000 mentah. Kode dapat ditemukan di sini yang didasarkan pada jawaban dari @Dakusan
Transaksi: 5.5194580554962
Masukkan: 0.20669293403625
Kasus: 16.474853992462
Multi: 0.0412278175354
Seperti yang Anda lihat, permintaan beberapa pernyataan lebih efisien daripada jawaban tertinggi.
Jika Anda mendapatkan pesan kesalahan seperti ini:
Anda mungkin perlu menambah
max_allowed_packet
file config di mysql yang ada di mesin saya/etc/mysql/my.cnf
dan kemudian restart mysqld.sumber
$mysqli->multi_query($sql)
membutuhkan waktu "0" detik. Namun, permintaan berikutnya gagal, menyebabkan saya menjadikan ini "program" yang terpisah.Ada pengaturan yang dapat Anda ubah yang disebut 'pernyataan multi' yang menonaktifkan 'mekanisme keselamatan' MySQL yang diterapkan untuk mencegah (lebih dari satu) perintah injeksi. Khas untuk implementasi MySQL yang 'brilian', ini juga mencegah pengguna melakukan kueri yang efisien.
Di sini ( http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html ) adalah beberapa info tentang implementasi C dari pengaturan.
Jika Anda menggunakan PHP, Anda dapat menggunakan mysqli untuk melakukan banyak pernyataan (saya pikir php telah dikirimkan dengan mysqli untuk sementara waktu sekarang)
Semoga itu bisa membantu.
sumber
mysqli::begin_transaction(..)
sebelum mengirim kueri danmysql::commit(..)
sesudahnya. Atau gunakan pernyataanSTART TRANSACTION
pertama danCOMMIT
terakhir dalam kueri itu sendiri.Anda bisa alias tabel yang sama untuk memberi Anda id yang ingin Anda masukkan (jika Anda melakukan pembaruan baris-demi-baris:
Selain itu, tampak jelas bahwa Anda juga dapat memperbarui dari tabel lain juga. Dalam hal ini, pembaruan berfungsi ganda sebagai pernyataan "SELECT", memberi Anda data dari tabel yang Anda tentukan. Anda secara eksplisit menyatakan dalam kueri Anda nilai-nilai pembaruan sehingga, tabel kedua tidak terpengaruh.
sumber
Anda juga mungkin tertarik menggunakan gabungan pada pembaruan, yang juga dimungkinkan.
Sunting: Jika nilai yang Anda perbarui tidak berasal dari tempat lain dalam database, Anda harus mengeluarkan beberapa permintaan pembaruan.
sumber
Dan sekarang cara mudah
sumber
menggunakan
Tolong dicatat:
sumber
Berikut ini akan memperbarui semua baris dalam satu tabel
Yang berikutnya akan memperbarui semua baris di mana nilai Column2 lebih dari 5
Ada semua contoh Unkwntech untuk memperbarui lebih dari satu tabel
sumber
Ya .. itu mungkin menggunakan INSERT ON DUPLICATE KEY UPDATE pernyataan sql .. sintaks: INSERT INTO table_name (a, b, c) VALUES (1,2,3), (4,5,6) ON DUPLICATE KEY UPDATE a = VALUES (a), b = VALUES (b), c = VALUES (c)
sumber
Ini harus mencapai apa yang Anda cari. Cukup tambahkan lebih banyak id. Saya sudah mengujinya.
sumber
// Anda hanya membangunnya seperti php
Jadi, Anda dapat memperbarui tabel lubang dengan satu permintaan
sumber
something
untuksomething
)