Come eseguire un UPSERT in modo da poter utilizzare sia nuovi che vecchi valori nella parte di aggiornamento

Stupido ma semplice esempio: supponiamo di avere una tabella “Item” in cui conservo i totali degli articoli che ricevono.

Item_Name Items_In_Stock 

Il nome dell’articolo è la chiave principale qui. Come raggiungere il seguente quando mai ricevo l’articolo A in quantità X.

Se l’articolo non esiste, inserisco un nuovo object registrato per l’articolo A e imposta gli articoli in magazzino su X e se esiste un record in cui gli articoli in magazzino erano Y, il nuovo valore negli articoli in magazzino è (X + Y)

 INSERT INTO `item` (`item_name`, items_in_stock) VALUES( 'A', 27) ON DUPLICATE KEY UPDATE `new_items_count` = 27 + (SELECT items_in_stock where item_name = 'A' ) 

Il mio problema è che ho più colonne nella mia tabella attuale. È una buona idea scrivere più istruzioni select nella parte di aggiornamento?

Certo che posso farlo in codice, ma c’è un modo migliore?

Come menzionato nel mio commento, non devi fare in modo che la sottoselezione faccia riferimento alla riga che sta causando l’triggerszione di ON DUPLICATE KEY. Quindi, nel tuo esempio puoi usare quanto segue:

 INSERT INTO `item` (`item_name`, items_in_stock) VALUES( 'A', 27) ON DUPLICATE KEY UPDATE `new_items_count` = `new_items_count` + 27 

Ricorda che la maggior parte delle cose è molto semplice, se ti sorprendi a complicare qualcosa che dovrebbe essere semplice, probabilmente lo farai nel modo sbagliato 🙂

Puoi avere un’idea da questo esempio:

Supponiamo di voler aggiungere dati di sette giorni utili agli utenti

Dovrebbe avere un valore unico per userid e giorno come

 UNIQUE KEY `seven_day` (`userid`,`day`) 

Ecco il tavolo

 CREATE TABLE `table_name` ( `userid` char(4) NOT NULL, `day` char(3) NOT NULL, `open` char(5) NOT NULL, `close` char(5) NOT NULL, UNIQUE KEY `seven_day` (`userid`,`day`) ); 

E la tua domanda sarà

 INSERT INTO table_name (userid,day,open,close) VALUES ('val1', 'val2','val3','val4') ON DUPLICATE KEY UPDATE open='val3', close='val4'; 

Esempio:

 array("userid"=>"1001", "open"=>"01.01", "close"=>"11.01"), 'sun'=>array("userid"=>"1001", "open"=>"02.01", "close"=>"22.01"), 'sat'=>array("userid"=>"1001", "open"=>"03.01", "close"=>"33.01"), 'mon'=>array("userid"=>"1002", "open"=>"08.01", "close"=>"08.01"), 'mon'=>array("userid"=>"1002", "open"=>"07.01", "close"=>"07.01") ); //If you query this in a loop //$conn = mysql_connect("localhost","root",""); //mysql_select_db("test", $conn); foreach($data as $day=>$info) { $sql = "INSERT INTO table_name (userid,day,open,close) VALUES ('$info[userid]', '$day','$info[open]','$info[close]') ON DUPLICATE KEY UPDATE open='$info[open]', close='$info[close]'"; mysql_query($sql); } ?> 

I tuoi dati saranno nella tabella:

 +--------+-----+-------+-------+ | userid | day | open | close | +--------+-----+-------+-------+ | 1001 | sat | 03.01 | 33.01 | | 1001 | sun | 02.01 | 22.01 | | 1002 | mon | 07.01 | 07.01 | +--------+-----+-------+-------+ 

Anche se la risposta di Michael è quella giusta, è necessario conoscere un po ‘di più per eseguire l’upsert a livello di codice:

Innanzitutto, crea la tua tabella e specifica su quali colonne desideri un indice univoco:

 CREATE TABLE IF NOT EXISTS Cell ( cellId BIGINT UNSIGNED, attributeId BIGINT UNSIGNED, entityRowId BIGINT UNSIGNED, value DECIMAL(25,5), UNIQUE KEY `id_ce` (`cellId`,`entityRowId`) ) 

Quindi inserisci alcuni valori in esso:

 INSERT INTO Cell VALUES( 1, 6, 199, 1.0 ); 

Prova a ripetere la stessa operazione e otterrai un errore chiave duplicato, poiché cellId e entityRowId sono gli stessi:

 INSERT INTO Cell VALUES( 1, 6, 199, 1.0 ); 

Voce duplicata ‘1-199’ per la chiave ‘id_ce’

Ecco perché usiamo il comando upsert:

 INSERT INTO Cell ( cellId, attributeId, entityRowId, value, s, l, p, t ) VALUES( 1, 6, 199, 300.0 ) ON DUPLICATE KEY UPDATE `value` = `value` + VALUES(`value`) 

Questo comando prende il valore 1.0 che è già lì come valore e fa un value = value + 300.0 .

Quindi, anche dopo aver eseguito il comando precedente, ci sarà solo una riga nella tabella e il valore sarà 302.0 .

Questa è la syntax per un upsert

 INSERT INTO `{TABLE}` (`{PKCOLUMN}`, `{COLUMN}`) VALUES (:value) ON DUPLICATE KEY UPDATE `{COLUMN}` = :value_dup';