Tabella MySql Inserisci se non esiste altrimenti aggiorna


105
UPDATE AggregatedData SET datenum="734152.979166667", 
Timestamp="2010-01-14 23:30:00.000" WHERE datenum="734152.979166667";

Funziona se datenumesiste, ma voglio inserire questi dati come una nuova riga se datenumnon esiste.

AGGIORNARE

il dato è univoco ma non è la chiave primaria


2
"Datenum" è unico? È possibile utilizzare INSERT ... ON DUPLICATE KEY UPDATE se lo è.
Jacob

Risposte:


143

Jai è corretto che dovresti usare INSERT ... ON DUPLICATE KEY UPDATE.

Nota che non è necessario includere il datenum nella clausola di aggiornamento poiché è la chiave univoca, quindi non dovrebbe cambiare. Devi includere tutte le altre colonne della tua tabella. È possibile utilizzare la VALUES()funzione per assicurarsi che vengano utilizzati i valori corretti durante l'aggiornamento delle altre colonne.

Ecco il tuo aggiornamento riscritto usando la INSERT ... ON DUPLICATE KEY UPDATEsintassi corretta per MySQL:

INSERT INTO AggregatedData (datenum,Timestamp)
VALUES ("734152.979166667","2010-01-14 23:30:00.000")
ON DUPLICATE KEY UPDATE 
  Timestamp=VALUES(Timestamp)

18
Fare attenzione quando si utilizza INSERT ... ON DUPLICATE KEY UPDATE su tabelle rispetto a una tabella con più di una chiave univoca o primaria. Tratto dalla documentazione di MySQL : Inoltre, a partire da MySQL 5.5.24, un'istruzione INSERT ... ON DUPLICATE KEY UPDATE su una tabella con più di una chiave univoca o primaria viene anch'essa contrassegnata come non sicura. (Bug # 11765650, Bug # 58637) Bug 58637 descrizione bugs.mysql.com/bug.php?id=58637
banda larga

1
Potrebbe essere necessario creare UNIQUEvincoli per l' Timestamputilizzo diALTER TABLE AggregatedData ADD UNIQUE (Timestamp)
Avyakt

@broadband puoi usare una chiave composita per evitare questo bug
Kareem

16

Prova a usare questo :

Se si specifica ON DUPLICATE KEY UPDATEe viene inserita una riga, ciò causerebbe un valore duplicato in un UNIQUE index orPRIMARY KEY , MySQL performs an [UPDATE`] ( http://dev.mysql.com/doc/refman/5.7/en/update.html ) della vecchia riga. ..

La ON DUPLICATE KEY UPDATEclausola può contenere più assegnazioni di colonna, separate da virgole.

Con ON DUPLICATE KEY UPDATE, il valore delle righe interessate per riga è 1 se la riga viene inserita come nuova riga, 2 se viene aggiornata una riga esistente e 0 se una riga esistente è impostata sui valori correnti. Se specifichi il CLIENT_FOUND_ROWSflag su mysql_real_connect()quando ti connetti a mysqld , il valore delle righe interessate è 1 (non 0) se una riga esistente è impostata sui suoi valori correnti ...


Ma il mio dato non è la chiave primaria.
OHLÁLÁ

Quindi nel mio caso qual è la soluzione, ho provato questa, senza alcuna soluzione: INSERT INTO forwind.aggregateddata (datenum, Timestamp, Min_F1_baro_20_) VALUES ('1', '2', '3') ON DUPLICATE KEY UPDATE datenum = datenum;
OHLÁLÁ

1
il dato dovrebbe essere unico? se sì, allora aggiungi un indice univoco (se non è già stato aggiunto) Allora funzionerà. Fare riferimento a dev.mysql.com/doc/refman/5.1/en/alter-table.html per informazioni su come aggiungere indici UNIQUE
Jai

ora ho definito il dato come unico, e funziona bene, grazie
OHLÁLÁ

1
Solo un link, magari dai una risposta.
Andrew

0

Ho avuto una situazione in cui avevo bisogno di aggiornare o inserire su una tabella in base a due campi (entrambe chiavi esterne) su cui non potevo impostare un vincolo UNICO (quindi INSERT ... ON DUPLICATE KEY UPDATE non funzionerà). Ecco cosa ho finito per usare:

replace into last_recogs (id, hasher_id, hash_id, last_recog) 
  select l.* from 
    (select id, hasher_id, hash_id, [new_value] from last_recogs 
     where hasher_id in (select id from hashers where name=[hasher_name])
     and hash_id in (select id from hashes where name=[hash_name]) 
     union 
     select 0, m.id, h.id, [new_value] 
     from hashers m cross join hashes h 
     where m.name=[hasher_name] 
     and h.name=[hash_name]) l 
  limit 1;

Questo esempio è cribbato da uno dei miei database, con i parametri di input (due nomi e un numero) sostituiti con [hasher_name], [hash_name] e [new_value]. L'annidato SELECT ... LIMIT 1 estrae il primo del record esistente o un nuovo record (last_recogs.id è una chiave primaria autoincrement) e lo utilizza come valore di input in REPLACE INTO.


REPLACE inserisce sempre una nuova riga! cancella solo l'originale, già esistente!
jasie
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.