2009-04-18 12 views
14

Molto spesso, voglio eseguire una query su uno dei miei utenti dove voglio una fila memorizzato e associato a tale utente, in una relazione 1 a 1. Quindi diciamo (questo è solo un esempio arbitrario), che ho un tavolo che tiene traccia della macchina di un utente, insieme ad alcune informazioni sulla macchina. Ogni utente può avere 0 o 1 auto. Se l'utente non ha una macchina, non vi è alcuna voce nella tabella per quell'utente. tavoloMySQL modo "buono" per inserire una riga, se non trovato, o aggiornare, se si trova

auto (di nuovo, solo un esempio): id, user_id, car_make, car_model

Così, quando aggiorno questo tavolo, finisco sempre per fare qualcosa di simile (pseudo-codice):

result = SELECT * FROM cars WHERE user_id=5 
if (num_rows(result)>0){ 
    UPDATE cars SET car_make='toyota', car_model='prius' WHERE user_id=5 
}else{ 
    INSERT INTO cars (user_id, car_make, car_model) VALUES (5, 'toyota', 'prius') 
} 

Come posso fare questo in una dichiarazione elegante che funziona "atomico"? Cosa succede se, in un altro processo, la riga viene RIMOSSA tra le istruzioni SELECT e UPDATE? La mia istruzione UPDATE fallirà dove dovrebbe essere eseguita la dichiarazione INSERT. E mi sento come se avessi bisogno di fare due dichiarazioni simili (ma diverse) per realizzare la stessa cosa! Quello di cui ho bisogno è una dichiarazione che mi assicuri che i dati che voglio siano presenti nella tabella, specialmente quando voglio solo una riga che soddisfi il mio requisito. Per esempio, potrebbe essere qualcosa di simile (questo è totalmente inventata ovviamente):

MAKE SURE A ROW IN cars WHERE user_id=5 IS SET WITH car_make='toyota', car_model='prius' 

In questo modo, se user_id 5 esiste già, sarà aggiornato, in caso contrario, verrà inserito. Inoltre, se ho cambiato i requisiti, ad esempio per dire che ogni utente può avere zero o un'auto di un dato car_make, quindi ho potuto inoltre precisare che:

MAKE SURE A ROW IN cars WHERE user_id=5 AND car_make='toyota' IS SET WITH car_model='prius' 

Spero che la mia domanda ha un senso! Come posso migliorare questa operazione di inserimento, se non trovata o aggiornamento-se-trovata di base che viene visualizzata così spesso? Grazie per qualsiasi aiuto!

risposta

0

In Oracle hai Merge.

Nessuna idea su MySql, ma il termine potrebbe darti qualcos'altro da cercare.

2

Si chiama UPSERT (UP data o in SERT). Ci sono un certo numero di domande SO su di esso è possibile cercare. See Wikipedia

EDIT: MySQL 4.1+ supporta INSATE (INS ert o upd ATE), che dovrebbe ottenere la stessa cosa, fino a quando si dispone di una chiave primaria. MySQL Manual

1

Penso che sia più semplice cambiarlo. Prova a inserire, quindi aggiorna.

MySQL ha espressamente una clausola di 'ON DUPLICATE KEY'

INSERT INTO automobili (campi) VALORI (valori) SU DUPLICATO KEY UPDATE ...

Questo naturalmente richiede di avere una corretta configurazione unica chiavi .

0

un esempio di come ho utilizzato ON DUPLICATE KEY UPDATE: INSERISCI NEL REGISTRO (nome, valore) VALUES ('". $ Chiave."', '". $ Val."') ON DUPLICATE KEY UPDATE valore = '" $ val.. "'"

5

da my other Stack Overflow answer:

Se si vuole fare questo in una singola istruzione, mi consiglia di utilizzare la sintassi INSERT ... ON DUPLICATE KEY UPDATE, come segue:

INSERT INTO table (id, someothervalue) VALUES (1, 'hi mom') 
    ON DUPLICATE KEY UPDATE someothervalue = 'hi mom'; 

La dichiarazione iniziale INSERT sarà e eseguire xecute se non esiste alcun record esistente con il valore della chiave specificato (chiave primaria o unica). Se un record esiste già, viene eseguita la seguente istruzione UPDATE (someothervalue = 3).

Questo è supportato in tutte le versioni di MySQL. Per ulteriori informazioni, vedere MySQL Reference Manual page for INSERT ... ON DUPLICATE KEY UPDATE

Problemi correlati