php - mysql_insert_id 和 last_insert_id 错误行为

标签 php mysql mysql-insert-id last-insert-id

我有这张 table

 CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  ;

a_b 是唯一键。

我有这样的 php 代码

 $db = DBFactory::getInstance();
 $db->selectDB('test');
 $db->query("insert into t5 (a, b) values(1, 1) on duplicate key update a=1, b=1");
 var_dump(mysql_insert_id());

 $cur = $db->query("select last_insert_id()");
 var_dump(mysql_fetch_assoc($cur));

在我的电脑上运行这段代码两次,结果是 第一名

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

第二

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

你可以看到,mysql_insert_id() 两次都返回相同的值“1”,这对我来说很好,因为我想知道插入后的真实 id,而不是下一个 auto_increment 值。

但是当我在另一个环境中运行这段代码两次时: 第一名

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

第二

int(2)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

正如您所看到的差异,第二次的结果 mysql_insert_id() 返回与 last_insert_id() 相同的值。

这个结果很糟糕,但我不知道为什么。我的代码在这两种环境中都运行良好大约 3 个月,直到今天才发生这种情况。有人可以解释吗?我确实在30天前将第二个环境的PHP版本升级到5.3.8,其他没有变化。这是错误吗?

更新

我切换到第三个mysql服务器(5.1.38-log),第二个插入返回 整数(0) 阵列(1){ ["last_insert_id()"]=> 字符串(1)“0”

所以我意识到问题可能与 mysql 版本有关。

最后,我把表定义改成了这个

DROP TABLE IF EXISTS `t5`;
CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `t` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

同时编辑我的脚本

$db = DBFactory::getInstance();
$db->selectDB('test');
$db->query("insert into t5 (a, b, t) values(1, 1, ".time().") on duplicate key update a=1, b=1, t=".time());
//$db->query("insert ignore into t5 (a, b) values(1, 1)");
var_dump(mysql_insert_id());

$cur = $db->query("select last_insert_id()");
var_dump(mysql_fetch_assoc($cur));

不同的mysql服务器返回相同的mysql_insert_id但不同的last_insert_id()

5.0.24a-community-nt

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

5.0.51a-log

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

5.1.38-log

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "0"
}

是否有任何系统变量控制这种行为?如果有人知道那将不胜感激。如果没有解决方案,我唯一能做的就是像这样强制插入以更新具有不同值的某些字段...

最佳答案

我认为您尝试使用 last_insert_id() 的方式并非本意 - 在这种情况下您没有插入任何内容,因此您也不应相信返回值。来自 MySQL docs :

If a table contains an AUTO_INCREMENT column and INSERT ... UPDATE inserts a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. If the statement updates a row instead, LAST_INSERT_ID() is not meaningful.

但是,似乎有一个解决方法(同一个文档)——手动设置 last_insert_id:

However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

关于php - mysql_insert_id 和 last_insert_id 错误行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8442926/

相关文章:

php - 在 PHP 中正确打印 python 脚本输出

mysql - LPAD/RPAD : Align column

php - 你在mysql_insert_id() 的括号里放了什么?

php - 如何在 android 推送通知中显示来自链接的图像?

php - Paypal 访问 - SSL 证书 : unable to get local issuer certificate

MySQL - 获取具有 "user-contact"的用户数

php - 基于触发器和存储过程更新汇总表

php - 是否可以将 mysql_insert_id() 与 while 循环一起使用?

php - mysql_insert_id() 返回 0

php - 如何将 SOAP 响应转换为 XML 或 JSON 格式?