sql >> Databáze >  >> RDS >> Mysql

INSERT IGNORE vs INSERT ... PŘI AKTUALIZACI DUPLIKÁTNÍHO KLÍČE

Doporučil bych použít INSERT...ON DUPLICATE KEY UPDATE .

Pokud používáte INSERT IGNORE , pak se řádek ve skutečnosti nevloží, pokud výsledkem bude duplicitní klíč. Ale příkaz nevygeneruje chybu. Místo toho generuje varování. Mezi tyto případy patří:

  • Vložení duplicitního klíče do sloupců pomocí PRIMARY KEY nebo UNIQUE omezení.
  • Vložení hodnoty NULL do sloupce s hodnotou NOT NULL omezení.
  • Vložení řádku do rozdělené tabulky, ale vložené hodnoty se nemapují na oddíl.

Pokud použijete REPLACE , MySQL ve skutečnosti provádí DELETE následuje INSERT interně, což má některé neočekávané vedlejší účinky:

  • Je přiděleno nové ID automatického zvýšení.
  • Závislé řádky s cizími klíči mohou být smazány (pokud používáte kaskádové cizí klíče) nebo jinak zabránit REPLACE .
  • Spouštěče, které se spouštějí při DELETE jsou prováděny zbytečně.
  • Nežádoucí účinky se šíří i do replik.

oprava: oba REPLACE a INSERT...ON DUPLICATE KEY UPDATE jsou nestandardní, proprietární vynálezy specifické pro MySQL. ANSI SQL 2003 definuje MERGE příkaz, který může vyřešit stejnou potřebu (a další), ale MySQL nepodporuje MERGE prohlášení.

Uživatel se pokusil upravit tento příspěvek (úprava byla zamítnuta moderátory). Úprava se pokusila přidat nárok, který INSERT...ON DUPLICATE KEY UPDATE způsobí přidělení nového ID automatického zvýšení. Je pravda, že nové ID je vygenerováno , ale ve změněném řádku se nepoužívá.

Viz ukázka níže, testováno s Percona Server 5.5.28. Konfigurační proměnná innodb_autoinc_lock_mode=1 (výchozí):

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

Výše uvedené ukazuje, že příkaz IODKU detekuje duplikát a vyvolá aktualizaci za účelem změny hodnoty u . Všimněte si AUTO_INCREMENT=3 označuje, že ID bylo vygenerováno, ale nebylo použito v řádku.

Zatímco REPLACE odstraní původní řádek a vloží nový řádek, vygeneruje a uložení nového ID automatického zvýšení:

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


  1. 3 oblasti, které budou mít prospěch z použití nástroje pro sledování výkonu serveru SQL Server

  2. Zakázat a později povolit všechny indexy tabulek v Oracle

  3. Připojení k databázi Oracle pomocí Sql Server Integration Services

  4. Jak zjistit dotaz, který drží zámek v Postgres?