Mysql
 sql >> Database >  >> RDS >> Mysql

INSERT IGNORE vs INSERT... SU AGGIORNAMENTO CHIAVE DUPLICATA

Consiglierei di usare INSERT...ON DUPLICATE KEY UPDATE .

Se usi INSERT IGNORE , la riga non verrà effettivamente inserita se risulta in una chiave duplicata. Ma l'istruzione non genererà un errore. Genera invece un avviso. Questi casi includono:

  • Inserimento di una chiave duplicata nelle colonne con PRIMARY KEY o UNIQUE vincoli.
  • Inserimento di un NULL in una colonna con un NOT NULL vincolo.
  • Inserimento di una riga in una tabella partizionata, ma i valori inseriti non vengono mappati su una partizione.

Se usi REPLACE , MySQL esegue effettivamente un DELETE seguito da un INSERT internamente, che ha alcuni effetti collaterali imprevisti:

  • Viene assegnato un nuovo ID di incremento automatico.
  • Le righe dipendenti con chiavi esterne possono essere eliminate (se si utilizzano chiavi esterne a cascata) oppure impedire il REPLACE .
  • Trigger che si attivano su DELETE vengono eseguiti inutilmente.
  • Gli effetti collaterali si propagano anche alle repliche.

correzione: entrambi REPLACE e INSERT...ON DUPLICATE KEY UPDATE sono invenzioni proprietarie non standard specifiche per MySQL. ANSI SQL 2003 definisce un MERGE istruzione che può risolvere la stessa esigenza (e più), ma MySQL non supporta il MERGE dichiarazione.

Un utente ha provato a modificare questo post (la modifica è stata rifiutata dai moderatori). La modifica ha tentato di aggiungere un'attestazione che INSERT...ON DUPLICATE KEY UPDATE determina l'allocazione di un nuovo ID di incremento automatico. È vero che il nuovo ID è generato , ma non viene utilizzato nella riga modificata.

Vedere la dimostrazione di seguito, testata con Percona Server 5.5.28. La variabile di configurazione innodb_autoinc_lock_mode=1 (l'impostazione predefinita):

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

Quanto sopra dimostra che l'istruzione IODKU rileva il duplicato e richiama l'aggiornamento per modificare il valore di u . Nota il AUTO_INCREMENT=3 indica che è stato generato un ID, ma non utilizzato nella riga.

Mentre REPLACE elimina la riga originale e inserisce una nuova riga, generando e memorizzazione di un nuovo ID di incremento automatico:

mysql> select * from foo;
+----+------+
| id | u    |
+----+------+
|  1 |   20 |
+----+------+
mysql> replace into foo (u) values (20);
mysql> select * from foo;
+----+------+
| id | u    |
+----+------+
|  3 |   20 |
+----+------+