2010-04-14 4 views
23

Ich habe ein paar Antworten dafür mit mySQL allein gefunden, aber ich hatte gehofft, jemand könnte mir einen Weg zeigen, um die ID der zuletzt eingefügten oder aktualisierten Zeile zu bekommen eine mysql-DB, wenn PHP verwendet wird, um die Einfügungen/Aktualisierungen zu handhaben.mysql_insert_id() während der Verwendung von ON DUPLICATE KEY UPDATE mit PHP

Zur Zeit habe ich so etwas wie diese, wo column3 ein eindeutiger Schlüssel ist, und es gibt auch eine ID-Spalte, die ein autoinkrementierten Primärschlüssel ist:

$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 $ korrekt auf INSERT, aber falsch, wenn es eine Aktualisierung Zeile (ON DUPLICATE KEY UPDATE).

Ich habe mehrere Beiträge gesehen mit Menschen beraten, dass Sie so etwas wie

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

verwenden Sie einen gültigen ID-Wert zu erhalten, wenn der ON DUPLICATE KEY invoked-- ist, aber diese Rückkehr, dass gültige ID an den PHP mysql_insert_id() Funktion?

+0

Ich habe keine Antwort. Aber die Lösung sieht clever aus. Warum versuchst du es nicht? Ich denke, es sollte nicht schwer sein, einen Testfall zu erstellen, der eine definitive Antwort geben würde. PS .: Versteh mich aber nicht falsch; Ich kann verstehen, dass Sie sich beruhigen wollen. Ich würde wahrscheinlich auch. Aber ich würde es zuerst versuchen, denke ich. :) –

+2

Ich war neugierig, wie das funktionieren könnte, aber ich fand dies im MySQL-Handbuch: * Wenn Ausdruck LAST_INSERT_ID() als Argument angegeben wird, wird der Wert des Arguments von der Funktion zurückgegeben und als der nächste Wert an erinnert von LAST_INSERT_ID() * zurückgegeben werden. –

+0

@Alexandre: Ja, und vorausgesetzt, mysql_insert_id() 'ist nur ein Proxy für' LAST \ _INSERT \ _ID() 'Ich würde denken, dies sollte wie erwartet funktionieren. –

Antwort

34

einfiel Hier ist die Antwort, wie von Alexandre vorgeschlagen:

, wenn Sie die id = LAST_INSERT_ID (id) setzt den Wert von mysql_insert_id = die aktualisierte ID-- so sollte Ihre endgültige Code wie folgt aussehen:

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

Dies ist der richtige Wert für $ zurück my_id unabhängig von Update o r einfügen.

+0

zurück, wenn die ID, die aktualisiert wird, in einer anderen Tabelle referenziert wird? Würde dies Ärger verursachen? – ianace

+5

Das hat mir geholfen, aber nur um klar zu sein, für jeden anderen, der das Problem hat ... Wenn der Datensatz bereits existiert und aktualisiert wird, stellt der Aufruf von LAST_INSERT_ID() sicher, dass beim späteren Aufruf von mysql_insert_id() der ID des Datensatzes aktualisiert, und nicht wie sonst üblich Null. Beachten Sie auch, dass "id" durch den Spaltennamen auto_increment in der Tabelle ersetzt werden sollte. Weitere Informationen: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

Sie könnten überprüfen, ob die Abfrage eine Einfügung oder ein Update war (mysql_affected_rows(); gibt 1 beim Einfügen und 2 beim Aktualisieren zurück).

Wenn es eine Einfügung war, verwenden Sie mysql_insert_id, wenn es eine Aktualisierung wäre, würden Sie eine andere Abfrage benötigen.

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

Ich weiß, es ist nicht excatly, was Sie suchen, aber es ist das Beste, was ich mit

+1

+1 für die betroffenen_Routen() gibt 1 zum Einfügen und 2 zum Aktualisieren zurück. –

+3

wenn nichts aktualisiert wird (Werte wie in db), noch eingefügt; betroffene Zeilen gibt 0 –

1

Obwohl nicht mysql_insert_id mit() und ON DUPLICATE KEY UPDATE, alternative gute Möglichkeit, den Wert eines Feldes zu erhalten, wenn ein anderer here gefunden Aktualisierung:

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

Ich benutzte es, Tisch mit mit (id, Status) 'ID' Primärindex Auto-Inkrement, und 'Status' war das Feld, auf dem Update gemacht wurde, aber ich musste 'ID' der aktualisierten Zeile erhalten. Diese Lösung kann auch als mysql_insert_id() verwendet werden.

0

Dies ist meine Lösung, wo Sie die Daten in einem einzigen Array und es automatisch in die Abfrage "INSERT INTO .. ​​ON DUPLICATE UPDATE .." eingefügt werden.

Es ist großartig für Wartbarkeit, und wenn Sie möchten, können Sie es auch eine Funktion/Methode machen.

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