【问题标题】:Get ID of record when mysql returns duplicate errormysql返回重复错误时获取记录ID
【发布时间】:2012-02-01 10:54:28
【问题描述】:

当mysql错误返回重复键时,有没有办法在插入后检索记录的ID(主键)?

例如我会怎么做:

$sql = "INSERT INTO table (`col1`, `col2`) VALUES ('$val1', '$val2')";
$result = mysql_query($sql);
if($result){
  $id = mysql_insert_id();
}
else {
  if(stristr(mysql_error(), "duplicate"){
    $sql = "SELECT `id` FROM `table` WHERE `col1`='$val1' AND `col2`='$val2'";
    $result = mysql_query($sql);
    $row = mysql_fetch_array($result);
    $id = $row['id'];
  }
  else {
    die(mysql_error());
  }
}

这里我不得不做两个 sql 语句,这不仅需要时间和精力,而且还要重复代码。

我不能使用ON DUPLICATE KEY UPDATE,因为我想使用最后插入的 id 或不能复制的记录的 id 来更新不同的表。

那么,我做的事情对吗?或者有没有办法获取行的id?

谢谢

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    MySQL 不会告诉你哪条记录拥有原始值,你必须自己找出来。这里有一些提示:

    • 在错误消息的文本中寻找duplicate 子字符串看起来不是很可靠。您可以针对重复条目的代码测试 mysql_errno() 的值,即 1062 (you can find all codes in the manual)。

    • mysql 扩展不提供查找违规密钥名称的机制,因此您必须使用非鲁棒的方法来解析错误消息的文本:

        if( preg_match("/Duplicate entry '.*' for key '(.*)'/Ui", mysql_error(), $matches) ){
            $violated_key = $matches[1];
        }else{
            throw new Exception('Could not find violated key name');
        }
      
    • 或者,只需运行上一个查询(没有理由避免它):

        SELECT id
        FROM table
        WHERE col1=... AND col2=...
        FOR UPDATE
      

      FOR UPDATE 子句将锁定匹配的行以避免竞争条件(假设 InnoDB)。

    【讨论】:

    • 很高兴它有帮助。让我补充一点:显然,如果没有匹配项,FOR UPDATE 将不会锁定任何内容。您仍然可以在检查后获取其他并发进程创建的记录。请考虑到这一点。
    • 好的,谢谢。我没有使用 InnoDB,也从未使用过,所以我不确定你在说什么! :p 但我会调查一下。 :)
    猜你喜欢
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多