Подтвердить что ты не робот

Получение mysql_insert_id() при использовании ON DUPLICATE KEY UPDATE с PHP

Я нашел несколько ответов для этого, используя только mySQL, но я надеялся, что кто-то сможет показать мне способ получить идентификатор последней вставленной или обновленной строки базы данных mysql при использовании PHP для обработки вставок/обновлений.

В настоящее время у меня есть что-то вроде этого, где column3 является уникальным ключом, а также столбец идентификатора, который содержит автоматический первичный ключ:

$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, но неверен, когда он обновляет строку (ON DUPLICATE KEY UPDATE).

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

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

чтобы получить действительное значение ID при вызове ключа ON DUPLICATE KEY - но вернет ли этот действительный идентификатор функции PHP mysql_insert_id()?

4b9b3361

Ответ 1

Здесь ответ, предложенный Александром:

когда вы используете id = LAST_INSERT_ID (id), он устанавливает значение mysql_insert_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 независимо от обновления или вставки.

Ответ 2

Вы можете проверить, был ли запрос вставкой или обновлением (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 ... 
}
?>

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

Ответ 3

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

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

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

Ответ 4

Это мое решение, в котором вы помещаете данные в один массив и автоматически дублируется/заполняется в запросе "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))))  ;