2010-04-14 10 views
23

he encontrado algunas respuestas para esta usando MySQL solo, pero yo estaba esperando que alguien me puede mostrar una manera de obtener el ID de la última fila insertada o actualizada una base de datos MySQL cuando usa PHP para manejar las inserciones/actualizaciones.conseguir mysql_insert_id(), mientras que el comando ON DUPLICATE KEY UPDATE con PHP

Actualmente tengo algo como esto, donde las columnas 3 es una clave única, y también hay una columna de ID que es una clave 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 es correcto en INSERT, pero incorrecta cuando se actualiza una row (ON DUPLICATE KEY UPDATE).

he visto varios mensajes con la gente aconsejando que utilice algo como

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

para obtener un valor de identidad válido cuando el EN llave duplicada es invoked-- sino que este retorno que una identificación válida a la PHP mysql_insert_id() ¿función?

+0

No tengo la respuesta. Pero la solución parece inteligente. ¿Por qué no lo intentas? Pensaría que no debería ser difícil crear un caso de prueba que diera una respuesta definitiva. PD .: Aunque no me malinterpreten; Puedo entender que quieras tranquilizarme. Probablemente también. Pero lo probaría primero, supongo. :) –

+2

tenía curiosidad cómo podría funcionar, pero me encontré con esto en el manual de MySQL: * Si expr se da como argumento para LAST_INSERT_ID(), el valor del argumento es devuelto por la función y es recordado como el siguiente valor a ser devuelto por LAST_INSERT_ID() *. –

+0

@Alexandre: sí, y suponiendo que 'mysql_insert_id()' es solo un proxy para 'LAST \ _INSERT \ _ID()' Creo que esto debería funcionar como se esperaba. –

Respuesta

34

Aquí está la respuesta, según lo sugerido por Alexandre:

cuando se utiliza el id = LAST_INSERT_ID (id) que establece el valor de la mysql_insert_id = ID-- actualizado para que su código final debe ser similar:

<? 
    $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(); 

Esto devolverá el valor correcto para $ my_id independientemente de actualización de la O r insertar.

+0

¿qué sucede si el ID que se actualiza está siendo referenciado en otra tabla? ¿Esto causaría problemas? – ianace

+5

Esto me ayudó, pero para ser claro, para cualquier otra persona que tenga el problema ... Si el registro ya existe y se actualiza, la llamada a LAST_INSERT_ID() asegura que cuando llame a mysql_insert_id(), devolverá el Identificación del registro actualizado, y no cero como normalmente lo haría. También tenga en cuenta que "id" debe reemplazarse por el nombre de la columna auto_increment en la tabla. Más información: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

se puede comprobar si la consulta fue una inserción o una actualización (mysql_affected_rows(); devuelve 1 en el inserto y 2 en la actualización).

Si se trata de un uso mysql_insert_id inserción, si se tratara de una actualización que había necesidad de otra consulta.

<?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 ... 
} 
?> 

Yo sé que no es excatly lo que busca pero es lo mejor que podía llegar a

+1

+1 para affected_rows() devuelve 1 en la inserción y 2 para la actualización. –

+3

si no se actualiza nada (valores iguales que en db), ni insertado; las filas afectadas devuelven 0 –

1

Aunque no usar mysql_insert_id() y ON DUPLICATE KEY UPDATE, gran manera alternativa de obtener el valor de cualquier campo en la actualización de otro encontró here:

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

que lo usaron tener mesa con (id, estado) El autoincremento del índice principal 'id' y el 'estado' fueron los campos sobre los que se realizó la actualización, pero necesitaba obtener 'id' de la fila actualizada. Esta solución también prueba las condiciones de carrera como mysql_insert_id().

0

Esta es mi solución en la que coloca los datos en una única matriz y se duplica o completa automáticamente en la consulta "INSERT INTO .. ​​ON DUPLICATE UPDATE ..".

Es muy bueno para el mantenimiento, y si lo desea, puede hacer que sea una función/método también.

// 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)))) ; 
Cuestiones relacionadas