Saya akan merekomendasikan menggunakan INSERT...ON DUPLICATE KEY UPDATE
.
Jika Anda menggunakan INSERT IGNORE
, maka baris tersebut tidak akan benar-benar disisipkan jika menghasilkan kunci duplikat. Tetapi pernyataan itu tidak akan menghasilkan kesalahan. Ini menghasilkan peringatan sebagai gantinya. Kasus-kasus ini meliputi:
- Memasukkan kunci duplikat di kolom dengan
PRIMARY KEY
atauUNIQUE
kendala. - Memasukkan NULL ke dalam kolom dengan
NOT NULL
kendala. - Menyisipkan baris ke tabel yang dipartisi, tetapi nilai yang Anda masukkan tidak dipetakan ke partisi.
Jika Anda menggunakan REPLACE
, MySQL sebenarnya melakukan DELETE
diikuti dengan INSERT
secara internal, yang memiliki beberapa efek samping yang tidak terduga:
- ID peningkatan otomatis baru dialokasikan.
- Baris dependen dengan kunci asing dapat dihapus (jika Anda menggunakan kunci asing bertingkat) atau mencegah
REPLACE
. - Pemicu yang diaktifkan pada
DELETE
dieksekusi secara tidak perlu. - Efek samping juga disebarkan ke replika.
koreksi: keduanya REPLACE
dan INSERT...ON DUPLICATE KEY UPDATE
adalah non-standar, penemuan eksklusif khusus untuk MySQL. ANSI SQL 2003 mendefinisikan sebuah MERGE
pernyataan yang dapat menyelesaikan kebutuhan yang sama (dan lebih banyak lagi), tetapi MySQL tidak mendukung MERGE
pernyataan.
Seorang pengguna mencoba mengedit posting ini (editan ditolak oleh moderator). Hasil edit mencoba menambahkan klaim bahwa INSERT...ON DUPLICATE KEY UPDATE
menyebabkan id kenaikan otomatis baru dialokasikan. Memang 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 id telah dibuat, tetapi tidak digunakan dalam 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 |
+----+------+