2010-04-14 5 views
23

J'ai trouvé quelques réponses pour cela en utilisant uniquement MySQL, mais j'espérais que quelqu'un pourrait me montrer un moyen d'obtenir l'ID de la dernière ligne insérée ou mise à jour de une base de données MySQL lors de l'utilisation de PHP pour gérer les insertions/mises à jour.get mysql_insert_id() lors de l'utilisation de ON DUPLICATE KEY UPDATE avec PHP

Actuellement, j'ai quelque chose comme ça, où colonne3 est une clé unique, et il y a aussi une colonne id qui est une clé primaire auto:

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

mon_id $ est correct sur INSERT, mais incorrect quand il mettre à jour un row (SUR LA MISE À JOUR DE LA CLÉ DUPLICATE).

J'ai vu plusieurs postes avec des personnes indiquant que vous utilisez quelque chose comme

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

pour obtenir une valeur d'identité valide lorsque le Duplicate KEY est invoked-- mais ce retour sera qu'une pièce d'identité valide au PHP mysql_insert_id() fonction?

+0

Je n'ai pas la réponse. Mais la solution semble intelligente. Pourquoi ne l'essayez-vous pas? Je pense qu'il ne devrait pas être trop difficile de créer un test qui donnerait une réponse définitive. PS: Ne vous méprenez pas si; Je peux comprendre que vous voulez être rassuré. Je le ferais probablement aussi. Mais je l'essaierais d'abord je suppose. :) –

+2

J'étais curieux de savoir comment cela pouvait fonctionner mais je l'ai trouvé dans le manuel de MySQL: * Si expr est donné en argument à LAST_INSERT_ID(), la valeur de l'argument est retournée par la fonction et est mémorisée comme valeur suivante être renvoyé par LAST_INSERT_ID() *. –

+0

@Alexandre: oui, et en supposant que mysql_insert_id() 'est juste un proxy pour' LAST \ _INSERT \ _ID() 'je pense que cela devrait fonctionner comme prévu. –

Répondre

34

Voici la réponse, comme suggéré par Alexandre:

lorsque vous utilisez l'id = LAST_INSERT_ID (id), il définit la valeur de mysql_insert_id = le ID-- mis à jour afin que votre code final devrait ressembler à:

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

Cela renverra la bonne valeur pour mon_id $ quel que soit mise à jour o r insérer.

+0

que se passe-t-il si l'ID en cours de mise à jour est référencé dans une autre table? cela causerait-il des ennuis? – ianace

+5

Cela m'a aidé, mais juste pour être clair, pour quelqu'un d'autre ayant le problème ... Si l'enregistrement existe déjà et est mis à jour, l'appel à LAST_INSERT_ID() assure que lorsque vous appellerez mysql_insert_id(), il retournera le id de l'enregistrement mis à jour, et non nul comme d'habitude. Notez également que "id" doit être remplacé par le nom de la colonne auto_increment dans la table. Plus d'infos: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

Vous pouvez vérifier si la requête était un insert ou une mise à jour (mysql_affected_rows(), retourne 1 à l'insertion et 2 à la mise à jour).

S'il s'agissait d'un insert, utilisez mysql_insert_id, s'il s'agissait d'une mise à jour, vous auriez besoin d'une autre requête.

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

Je sais que ce n'est pas excatly ce que vous cherchez, mais il est le meilleur que je pouvais venir avec

+1

+1 pour le_respected_rows() renvoie 1 lors de l'insertion et 2 pour la mise à jour. –

+3

si rien n'est mis à jour (valeurs identiques à db), ni inséré; les lignes affectées retourne 0 –

1

Bien que ne pas utiliser mysql_insert_id() et Duplicate KEY UPDATE, alternative excellente façon d'obtenir la valeur d'un champ lors de la mise à jour une autre trouvé here:

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

Je l'ai utilisé avec table (id, état) 'id' auto-increment de l'index primaire, et 'status' était le champ sur lequel la mise à jour a été faite, mais j'avais besoin de 'id' de la ligne mise à jour. Cette solution prouve également aux conditions de course que mysql_insert_id().

0

Ceci est ma solution où vous mettez les données dans un seul tableau et il est automatiquement dupliqué/rempli dans la requête "INSERT INTO .. ​​ON DUPLICATE UPDATE ..".

C'est génial pour la maintenabilité, et si vous voulez, vous pouvez en faire une fonction/méthode aussi.

// 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)))) ; 
Questions connexes