Inserisci in una tabella MySQL o aggiorna se esiste


875

Voglio aggiungere una riga a una tabella del database, ma se esiste una riga con la stessa chiave univoca voglio aggiornare la riga.

Per esempio:

insert into table (id, name, age) values(1, "A", 19)

Diciamo che la chiave unica è id, e nel mio database , c'è una riga con id = 1. In tal caso, voglio aggiornare quella riga con questi valori. Normalmente questo dà un errore.
Se lo uso insert IGNOREignorerà l'errore, ma non verrà aggiornato.


6
SQL ha bisogno di una sintassi ufficiale per questo caso d'uso che non imponga la duplicazione dei valori nella sintassi e conserva la chiave primaria.
Pete Alvin,

Per ottenere l'id influenzato fare riferimento a MySQL ON DUPLICATE KEY - id ultimo inserimento?
Kris Roofe,

Avvertenza: dalla versione 5.7 questo approccio non supporta direttamente la clausola WHERE come parte dell'operazione INSERT / UPDATE. Inoltre, un AGGIORNAMENTO conta effettivamente come due operazioni separate (ELIMINA e INSERISCI) ... nel caso in cui ciò sia importante ai fini della verifica. (Learnbit)
dreftymac,

Risposte:


1600

Uso INSERT ... ON DUPLICATE KEY UPDATE

DOMANDA:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name="A", age=19

86
+1 Da quello che ho trovato, questo metodo è meno problematico per le chiavi di incremento automatico e altre collisioni di chiavi univoche rispetto a SOSTITUIRE INTO, ed è più efficiente.
Andrew Ensley,

46
So che tutti voi alludete a questo, ma voglio essere esplicito per gli altri. Se l'ID inserito NON è il PRIMARY KEY o UNIQUE, questo non funzionerà. Inizialmente non funzionava per me perché il mio ID non era univoco.
Keven,

7
Mi chiedo perché affected row countrisultati 2quando si aggiorna correttamente (su chiave duplicata) singola riga? Qualcun altro ha avuto questo risultato? (I dati sono aggiornati correttamente: significa che viene aggiornata solo 1 riga)
Dimitry K

15
Questo è un po 'tardi, ma comunque: nel manuale è indicato che si aggiorna ON DUPLICATE KEY UPDATEaumentando le righe interessate di 2. Segnala 0 se nulla è effettivamente aggiornato (uguale al normale UPDATE).
Vatev,

61
Si noti inoltre che è possibile utilizzare VALORI (nome) per fare riferimento al valore che si tenta di inserire, ad esempio INSERIRE tabella (ID, nome, età) VALORI (1, "A", 19) SU DUPLICATE KEY UPDATE nome = VALORI (nome) , età = VALORI (età)
Curioso Sam

246

Dai un'occhiata a SOSTITUISCI

http://dev.mysql.com/doc/refman/5.0/en/replace.html

REPLACE into table (id, name, age) values(1, "A", 19)

11
@Piontek Perché questo è più breve e più facile da capire e nessuno ha spiegato perché "inserire in duplicato" sia migliore.
Mr_Chimp,

77
cambia gli ID del record e quindi può distruggere riferimenti stranieri.
boh,

102
L'altro problema con REPLACE INTO è che è necessario specificare i valori per TUTTI i campi ... altrimenti i campi andranno persi o sostituiti con i valori predefiniti. REPLACE INTO elimina essenzialmente la riga se esiste e inserisce la nuova riga. Nell'esempio, se si sostituisse 'SOSTITUIRE I valori della tabella (id, age) (1, 19), il campo del nome diventerebbe nullo.
Dale,

33
In realtà, questo elimina l'intera riga ed esegue un nuovo INSERT.
mjb,

8
@mjb Quindi devi avere i privilegi DELETE, che è meglio non avere se non ne hai bisogno. L'utente del database del mio ambiente ha solo le autorizzazioni INSERT e UPDATE, quindi REPLACE non funzionerà.
ndm13,

54

Quando si utilizza l'inserimento batch, utilizzare la sintassi seguente:

INSERT INTO TABLE (id, name, age) VALUES (1, "A", 19), (2, "B", 17), (3, "C", 22)
ON DUPLICATE KEY UPDATE
    name = VALUES (name),
    ...

Molto utile se vuoi manipolare il nuovo valore
Fame

Se VALUES(name)non funziona, puoi provarename = 'name_value',...;
Son Pham il

26

Prova questo:

INSERT INTO table (id, name, age) VALUES (1, 'A', 19) ON DUPLICATE KEY UPDATE id = id + 1;

Spero che sia di aiuto.


6
in realtà non ho bisogno di aggiungere i nuovi valori a un'altra riga con un nuovo ID, invece voglio sostituire i valori esistenti di id = 1 con questi valori. (A quanto ho capito, questo aumenta l'id e aggiunge i dati)
Keshan,

49
Non penso che voglia aumentare l'ID di uno sui duplicati.
Donnie,

7
"trasgresso" non è la parola che stai cercando :) Sfortunatamente, ora ho visto "trasgresso", non riesco più a visualizzare la parola reale ..
mwfearnley

1
Stavi cercando "traverses" o "cover"?
Chris Dev,

4
@mwfearnley La parola che stavi cercando di visualizzare è "trascende". Ci sono voluti solo un anno e mezzo :-)
Michael Krebs,

20

Prova questo:

INSERT INTO table (id,name,age) VALUES('1','Mohammad','21') ON DUPLICATE KEY UPDATE name='Mohammad',age='21'

Nota:
qui se id è la chiave primaria, dopo il primo inserimento id='1'ogni volta che si tenta di inserire id='1'verranno aggiornati il ​​nome e l'età e l'età del nome precedente cambierà.


Voglio lavorare senza usare l' id . Hai provato senza chiave primaria?
ersks

@ersks vedi la domanda. l'utente ha chiesto quando esiste una chiave univoca
Rasel,

L'ho capito, ma sto cercando di risolvere il mio problema in cui questi unici valori sono noti. Quindi, in tale situazione, ho scritto sopra il commento nella speranza di una soluzione corretta.
ersks

15
INSERT IGNORE INTO table (id, name, age) VALUES (1, "A", 19);

INSERT INTO TABLE (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE NAME = "A", AGE = 19;

REPLACE INTO table (id, name, age) VALUES(1, "A", 19);

Tutte queste soluzioni funzioneranno per quanto riguarda la tua domanda.

Se vuoi sapere in dettaglio riguardo a queste affermazioni visita questo link


REPLACEnon è documentato nel documento collegato.
Ray Baxter,

query sql piene di errori di battitura, i tuoi esempi non funzioneranno. È INSERIRE IN TABELLA (non IN TABELLA) e SU DUPLICATE KEY UPDATE (non SU DUPLICATE UPDATE SET). Non sono sicuro di chi abbia votato per questo
Robert Sinclair il

1
Ci scusiamo per l'errore di battitura. Grazie per avermi corretto
Dilraj Singh,

11

Quando si utilizza SQLite:

REPLACE into table (id, name, age) values(1, "A", 19)

A condizione che idsia la chiave primaria. Altrimenti inserisce semplicemente un'altra riga. Vedi INSERT (SQLite).


Quello che replace intofa è esattamente "inserisci o aggiorna quando esistente". @Owl
DawnSong

+1 (1 di 3) Ho trovato che questo funzionasse per la mia situazione: dovevo sostituire una riga esistente con una chiave univoca o, in caso contrario, aggiungere la riga. Le soluzioni più semplici qui.
therobyouknow,

(2 di 3) La mia domanda:CREATE TRIGGER worklog_update AFTER INSERT ON worklog FOR EACH ROW REPLACE INTO support_time_monthly_hours ( ProjectID, monthTotalTime, Year, Month ) SELECT jiraissue.PROJECT, SUM(worklog.timeworked), YEAR(CURRENT_DATE()), MONTH(CURRENT_DATE()) FROM worklog, jiraissue WHERE worklog.issueid = jiraissue.ID AND jiraissue.PROJECT = (SELECT PROJECT FROM jiraissue WHERE NEW.issueid = jiraissue.ID ) AND worklog.startdate BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01 00:00:00') AND NOW();
therobyouknow il

(3 di 3) domanda / risposta correlati stackoverflow.com/questions/41767517/...
therobyouknow

2
Il problema con questo in mysql è che sostituirà rimuoverà altri valori nel caso in cui non vengano forniti. Tuttavia, la soluzione @ fabiano-souza è più appropriata
Quamber Ali

11

Solo perché ero qui alla ricerca di questa soluzione, ma per l'aggiornamento da un'altra tabella strutturata in modo identico (nel mio caso il sito Web test DB per live DB):

INSERT  live-db.table1
SELECT  *
FROM    test-db.table1 t
ON DUPLICATE KEY UPDATE
        ColToUpdate1 = t.ColToUpdate1,
        ColToUpdate2 = t.ColToUpdate2,
        ...

Come menzionato altrove, solo le colonne che si desidera aggiornare devono essere incluse dopo ON DUPLICATE KEY UPDATE.

Non è necessario elencare le colonne in INSERTo SELECT, anche se concordo sul fatto che probabilmente è una pratica migliore.


4

Nel caso in cui volessi creare un non-primarycampo come criterio / condizione per ON DUPLICATE, puoi creare una UNIQUE INDEXchiave su quella tabella per attivare il DUPLICATE.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`);

E nel caso in cui desideri combinare due campi per renderlo univoco sulla tabella, puoi ottenerlo aggiungendo altro sull'ultimo parametro.

ALTER TABLE `table` ADD UNIQUE `unique_index`(`name`, `age`);

Nota, assicurati di eliminare prima tutti i dati che hanno lo stesso namee agevalore nelle altre righe.

DELETE table FROM table AS a, table AS b WHERE a.id < b.id 
AND a.name <=> b.name AND a.age <=> b.age;

Successivamente, dovrebbe attivare l' ON DUPLICATEevento.

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name = VALUES(name), age = VALUES(age)

2

Nel mio caso ho creato le query seguenti, ma nella prima query se id1 è già esistente e l'età è già lì, dopo di ciò se si crea la prima query senza ageche il valore di agesarà nessuno

REPLACE into table SET `id` = 1, `name` = 'A', `age` = 19

per evitare il problema precedente, creare una query come di seguito

INSERT INTO table SET `id` = '1', `name` = 'A', `age` = 19 ON DUPLICATE KEY UPDATE `id` = "1", `name` = "A",`age` = 19

possa aiutarti ...


2
Qualcuno sa perché dobbiamo assegnare i valori due volte? Perché MySQL non ci consente di terminare la query a ON DUPLICATE KEY UPDATE senza duplicare tutte le istruzioni di assegnazione? Alcune tabelle del database hanno molte colonne e questo sembra ridondante / gratuito. Capisco perché abbiamo l'opzione per incarichi alternativi, ma perché non abbiamo anche l'opzione di ometterli? Solo curioso se qualcuno lo sa.
Blue Water,

2

Nel caso, si desidera mantenere il vecchio campo (ad esempio: nome). La query sarà:

INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE    
name=name, age=19;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.