2010-04-14 19 views
23

Ho trovato alcune risposte per questo utilizzando mySQL da solo, ma speravo che qualcuno potesse mostrarmi un modo per ottenere l'ID dell'ultima riga inserita o aggiornata di un DB mysql quando si utilizza PHP per gestire gli inserti/gli aggiornamenti.ottenere mysql_insert_id() durante l'utilizzo ON DUPLICATE KEY UPDATE con PHP

Attualmente ho qualcosa come questo, in cui column3 è una chiave unica, e c'è anche una colonna id che è una chiave primaria autoincremented:

$query ="INSERT INTO TABLE (column1, column2, column3) VALUES (value1, value2, value3) ON DUPLICATE KEY UPDATE SET column1=value1, column2=value2, column3=value3"; 
mysql_query($query); 

$my_id = mysql_insert_id(); 

$ my_id è corretto su INSERT, ma non corretto quando è l'aggiornamento di un riga (ON DUPLICATE KEY UPDATE).

ho visto diversi posti con le persone consigliando di utilizzare qualcosa come

INSERT INTO table (a) VALUES (0) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id) 

per ottenere un valore di identità valido quando il ON DUPLICATE KEY è invoked-- ma sarà questo ritorno che di identità valido al PHP mysql_insert_id() funzione?

+0

Non ho la risposta. Ma la soluzione sembra intelligente. Perché non lo provi? Penserei che non dovrebbe essere difficile creare un test che darebbe una risposta definitiva. PS .: Non fraintendermi però; Posso capire che vorrai rassicurazione. Probabilmente lo farei anch'io. Ma proverei prima io indovino. :) –

+2

Ero curioso di sapere come potesse funzionare, ma ho trovato questo nel manuale di MySQL: * Se expr è dato come argomento a LAST_INSERT_ID(), il valore dell'argomento viene restituito dalla funzione e viene ricordato come il valore successivo a essere restituito da LAST_INSERT_ID() *. –

+0

@Alexandre: sì, e presumendo 'mysql_insert_id()' è solo un proxy di 'LAST \ _INSERT \ _ID()' Penso che questo dovrebbe funzionare come previsto. –

risposta

34

Ecco la risposta, come suggerito da Alexandre:

quando si utilizza l'id = LAST_INSERT_ID (id) imposta il valore della mysql_insert_id = aggiornato ID-- in modo che il codice finale dovrebbe essere simile:

<? 
    $query = mysql_query(" 
     INSERT INTO table (column1, column2, column3) 
     VALUES (value1, value2, value3) 
     ON DUPLICATE KEY UPDATE 
      column1 = value1, 
      column2 = value2, 
      column3 = value3, 
      id=LAST_INSERT_ID(id) 
    "); 
    $my_id = mysql_insert_id(); 

Ciò restituirà il giusto valore a $ my_id indipendentemente aggiornamento o r inserire.

+0

e se l'id che si sta aggiornando viene referenziato in un'altra tabella? questo causerebbe problemi? – ianace

+5

Questo mi ha aiutato, ma per essere chiari, per chiunque abbia il problema ... Se il record esiste già e viene aggiornato, la chiamata a LAST_INSERT_ID() garantisce che quando si chiama mysql_insert_id(), restituirà il id del record aggiornato, e non zero come di solito. Si noti inoltre che "id" deve essere sostituito dal nome della colonna auto_increment nella tabella. Maggiori informazioni: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

È possibile verificare se la Query fosse un inserimento o un aggiornamento (mysql_affected_rows(); restituisce 1 in insert e 2 in aggiornamento).

Se si trattava di un insert, utilizzare mysql_insert_id, se si trattava di un aggiornamento, sarebbe necessaria un'altra query.

<?php 
$query ="INSERT INTO TABLE (column1, column2, column3) VALUES (value1, value2, value3) ON DUPLICATE KEY UPDATE SET column1=value1, column2=value2, column3=value3"; 
mysql_query($query); 
if(mysql_affected_rows() == 1) { $id = mysql_insert_id(); } 
else { // select ... 
} 
?> 

io so che non è excatly quello che cercate, ma è il meglio che potessi venire con

+1

+1 per the affected_rows() restituisce 1 su insert e 2 per update. –

+3

se non viene aggiornato nulla (valori come in db), né inserito; le righe interessate restituiscono 0 –

1

Anche se non si usa mysql_insert_id() e ON DUPLICATE KEY UPDATE, ottimo modo alternativo per ottenere il valore di ogni campo quando si aggiorna un altro trovato here:

UPDATE table SET id=(@tempid:=id) , .... LIMIT 1; 
SELECT @tempid; 

ho usato esso abbia tavolo con (id, stato) 'auto' incremento indice primario 'id' e 'stato' era il campo su cui è stato effettuato l'aggiornamento, ma avevo bisogno di ottenere 'id' della riga aggiornata. Questa soluzione prova anche le condizioni di gara come mysql_insert_id().

0

Questa è la mia soluzione in cui si inseriscono i dati in un singolo array e viene automaticamente duplicato/popolato nella query "INSERT INTO .. ​​ON DUPLICATE UPDATE ..".

È ottimo per la manutenibilità e, se lo si desidera, è possibile renderlo anche una funzione/metodo.

// save to db: 

$qData = [ 
    "id" =>    mysql_real_escape_string($email_id),  
    "synd_id" =>   mysql_real_escape_string($synd_id), 
    "campaign_id" =>  mysql_real_escape_string($campaign_id), 
    "event_id" =>   mysql_real_escape_string($event_id), 
    "user_id" =>   mysql_real_escape_string($user_id), 
    "campaign_name" =>  mysql_real_escape_string($campaign_name), 
    "subject" =>   mysql_real_escape_string($subject), 
    "from_name"=>   mysql_real_escape_string($from_name), 
    "from_email"=>   mysql_real_escape_string($from), 
    "content"=>   mysql_real_escape_string($html), 
    "link_to_template" => mysql_real_escape_string($hash), 
    "ext_campaign_id" => mysql_real_escape_string($ext_campaign_id), 
    "ext_list_id"=>  mysql_real_escape_string($ext_list_id), 
]; 


$q = "INSERT INTO email_campaigns (". 
    // i.e create a string like `id`, `synd_id`, `campaign_id`.. with linebreaks for readability 
    implode(", \n", array_map(function($k){ return "`$k`"; }, array_keys($qData))) 
.") 
VALUES (". 
    // i.e '20', '532', '600' .. 
    implode(", \n", array_map(function($v){ return "'$v'"; }, array_values($qData))) 
.") ON DUPLICATE KEY UPDATE ". 
    // i.e `synd_id`='532', `campaign_id`='600' ... 
    // id & link_to_template table keys are excluded based on the array below 
    implode(", \n", array_filter(array_map(function($k, $v){ if(!in_array($k, ['id', 'link_to_template'])) return "`$k`='$v'" ; }, array_keys($qData), array_values($qData)))) ; 
Problemi correlati