【问题标题】:getting mysql_insert_id() while using ON DUPLICATE KEY UPDATE with PHP在使用 ON DUPLICATE KEY UPDATE 和 PHP 时获取 mysql_insert_id()
【发布时间】:2010-04-14 00:34:39
【问题描述】:

我已经找到了一些单独使用 mySQL 的答案,但我希望有人可以告诉我一种方法来获取使用 PHP 处理插入/更新时最后插入或更新的 mysql DB 行的 ID .

目前我有这样的东西,其中 column3 是唯一键,还有一个 id 列是自动递增的主键:

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

在调用 ON DUPLICATE KEY 时获取有效的 ID 值——但这会将有效的 ID 返回给 PHP mysql_insert_id() 函数吗?

【问题讨论】:

  • 我没有答案。但这个解决方案看起来很聪明。你为什么不试试呢?我认为创建一个可以给出明确答案的测试用例应该不难。 PS.:不要误会我的意思;我能理解你想要安慰。我可能也会。但我想我会先尝试一下。 :)
  • 我很好奇它是如何工作的,但我在 MySQL 手册中找到了这一点:如果 expr 作为 LAST_INSERT_ID() 的参数给出,则该参数的值由函数返回并且被记住为 LAST_INSERT_ID() 所返回的下一个值
  • @Alexandre:是的,假设mysql_insert_id() 只是LAST\_INSERT\_ID() 的代理,我认为这应该按预期工作。
  • 谢谢大家,这是对我有用的方法。你是对的——当你使用 id=LAST_INSERT_ID(id) 时,它会设置 mysql_insert_id 的值 = 更新后的 ID。

标签: php mysql mysql-insert-id


【解决方案1】:

这是 Alexandre 建议的答案:

当您使用 id=LAST_INSERT_ID(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 返回正确的值。

【讨论】:

  • 如果正在更新的 id 在另一个表中被引用怎么办?这会造成麻烦吗?
  • 这对我有帮助,但要明确一点,对于其他有问题的人......如果记录已经存在并得到更新,对 LAST_INSERT_ID() 的调用可确保您稍后调用 mysql_insert_id( ),它将返回更新记录的 id,而不是像通常那样为零。另请注意,“id”应替换为表中的 auto_increment 列名。更多信息:dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html
  • 遗憾的是,从 MySQL 5.7 开始,这似乎不再起作用,它不会返回正确的值。它似乎给出了插入 id + 更新的结果 (0,1,2)
【解决方案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 ... 
}
?>

我知道这不是你要找的,但这是我能想到的最好的了

【讨论】:

  • +1 for the affected_rows() 在插入时返回 1,在更新时返回 2。
  • 如果没有更新(值与 db 中的值相同),也没有插入;受影响的行返回 0
【解决方案3】:

虽然不使用 mysql_insert_id() 和 ON DUPLICATE KEY UPDATE,但在更新另一个找到的 here 时获取任何字段值的另一种好方法:

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

我使用它的表具有(id,status)'id'主索引自动增量,'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))))  ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-15
      • 2018-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-16
      • 1970-01-01
      相关资源
      最近更新 更多