Saya akan merekomendasikan menggunakan INSERT...ON DUPLICATE KEY UPDATE
.
Jika Anda menggunakan INSERT IGNORE
, maka baris tersebut tidak akan benar-benar dimasukkan jika menghasilkan kunci duplikat. Tetapi pernyataan itu tidak akan menghasilkan kesalahan. Alih-alih menghasilkan peringatan. Kasus-kasus ini meliputi:
- Memasukkan kunci duplikat dalam kolom dengan
PRIMARY KEY
atau UNIQUE
kendala.
- Memasukkan NULL ke dalam kolom dengan
NOT NULL
batasan.
- Menyisipkan baris ke tabel dipartisi, tetapi nilai yang Anda masukkan tidak memetakan ke partisi.
Jika Anda menggunakan REPLACE
, MySQL sebenarnya DELETE
diikuti oleh INSERT
internal, yang memiliki beberapa efek samping yang tidak terduga:
- ID kenaikan-otomatis baru dialokasikan.
- Baris bergantung dengan kunci asing dapat dihapus (jika Anda menggunakan kunci asing mengalir) atau mencegah
REPLACE
.
- Pemicu yang menyala
DELETE
dijalankan tidak perlu.
- Efek samping juga disebarkan ke replika.
koreksi: keduanya REPLACE
dan INSERT...ON DUPLICATE KEY UPDATE
non-standar, penemuan eksklusif untuk MySQL. ANSI SQL 2003 mendefinisikan MERGE
pernyataan yang dapat menyelesaikan kebutuhan yang sama (dan banyak lagi), tetapi MySQL tidak mendukung MERGE
pernyataan itu.
Seorang pengguna mencoba mengedit posting ini (hasil edit ditolak oleh moderator). Hasil edit mencoba menambahkan klaim yang INSERT...ON DUPLICATE KEY UPDATE
menyebabkan id penambahan otomatis baru dialokasikan. Benar bahwa id baru dibuat , tetapi tidak digunakan di baris yang diubah.
Lihat demonstrasi di bawah, diuji dengan Percona Server 5.5.28. Variabel konfigurasi innodb_autoinc_lock_mode=1
(default):
mysql> create table foo (id serial primary key, u int, unique key (u));
mysql> insert into foo (u) values (10);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 10 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
mysql> insert into foo (u) values (10) on duplicate key update u = 20;
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> show create table foo\G
CREATE TABLE `foo` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`u` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `u` (`u`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
Di atas menunjukkan bahwa pernyataan IODKU mendeteksi duplikat, dan meminta pembaruan untuk mengubah nilai u
. Perhatikan AUTO_INCREMENT=3
menunjukkan bahwa id dihasilkan, tetapi tidak digunakan di baris.
Sedangkan REPLACE
menghapus baris asli dan menyisipkan baris baru, menghasilkan dan menyimpan id kenaikan otomatis baru:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+
INSERT ... ON DUPLICATE KEY UPDATE ...
pernyataan. Banyak data duplikat, dan telah menghasilkan satu contoh dari PK AI meningkat dari 17.029.941 menjadi 46.271.740 antara dua baris. Generasi AI baru setiap kali berarti jangkauan Anda dapat dengan sangat cepat diisi dan Anda perlu membersihkannya. Meja ini baru berumur dua minggu!Jika Anda ingin melihat apa arti semua ini, berikut adalah pukulan dari segalanya:
Kunci primer didasarkan pada kedua kolom dari tabel referensi cepat ini. Kunci primer memerlukan nilai unik.
Mari kita mulai:
perhatikan, di atas menyimpan terlalu banyak pekerjaan tambahan dengan mengatur kolom sama dengan dirinya sendiri, tidak ada pembaruan yang benar-benar diperlukan
dan sekarang beberapa tes baris:
tidak ada pesan lain yang dihasilkan di konsol, dan sekarang ada 4 nilai di tabel data. Saya menghapus semuanya kecuali (1,1) sehingga saya bisa menguji dari lapangan bermain yang sama
Jadi begitulah. Karena ini semua dilakukan di atas meja baru dengan hampir tidak ada data dan tidak dalam produksi, waktu pelaksanaannya adalah mikroskopis dan tidak relevan. Siapa pun dengan data dunia nyata akan lebih dari senang untuk berkontribusi.
sumber
INSERT IGNORE INTO users_partners (uid,pid) VALUES (1,1),(1,2),(1,3),(1,4)
.Sesuatu yang penting untuk ditambahkan: Ketika menggunakan INSERT IGNORE dan Anda memang memiliki pelanggaran utama, MySQL TIDAK memunculkan peringatan!
Jika Anda mencoba misalnya untuk memasukkan 100 catatan sekaligus, dengan satu catatan yang salah, Anda akan mendapatkan dalam mode interaktif:
Seperti yang Anda lihat: Tidak Ada Peringatan! Perilaku ini bahkan salah dijelaskan dalam Dokumentasi Mysql resmi.
Jika skrip Anda perlu diinformasikan, jika beberapa catatan belum ditambahkan (karena pelanggaran utama), Anda harus memanggil mysql_info () dan menguraikannya untuk nilai "Duplikat".
sumber
mysqli_affected_rows()
untuk mengetahui apakah ituINSERT
benar - benar terjadi.Cannot add or update a child row: a foreign key constraint fails
dan tidak ada baris (bahkan yang valid) ditambahkan.INSERT IGNORE
, kunci duplikat diabaikan tanpa kesalahan atau peringatan.Saya secara rutin menggunakan
INSERT IGNORE
, dan sepertinya jenis perilaku yang Anda cari juga. Selama Anda tahu bahwa baris yang akan menyebabkan konflik indeks tidak akan dimasukkan dan Anda merencanakan program Anda sesuai, itu seharusnya tidak menyebabkan masalah.sumber
Saya tahu ini sudah tua, tetapi saya akan menambahkan catatan ini jika ada orang lain (seperti saya) tiba di halaman ini ketika mencoba mencari informasi di INSERT..IGNORE.
Seperti disebutkan di atas, jika Anda menggunakan INSERT..IGNORE, kesalahan yang terjadi saat menjalankan pernyataan INSERT diperlakukan sebagai peringatan.
Satu hal yang tidak disebutkan secara eksplisit adalah bahwa INSERT..IGNORE akan menyebabkan nilai yang tidak valid akan disesuaikan dengan nilai terdekat saat dimasukkan (sedangkan nilai yang tidak valid akan menyebabkan permintaan dibatalkan jika kata kunci IGNORE tidak digunakan).
sumber
DI UPDATE KUNCI DUPLICATE tidak benar - benar dalam standar. Ini tentang standar seperti REPLACE. Lihat SQL MERGE .
Pada dasarnya kedua perintah adalah versi sintaks alternatif dari perintah standar.
sumber
Replace
Sepertinya pilihan. Atau Anda bisa memeriksanyaIni akan menyisipkan atau menghapus lalu menyisipkan. Saya cenderung pergi untuk
IF NOT EXISTS
cek dulu.sumber
REPLACE
menghapus semua baris dalam tabel dengan mencocokkan tombol atau apa pun , lalu . Ini berpotensi lebih banyak pekerjaan daripada IODKU.PRIMARY
UNIQUE
INSERTs
Bahaya potensial INSERT IGNORE. Jika Anda mencoba memasukkan nilai VARCHAR lebih lama dari itu kolom didefinisikan dengan - nilai akan dipotong dan disisipkan BAHKAN JIKA mode ketat diaktifkan.
sumber
Jika menggunakan
insert ignore
memilikiSHOW WARNINGS;
pernyataan di akhir set kueri Anda akan menampilkan tabel dengan semua peringatan, termasuk ID mana yang merupakan duplikat.sumber
SHOW WARNINGS;
sepertinya hanya memengaruhi kueri terbaru. Pernyataan sebelumnya tidak diakumulasi, jika Anda memiliki lebih dari satu pernyataan.Jika Anda ingin menyisipkan dalam tabel dan pada konflik kunci utama atau indeks unik itu akan memperbarui baris yang bertentangan daripada memasukkan baris itu.
Sintaksis:
Sekarang di sini, pernyataan penyisipan ini mungkin terlihat berbeda dari yang Anda lihat sebelumnya. Pernyataan penyisipan ini mencoba menyisipkan baris dalam table1 dengan nilai a dan b ke dalam kolom1 dan kolom2 masing-masing.
Mari kita memahami pernyataan ini secara mendalam:
Sebagai contoh: di sini kolom1 didefinisikan sebagai kunci utama dalam tabel1.
Sekarang jika dalam table1 tidak ada baris yang memiliki nilai "a" di kolom1. Jadi pernyataan ini akan menyisipkan baris di table1.
Sekarang jika dalam table1 ada baris yang memiliki nilai "a" di kolom2. Jadi pernyataan ini akan memperbarui nilai kolom2 baris dengan "c" di mana nilai column1 adalah "a".
Jadi, jika Anda ingin menyisipkan baris baru, perbarui baris tersebut pada konflik kunci utama atau indeks unik.
Baca lebih lanjut tentang tautan ini
sumber
INSERT...ON DUPLICATE KEY UPDATE
lebih disukai untuk mencegah manajemen Pengecualian yang tidak terduga.Solusi ini berfungsi saat Anda memiliki ** 1 batasan unik ** saja
Dalam kasus saya, saya tahu itu
col1
dancol2
membuat indeks komposit yang unik.Ini melacak kesalahan, tetapi tidak melempar pengecualian pada duplikat. Mengenai kinerja, pembaruan dengan nilai yang sama efisien karena pemberitahuan MySQL ini dan tidak memperbaruinya
Gagasan untuk menggunakan pendekatan ini berasal dari komentar di phpdelusions.net/pdo .
sumber