如何在mysql-php中检索所有最后插入的行ID?

6

有没有一种高效的方法使用PHP从MySQL数据库中检索所有最后插入的自增ID行?假设我不知道要批量插入多少行,但我需要在插入后获取它们的所有ID。

在Google搜索后,我没有找到任何有效的方法来完成这个任务,所以我不确定是否可能。我可以尝试这种方法,但必须多次访问数据库以检索ID。

$data = array (
array(1,2),
array(3,4),
array(5,6)
);

$ids = array();

foreach ($data as $item) {
   $sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
   mysql_query ($sql);
   $ids[] = mysql_insert_id();
}

谢谢您


1
这是什么问题?应该可以正常工作。 - slash197
3
在你的批次获取最大ID之前。在你的批次获取最大ID之后。现在你知道了范围。 - ITroubs
1
顺便提一下:mysql_* 函数正在被弃用,并将在未来的 PHP 版本中被移除。您不应该使用它们来编写新代码。请改用 mysqli_* 函数或 PDO 对象。 - Gerald Schneider
最多也就跟往数据库插入一行数据一样的费用,也就是说不太可能有什么显著的影响。 - AD7six
@OzkanOzlu:那是个打字错误。我已经编辑过了。 - leevi
显示剩余11条评论
5个回答

1
你的代码已经接近完美解决方案了。
$data = array (
array(1,2),
array(3,4),
array(5,6)
);

$ids = array();

foreach ($data as $item) {
   $sql = "INSERT INTO `table` (`a`, `b`) VALUES ('{$item[0]}' ,'{$item[1]}');";
   mysql_query ($sql) or mysql_error();
   $ids[] = mysql_insert_id();
}

var_dump($ids);

如果问题是关于性能问题的话,另一个解决方案可能是:
foreach ($data as $item) {
   $sql = "INSERT INTO `table`.`table` (`a`, `b`) VALUES ('{$item[0]}' ,'{$item[1]}');";
   mysql_query ($sql) or mysql_error();
}

$last_id = mysql_insert_id();
$total = count($data);
for($i = 0; $i <= $total; $i++){
    $ids[] = $total-$i;
}

这将防止多个SQL查询。

你正在指向$ids变量。但是即使按照leevi的代码打印$ids,它应该是所有的ids。 - Suresh Kamrushi
@silentboy:实际上你说得没错,但我只是好奇那样是否高效... - leevi
@silentboy:他初始化并使用不同的变量,但即使 $id 必须包含所有 ID,PHP 也不需要变量初始化。 - Suresh Kamrushi
@silentboy:那是个打错字,我已经修改了。 - leevi
@leevi 编辑了我的答案。在本地运行正常。请测试一下你的。 - user2193789
显示剩余2条评论

1
Mysql仅返回最后插入的id,不幸的是没有办法直接检索所有id。你需要使用解决方法,例如:
1. 计算插入的行数和最后插入的ID,然后向后计算剩余部分。 2. 生成自定义ID而不是让mysql按顺序创建它们,如果插入查询成功,则将ID存储到数组中(通常,如果其中一个失败,整个查询也会失败)。
第二种方法是推荐的,因为对于n1,如果您执行稍微复杂的操作,例如使用INSERT blah blah ON DUPLICATE KEY,则修改会被视为2个插入(不要问我为什么),而不是一个,您必须进行一些计算来查看实际插入了多少个和修改了多少个。
顺便说一下,停止使用mysql_扩展,它已被弃用,请改用mysqli或pdo。

感谢您的回复。实际上,我正在考虑一种关于自动增量的高效解决方案。顺便提一下:我已经知道了mysql_扩展和在我的实际代码中已经使用mysqli_。谢谢 :) - leevi
一个想法是在插入时添加日期时间或时间戳,获取最后插入的id的日期时间,并查询所有具有该日期时间的id。 - aleation

0
如果您的自增字段是“普通”的,那么它不会以某种特殊方式行为,而是将最后一个ID增加一,您可以在插入之前找到其最大值,然后找到所有高于该值的记录。
例如:
$sql = "SELECT id FROM table ORDER BY id DESC LIMIT 1";
    // get maximal value before insert

$sql = "SELECT id FROM table WHERE id > :last_id"; // get all new

但这个解决方案并不是很专业。


2
如果有其他请求向数据库插入数据,这种方法可能会不准确——这种情况很可能存在于同一个页面或请求被两个用户访问的时候。如果没有这种情况的话,您可以采用这种方法。但是,既然如此,为什么不直接执行第一个查询语句呢?range($firstMax, $lastMax)可以返回所有的id,即使范围很大也没问题。 - AD7six
1
我会在第一次插入后运行第一个查询。如果你在第一次插入之前这样做,如果有人删除了最后几行并且自增值不等于最大ID,你就会遇到巨大的问题! - ITroubs
@AD7six 是的,你说得对。我没有考虑从另一个来源插入行的可能性。 - Voitcus

0
当我需要跟踪输入的记录批次时,我会在表中添加一个额外的字段,通常标记为时间戳或其他名称。当记录被插入时,时间戳字段将使用time()函数提供的当前时间戳进行填充。然后,无论这些记录有多久,每个批次都可以被跟踪。此外,保存时间戳是获取它们被添加的确切时间的简单方法。

-1

获取最后插入的id

    <?php

$conn = mysql_connect('localhost', 'user', 'password');

mysql_select_db('test');

$data = array (
array(1,2),
array(3,4),
array(5,6)
);

$ids = array();

foreach ($data as $item) {

   $sql = 'insert into testtable (a,b) values ('.$item[0].','.$item[1].')';   
   mysql_query ($sql, $conn);
   $id[] = mysql_insert_id($conn);
}

1
这看起来像是问题中代码的副本,但其中有一个打字错误。 - AD7six
@AD7six:我使用了相同的代码,但修改了mysql_insert_id($conn)而不是mysql_insert_id。由于我是stackoverflow的新手,所以我想分享完整的示例会很好。如果您知道如何分享此类示例,请告诉我。 - Jayendra Kainthola
如果未指定链接标识符,则假定由mysql_connect()打开的最后一个链接是使用的。也就是说,在代码中添加$ conn并不会改变它的工作方式。将$ ids更改为$ id只意味着新变量具有所有ID,而不是OP期望的ID。 - AD7six
好的。但是只有在我将 $conn 添加到 mysql_insert_db 中时它才对我有效。感谢提供链接,我会仔细阅读。 - Jayendra Kainthola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接