sql >> Databasteknik >  >> RDS >> Mysql

Hur man infogar om rad inte finns (UPSERT) i MySQL

  • Med INSERT IGNORE
  • Med REPLACE
  • Med INSERT ... ON DUPLICATE KEY UPDATE

MySQL tillhandahåller ett antal användbara uttalanden när det är nödvändigt att INSERTED rader efter avgöra om den raden faktiskt är ny eller redan existerar.

Nedan kommer vi att undersöka de tre olika metoderna och förklara fördelarna och nackdelarna med var och en i tur och ordning så att du har ett fast grepp om hur du konfigurerar dina egna uttalanden när du tillhandahåller nya eller potentiellt befintliga data för INSERTION .

Använda INSERT IGNORE

Använder INSERT IGNORE får MySQL att ignorera effektivt exekveringsfel vid försök att utföra INSERTED uttalanden. Detta betyder att en INSERT IGNORE sats som innehåller ett dubblettvärde i en UNIQUE index eller PRIMARY KEY fältet inte producerar ett fel, men kommer istället helt enkelt att ignorera den specifika INSERTED kommandot helt och hållet. Det uppenbara syftet är att köra ett stort antal INSERTED uttalanden för en kombination av data som både redan finns i databasen och nya data som kommer in i systemet.

Till exempel våra books Tabell kan redan innehålla några poster:

mysql> SELECT * FROM books LIMIT 3;
+----+-------------------------+---------------------+----------------+
| id | title                   | author              | year_published |
+----+-------------------------+---------------------+----------------+
|  1 | In Search of Lost Time  | Marcel Proust       |           1913 |
|  2 | Ulysses                 | James Joyce         |           1922 |
|  3 | Don Quixote             | Miguel de Cervantes |           1605 |
+----+-------------------------+---------------------+----------------+
3 rows in set (0.00 sec)

Om vi ​​har en stor mängd nya och befintliga data att INSERTED och en del av den datan innehåller ett matchande värde för id fält (som är en UNIQUE PRIMARY_KEY i tabellen), med en grundläggande INSERTED kommer att ge ett förväntat fel:

mysql> INSERT INTO books
    (id, title, author, year_published)
VALUES
    (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

Å andra sidan, om vi använder INSERT IGNORE , dupliceringsförsöket ignoreras och inga resulterande fel uppstår:

mysql> INSERT IGNORE INTO books
    (id, title, author, year_published)
VALUES
    (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
Query OK, 0 rows affected (0.00 sec)

Använda REPLACE

I händelse av att du faktiskt vill byta ut rader där INSERTED kommandon skulle producera fel på grund av dubbletter av UNIQUE eller PRIMARY KEY värden som beskrivs ovan är ett alternativ att välja REPLACE uttalande.

När du utfärdar en REPLACE uttalande finns det två möjliga utfall för varje utfärdat kommando:

  • Ingen befintlig datarad hittades med matchande värden och därmed en standard INSERTED uttalande utförs.
  • En matchande datarad är hittas, vilket gör att den befintliga raden raderas med standarden DELETE sats, sedan en normal INSERTED utförs efteråt.

Till exempel kan vi använda REPLACE för att byta ut vår befintliga post med id = 1 av I Search of Lost Time av Marcel Proust med Gröna ägg och skinka av Dr. Seuss:

mysql> REPLACE INTO books
    (id, title, author, year_published)
VALUES
    (1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
Query OK, 2 rows affected (0.00 sec)

Observera att även om vi bara ändrade en rad, indikerar resultatet att två rader påverkades eftersom vi faktiskt DELETED den befintliga raden och sedan INSERTED den nya raden för att ersätta den.

Mer information om hur du använder REPLACE finns i den officiella dokumentationen.

Använda INSERT ... ON DUPLICATE KEY UPDATE

Den alternativa (och generellt föredragna) metoden för INSERTING i rader som kan innehålla dubbletter av UNIQUE eller PRIMARY KEY värden är att använda INSERT ... ON DUPLICATE KEY UPDATE uttalande och klausul.

Till skillnad från REPLACE – ett i sig destruktivt kommando på grund av DELETE kommandon som den utför när det behövs – med INSERT ... ON DUPLICATE KEY UPDATE är icke-förstörande , eftersom det bara kommer att utfärda INSERTED eller UPDATE uttalanden, men aldrig DELETE .

Till exempel har vi bestämt att vi vill ersätta vårt id = 1 register över Gröna ägg och skinka och återställ den till originalet In Search of Lost Time spela in istället. Vi kan därför ta vår ursprungliga INSERTED uttalande och lägg till den nya ON DUPLICATE KEY UPDATE klausul:

mysql> SET @id = 1,
    @title = 'In Search of Lost Time',
    @author = 'Marcel Proust',
    @year_published = 1913;
INSERT INTO books
    (id, title, author, year_published)
VALUES
    (@id, @title, @author, @year_published)
ON DUPLICATE KEY UPDATE
    title = @title,
    author = @author,
    year_published = @year_published;

Observera att vi använder normal UPDATE syntax (men exklusive den onödiga table namn och SET nyckelord), och bara tilldelar non-UNIQUE värden. Även om det är onödigt för ON DUPLICATE KEY UPDATE metod för att fungera korrekt har vi också valt att använda user variables så vi behöver inte specificera de faktiska värdena vi vill INSERTED eller UPDATE mer än en gång.

Som ett resultat blir vårt id = 1 posten var korrekt UPDATED som förväntat:

mysql> SELECT * FROM books LIMIT 1;
+----+------------------------+---------------+----------------+
| id | title                  | author        | year_published |
+----+------------------------+---------------+----------------+
|  1 | In Search of Lost Time | Marcel Proust |           1913 |
+----+------------------------+---------------+----------------+
1 row in set (0.00 sec)

Mer information finns i den officiella dokumentationen.


  1. Hur returnerar man en resultatuppsättning/markör från ett anonymt Oracle PL/SQL-block som kör Dynamic SQL?

  2. PDO förberedde satsen fetch() som returnerar dubbla resultat

  3. 3 sätt att lista alla lagrade procedurer i en PostgreSQL-databas

  4. Postgres 9.1 vs Mysql 5.6 InnoDB?