2012-02-01 9 views
6

C'è un modo per recuperare l'ID di un record (chiave primaria) dopo un inserimento quando l'errore mysql restituisce una chiave duplicata?Ottieni l'ID del record quando mysql restituisce l'errore duplicato

E.G. Come vorrei andare a questo proposito:

$sql = "INSERT INTO table (`col1`, `col2`) VALUES ('$val1', '$val2')"; 
$result = mysql_query($sql); 
if($result){ 
    $id = mysql_insert_id(); 
} 
else { 
    if(stristr(mysql_error(), "duplicate"){ 
    $sql = "SELECT `id` FROM `table` WHERE `col1`='$val1' AND `col2`='$val2'"; 
    $result = mysql_query($sql); 
    $row = mysql_fetch_array($result); 
    $id = $row['id']; 
    } 
    else { 
    die(mysql_error()); 
    } 
} 

Qui ho dovuto fare due istruzioni SQL che non solo richiedono tempo e fatica, ma duplicano codice pure.

Non riesco a utilizzare ON DUPLICATE KEY UPDATE perché voglio aggiornare una tabella diversa utilizzando l'ultimo ID inserito o l'ID del record che non può essere duplicato.

Quindi, ho ragione in quello che sto facendo? O c'è un modo per ottenere l'id della riga?

Grazie

risposta

6

MySQL non vi dirà che registrano contiene il valore originale, dovrete scoprire da soli. Ecco alcuni suggerimenti:

  • Cercare la sottostringa duplicate nel testo del messaggio di errore non sembra molto robusto. È sufficiente verificare il valore di mysql_errno() rispetto al codice per la voce duplicata, ovvero 1062 (you can find all codes in the manual).
  • L'estensione mysql non fornisce un meccanismo per scoprire il nome della chiave violata, quindi dovrete usare l'approccio non robusta analisi del testo del messaggio di errore:

    if(preg_match("/Duplicate entry '.*' for key '(.*)'/Ui", mysql_error(), $matches)){ 
        $violated_key = $matches[1]; 
    }else{ 
        throw new Exception('Could not find violated key name'); 
    } 
    
  • In alternativa, basta eseguire una query precedente (non c'è alcuna ragione per evitarlo):

    SELECT id 
    FROM table 
    WHERE col1=... AND col2=... 
    FOR UPDATE 
    

    La clausola FOR UPDATE bloccherà righe corrispondenti evitare (InnoDB supponendo) condizioni di gara.

+0

Fantastico, grazie per le informazioni e i suggerimenti. –

+0

Felice di averlo aiutato. Lasciatemi aggiungere una nota: ovviamente, 'FOR UPDATE' non bloccherà nulla se non ci sono corrispondenze. È ancora possibile ottenere il record creato da un altro processo concorrente subito dopo il controllo. Basta tenerne conto. –

+0

Ok, grazie. Non sto usando InnoDB, e non ho mai avuto, quindi non sono sicuro di cosa tu stia parlando! : p Ma lo esaminerò. :) –

Problemi correlati