2010-04-14 3 views
23

Я нашел несколько ответов для этого, используя только mySQL, но я надеялся, что кто-то сможет показать мне способ получить идентификатор последней вставленной или обновленной строки mysql DB при использовании PHP для обработки вставок/обновлений.Получение mysql_insert_id() при использовании ON DUPLICATE KEY UPDATE с PHP

В настоящее время у меня есть что-то вроде этого, где колонка3 является уникальным ключом, и есть также колонка идентификатор, который приведен 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 правильно на INSERT, но неправильно, когда это обновление row (ON DUPLICATE KEY UPDATE).

Я видел несколько постов с людьми, советуя использовать что-то вроде

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

, чтобы получить действительное значение идентификатора, когда дублированием KEY является invoked--, но это будет возвращение, что действительное удостоверение личности с PHP mysql_insert_id() функционировать?

+0

У меня нет ответа. Но решение выглядит умным. Почему бы вам не попробовать? Я бы подумал, что не должно быть сложно создать тестовый пример, который дал бы окончательный ответ. PS: Не поймите меня неправильно; Я могу понять, что вы хотите успокоить. Возможно, я тоже. Но сначала я попробую. :) –

+2

Мне было любопытно, как это может работать, но я нашел это в руководстве по MySQL: * Если expr задано как аргумент LAST_INSERT_ID(), значение аргумента возвращается функцией и запоминается как следующее значение для должен быть возвращен LAST_INSERT_ID() *. –

+0

@Alexandre: да, и предположим, что 'mysql_insert_id()' является просто прокси-сервером 'LAST \ _INSERT \ _ID()' Я бы подумал, что это должно работать должным образом. –

ответ

34

Вот ответ, как это было предложено Alexandre:

при использовании Ид = LAST_INSERT_ID (идентификатор) задает значение mysql_insert_id = обновленный ID-- поэтому окончательный код должен выглядеть следующим образом:

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

Это будет возвращать правильное значение $ my_id независимо от обновления O r вставка.

+0

Что делать, если обновляемый идентификатор ссылается в другой таблице? это вызовет проблемы? – ianace

+5

Это помогло мне, но для того, чтобы быть понятным, для всех, у кого возникла проблема ... Если запись уже существует и обновляется, вызов LAST_INSERT_ID() гарантирует, что, когда вы позже вызовете mysql_insert_id(), он вернет id обновленной записи, а не ноль, как обычно. Также обратите внимание, что «id» следует заменить на имя столбца auto_increment в таблице. Дополнительная информация: http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html –

10

Вы можете проверить, была ли Query вставка или обновление (mysql_affected_rows(); возвращает 1 на вставке и 2 на обновление).

Если это была вставка, используйте mysql_insert_id, если это было обновление, вам понадобится другой запрос.

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

Я знаю, что это не все тоже, что ищете, но это лучшее, что я мог придумать

+1

+1 для affected_rows() возвращает 1 для вставки и 2 для обновления. –

+3

, если ничего не обновлено (значения такие же, как в db), и не вставлены; затронутые строки возвращают 0 –

1

Хотя не используется mysql_insert_id() и дублированием KEY UPDATE, альтернативный отличный способ, чтобы получить значение любого поля при обновлении другой нашел here:

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

Я использовал это имея таблицу с (идентификатор, статус) 'id' первичный индекс auto-increment, а 'status' - поле, на котором было произведено обновление, но мне нужно было получить 'id' обновленной строки. Это решение также подтверждает условия гонки как mysql_insert_id().

0

Это мое решение, в котором вы помещаете данные в один массив, и он автоматически дублируется/заполняется в запросе «INSERT INTO .. ​​ON DUPLICATE UPDATE ..».

Это отлично подходит для ремонтопригодности, и если вы хотите, вы можете сделать его функцией/методом.

// 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)))) ; 
Смежные вопросы