使用自动递增字段本身没有错。主要的竞争性想法也没有错,即让数据库提供一个非重复标识符的简单序列,通常是整数。这有点像你开车走哪边路。
更大的问题是,当人们不了解他们在做什么数据库访问时。这就像开车却不知道交通规则一样。这些人最终会在没有意识到的情况下做出错误的决定,然后最终,就会出现问题。
数据库是复杂的系统,值得花时间去真正理解。了解不同方法解决问题的含义和局限性。然后,你就可以根据必须生效的方案来选择解决方案。
(PHP 4, PHP 5)
mysql_insert_id — 获取最后一次查询生成的 ID
此扩展在 PHP 5.5.0 中已弃用,并在 PHP 7.0.0 中被移除。应改用 MySQLi 或 PDO_MySQL 扩展。另请参阅 MySQL:选择 API 指南。此函数的替代方法包括
检索先前查询(通常为 INSERT)为 AUTO_INCREMENT 列生成的 ID。
link_identifier
MySQL 连接。如果未指定链接标识符,则假定为 mysql_connect() 打开的最后一个链接。如果未找到此类链接,它将尝试创建链接,就像 mysql_connect() 被调用且没有参数一样。如果未找到或建立连接,则会生成 E_WARNING
级别的错误。
如果成功,则返回先前查询为 AUTO_INCREMENT 列生成的 ID,如果先前查询未生成 AUTO_INCREMENT 值,则返回 0
,如果未建立 MySQL 连接,则返回 false
。
示例 #1 mysql_insert_id() 示例
<?php
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("INSERT INTO mytable (product) values ('kossu')");
printf("Last inserted record has id %d\n", mysql_insert_id());
?>
mysql_insert_id() 将将本机 MySQL C API 函数 mysql_insert_id()
的返回类型转换为 long
类型(在 PHP 中命名为 int)。如果您的 AUTO_INCREMENT 列的列类型为 BIGINT(64 位),则转换可能会导致不正确的值。相反,请在 SQL 查询中使用内部 MySQL SQL 函数 LAST_INSERT_ID()。有关 PHP 最大整数值的更多信息,请参阅 整数 文档。
注意:
因为 mysql_insert_id() 对最后执行的查询起作用,所以请确保在生成值的查询后立即调用 mysql_insert_id()。
注意:
MySQL SQL 函数
LAST_INSERT_ID()
的值始终包含最近生成的 AUTO_INCREMENT 值,并且不会在查询之间重置。
使用自动递增字段本身没有错。主要的竞争性想法也没有错,即让数据库提供一个非重复标识符的简单序列,通常是整数。这有点像你开车走哪边路。
更大的问题是,当人们不了解他们在做什么数据库访问时。这就像开车却不知道交通规则一样。这些人最终会在没有意识到的情况下做出错误的决定,然后最终,就会出现问题。
数据库是复杂的系统,值得花时间去真正理解。了解不同方法解决问题的含义和局限性。然后,你就可以根据必须生效的方案来选择解决方案。
忘记使用 MAX 来获取最后插入的 ID。像其他用户在你的 SELECT MAX(.. 和 INSERT 之间插入这样的竞争条件可能会导致你的 ID 不可使用。
获取 ID 的正确方法是使用 mysql_insert_id() 或 mysql SQL 函数 LAST_INSERT_ID()。
注意,如果使用 mysql_insert_id(),你应该提供 mysql_connect 返回的资源,而不是 mysql_query 返回的结果集。
我不明白大家为什么对这个这么激动。
我读到
"mysql_insert_id() 的值只受当前客户端连接中发出的语句影响。它不受其他客户端发出的语句影响。"
参见:https://dev.mysqlserver.cn/doc/refman/5.0/es/mysql-insert-id.html
我真的不明白这句话有什么不准确的地方。
"对于多行 INSERT 语句,mysql_insert_id() 返回第一个自动生成的 AUTO_INCREMENT 值;如果未生成此类值,则返回最后插入到 AUTO_INCREMENT 列的显式值。"
我可能漏掉了什么,但为什么你要插入多行,然后只对最后一行使用一些特殊行为?你可以逐个插入它们,然后分别处理每一行,使用最新的 ID。
我不明白有什么问题。
但是,我可以理解为什么仅仅使用 max(my_table.id_column) 会有并发访问问题。
我认为这对于所有使用 mysqli 并希望在 INSERT 命令后获取 ID 的人来说都很有用
<?php
function insert_join($catid, $disc_id) {
// 向数据库中插入一个新项
$conn = db_connect();
// 插入新项
$demande = "insert into categories_disc values ('', '".$catid."', '".$disc_id."')";
$resultat = $conn->query($demande);
if (!$resultat) {
return false;
} else {
return $conn->insert_id; // 该函数现在将返回 ID 而不是 true。
}
}
?>
然后,在另一边,让我们像这样调用此函数
<?php
$cat_id = insert_join($catid, $disc_id);
if($cat_id !== false) {
echo "<p>类别信息已添加到数据库,如下所示:<br>";
echo "<hr>类别 ID:".$cat_id."</p><hr>";
}
?>
如果你使用 INSERT 语句中的 ON DUPLICATE KEY UPDATE 子句插入数据行,mysql_insert_id() 函数返回的结果与你在 MySQL 中直接使用 LAST_INSERT_ID() 的结果不同。
请查看以下示例
<?
// 插入数据行,主键为 auto_increment
// 值是唯一键
$query = "INSERT INTO test (value) VALUES ('test')";
mysql_query( $query );
echo 'LAST_INSERT_ID: ',
mysql_query( "SELECT LAST_INSERT_ID()" ),
'<br>mysql_insert_id: ',
mysql_insert_id();
?>
这将打印
LAST_INSERT_ID: 1
mysql_insert_id: 1
在这种情况下,函数返回的值与 MySQL 语句相同。
但请查看对现有键的插入操作
<?
$query = "INSERT INTO test (value)
VALUES ('test')
ON DUPLICATE KEY UPDATE value = 'test2'";
mysql_query( $query );
echo 'LAST_INSERT_ID: ',
mysql_query( "SELECT LAST_INSERT_ID()" ),
'<br>mysql_insert_id: ',
mysql_insert_id();
?>
这将打印
LAST_INSERT_ID: 2
mysql_insert_id: 1
使用 ON DUPLICATE KEY UPDATE 子句,如果 INSERT 语句导致重复条目,则只会修改旧的数据行,但 LAST_INSERT_ID() 函数会返回主键的下一个 auto_increment 值,它实际上并没有在数据库中设置为下一个 auto_increment 值。
mysql_insert_id() 函数返回旧(且已更改)数据行的主键。对我来说,这是正确的操作方法,因为 LAST_INSERT_ID() 函数返回的值根本没有与数据行关联。
来自慕尼黑的祝福。
heiligkind
如何在 MySQL 中获取最后更新行的 ID?
75
反对
我找到了这个问题的答案 :)
by Pomyk
SET @update_id := 0;
UPDATE some_table SET row = 'value', id = (SELECT @update_id := id)
WHERE some_other_row = 'blah' LIMIT 1;
SELECT @update_id;
EDIT by aefxx
此技术可以进一步扩展,以检索受更新语句影响的每行的 ID
SET @uids := null;
UPDATE footable
SET foo = 'bar'
WHERE fooid > 5
AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;
这将返回一个字符串,其中所有 ID 由冒号分隔。
(questions: 1388025 form stackoverflow)
你不能执行 INSERT DELAYED 并期望得到非零值,因为它在单独的线程中运行,而 mysql_insert_id() 与当前线程绑定。
Vlad
如果 mysql_insert_id() 返回 0 或 null,请检查你的自增字段是否由你的 SQL 查询设置,此外,如果你像我一样有多个数据库连接,解决方案是为该查询创建单独的数据库连接。
MySQLi 过程式
//---------------------------------------------
$last_id = mysqli_insert_id($conn);
//---------------------------------------------
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// 建立连接
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 检查连接
if (!$conn) {
die("连接失败:" . mysqli_connect_error());
}
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]')";
if (mysqli_query($conn, $sql)) {
$last_id = mysqli_insert_id($conn);
echo "新记录创建成功。最后一个插入的 ID 是:" . $last_id;
} else {
echo "错误:" . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
?>
如果你在执行 INSERT ... SELECT 一次插入多行后使用此函数,你将得到 INSERT 添加的 *第一* 行的自增 ID。
例如,如果表 'init' 中有 4 条记录,其 'type' 列值为 2
我想将这 4 条记录添加到表 'game' 中
表 game 具有自增列 'game_id',当前值为 32。
如果我执行此查询
INSERT INTO game (type, players, rounds)
SELECT type, players, rounds FROM init
WHERE type = 2
那么 mysql_insert_id() 将返回 33,而不是 36。