Бих препоръчал да използвате INSERT...ON DUPLICATE KEY UPDATE
.
Ако използвате INSERT IGNORE
, тогава редът всъщност няма да бъде вмъкнат, ако доведе до дублиран ключ. Но изявлението няма да генерира грешка. Вместо това генерира предупреждение. Тези случаи включват:
- Вмъкване на дублиран ключ в колони с
PRIMARY KEY
илиUNIQUE
ограничения. - Вмъкване на NULL в колона с
NOT NULL
ограничение. - Вмъкване на ред в разделена таблица, но стойностите, които вмъквате, не се съпоставят с дял.
Ако използвате REPLACE
, MySQL всъщност извършва DELETE
последвано от INSERT
вътрешно, което има някои неочаквани странични ефекти:
- Разпределя се нов идентификатор за автоматично увеличение.
- Зависимите редове с външни ключове може да бъдат изтрити (ако използвате каскадни външни ключове) или да предотвратите
REPLACE
. - Задействания, които се задействат при
DELETE
се изпълняват ненужно. - Страничните ефекти се разпространяват и в копия.
корекция: и двете REPLACE
и INSERT...ON DUPLICATE KEY UPDATE
са нестандартни, патентовани изобретения, специфични за MySQL. ANSI SQL 2003 дефинира MERGE
изявление, което може да реши същата нужда (и повече), но MySQL не поддържа MERGE
изявление.
Потребител се опита да редактира тази публикация (редактирането беше отхвърлено от модераторите). Редактирането се опита да добави твърдение, което INSERT...ON DUPLICATE KEY UPDATE
причинява разпределяне на нов идентификатор за автоматично увеличение. Вярно е, че новият идентификатор е генериран , но не се използва в променения ред.
Вижте демонстрация по-долу, тествана с Percona Server 5.5.28. Конфигурационната променлива innodb_autoinc_lock_mode=1
(по подразбиране):
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
Горното показва, че операторът IODKU открива дубликата и извиква актуализацията, за да промени стойността на u
. Обърнете внимание на AUTO_INCREMENT=3
показва, че идентификаторът е генериран, но не е използван в реда.
Докато REPLACE
изтрива оригиналния ред и вмъква нов ред, генерирайки и съхраняване на нов идентификатор за автоматично увеличение:
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 1 | 20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u |
+----+------+
| 3 | 20 |
+----+------+