mysqli::$insert_id

mysqli_insert_id

(PHP 5, PHP 7, PHP 8)

mysqli::$insert_id -- mysqli_insert_id返回最后一次查询为 AUTO_INCREMENT 列生成的的值

描述

面向对象风格

过程式风格

mysqli_insert_id(mysqli $mysql): int|string

返回在具有 AUTO_INCREMENT 属性的列的表上,由 INSERTUPDATE 查询生成的 ID。在多行 INSERT 语句的情况下,它返回成功插入的第一个自动生成的的值。

使用 LAST_INSERT_ID() MySQL 函数执行 INSERTUPDATE 语句也会修改 mysqli_insert_id() 返回的值。如果 LAST_INSERT_ID(expr) 用于生成 AUTO_INCREMENT 的值,则它返回最后一个 expr 的值,而不是生成的 AUTO_INCREMENT 值。

如果之前的语句没有更改 AUTO_INCREMENT 值,则返回 0mysqli_insert_id() 必须在生成值的语句之后立即调用。

参数

mysql

仅过程式风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象

返回值

由前一个查询更新的 AUTO_INCREMENT 字段的值。如果在连接上没有前一个查询,或者查询没有更新 AUTO_INCREMENT 值,则返回零。

只有使用当前连接发出的语句会影响返回值。该值不受使用其他连接或客户端发出的语句影响。

注意:

如果数字大于最大 int 值,则它将作为字符串返回。

示例

示例 #1 $mysqli->insert_id 示例

面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

$mysqli->query("CREATE TABLE myCity LIKE City");

$query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)";
$mysqli->query($query);

printf("New record has ID %d.\n", $mysqli->insert_id);

/* drop table */
$mysqli->query("DROP TABLE myCity");

过程式风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

mysqli_query($link, "CREATE TABLE myCity LIKE City");

$query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)";
mysqli_query($link, $query);

printf("New record has ID %d.\n", mysqli_insert_id($link));

/* drop table */
mysqli_query($link, "DROP TABLE myCity");

上面的示例将输出

New record has ID 1.
添加备注

用户贡献的备注 10 条备注

43
will at phpfever dot com
18 年前
我收到了很多关于 insert_id 属性存在错误的陈述,因为它“有时有效”。请记住,在使用 OOP 方法时,mysqli 类的实际实例化将保存 insert_id。

以下代码将不返回任何内容。
<?php
$mysqli
= new mysqli('host','user','pass','db');
if (
$result = $mysqli->query("INSERT INTO t (field) VALUES ('value');")) {
echo
'The ID is: '.$result->insert_id;
}
?>

这是因为 insert_id 属性不属于结果,而是属于实际的 mysqli 类。这将有效

<?php
$mysqli
= new mysqli('host','user','pass','db');
if (
$result = $mysqli->query("INSERT INTO t (field) VALUES ('value');")) {
echo
'The ID is: '.$mysqli->insert_id;
}
?>
16
mmulej at gmail dot com
3 年前
还没有关于预处理语句的示例。

```php
$u_name = "John Doe";
$u_email = "[email protected]";

$stmt = $connection->prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
);
$stmt->bind_param('ss', $u_name, $u_email);
$stmt->execute();

echo $stmt->insert_id;
```

对于 UPDATE,您只需相应地更改查询字符串和绑定参数,其余保持不变。

当然,表需要具有 AUTOINCREMENT 主键。
2
adrian dot nesse dot wiik at gmail dot com
1 年前
如果您尝试使用 ON DUPLICATE KEY UPDATE 插入一行,请注意,如果触发了 ON DUPLICATE KEY UPDATE 子句,insert_id 将不会更新。

仔细想想,这实际上非常合乎逻辑,因为 ON DUPLICATE KEY UPDATE 是一个 UPDATE 语句,而不是 INSERT。

在最糟糕的情况下,如果您正在迭代某些内容并执行 INSERT,同时在后面的代码中依赖 insert_id,您可能会在触发 ON DUPLICATE KEY UPDATE 的迭代中指向错误的行!
4
www dot wesley at gmail dot com
5 年前
当使用“INSERT ... ON DUPLICATE KEY UPDATE `id` = LAST_INSERT_ID(`id`)”时,AUTO_INCREMENT 将在 InnoDB 表中增加,但在 MyISAM 表中不会增加。
5
bert at nospam thinc dot nl
16 年前
注意 oo 风格使用 $db->insert_id。当 insert_id 超过 2^31 (2147483648) 时,获取 insert id 会返回一个错误的、过大的数字。你最好使用过程式的 mysqli_insert_id( $db ) 替代。

[由 danbrown AT php DOT net 编辑:这是另一个 32 位有符号整数限制的典型例子。]
3
Nick Baicoianu
17 年前
在对带有 AUTO_INCREMENT 字段的表进行扩展插入时,mysqli_insert_id() 的值将等于插入的 *第一* 行的值,而不是像你预期的那样是最后一行。

<?
//mytable 有一个 auto_increment 字段
$db->query("INSERT INTO mytable (field1,field2,field3) VALUES ('val1','val2','val3'),
('val1','val2','val3'),
('val1','val2','val3')");

echo $db->insert_id; //将回显插入的 *第一* 行的 ID
?>
0
jpage at chatterbox dot fyi
1 年前
不清楚的是并发控制如何影响此函数。当你对 mysql 进行两次连续调用,第二次调用的结果依赖于第一次调用时,另一个用户可能在此期间插入了一些数据。

文档对此保持沉默,因此我总是会在插入前后确定自动递增的值以防这种情况发生。
0
alan at commondream dot net
19 年前
我在获取插入 ID 时遇到问题,并进行了一些测试。结果发现,如果你在获取最后插入的 ID 之前提交事务,它每次都会返回 0,但如果你在提交事务之前获取最后插入的 ID,则会获取正确的值。
-6
owenzx at gmail dot com
10 年前
这个例子缺少 multi_query 中的 insert_id。这是我的例子
假设你在 mysql 中有一个新的 test_db,如下所示

create database if not exists test_db;
use test_db;
create table user_info (_id serial, name varchar(100) not null);
create table house_info (_id serial, address varchar(100) not null);

然后你运行一个像这样的 php 文件

<?php
define
('SERVER', '127.0.01');
define('MYSQL_USER', 'your_user_name');
define('MYSQL_PASSWORD', 'your_password');

$db = new mysqli(SERVER, MYSQL_USER, MYSQL_PASSWORD, "test_db", 3306);
if (
$db->connect_errno)
echo
"create db failed, error is ", $db->connect_error;
else {
$sql = "insert into user_info "
. "(name) values "
. "('owen'), ('john'), ('lily')";
if (!
$result = $db->query($sql))
echo
"insert failed, error: ", $db->error;
else
echo
"last insert id in query is ", $db->insert_id, "\n";
$sql = "insert into user_info"
. "(name) values "
. "('jim');";
$sql .= "insert into house_info "
. "(address) values "
. "('shenyang')";
if (!
$db->multi_query($sql))
echo
"insert failed in multi_query, error: ", $db->error;
else {
echo
"last insert id in first multi_query is ", $db->insert_id, "\n";
if (
$db->more_results() && $db->next_result())
echo
"last insert id in second multi_query is ", $db->insert_id, "\n";
else
echo
"insert failed in multi_query, second query error is ", $db->error;
}
$db->close();
}
?>

你将获得类似这样的输出

last insert id in query is 1
last insert id in first multi_query is 4
last insert id in second multi_query is 1

结论
1 insert_id 在 multi_query 中有效
2 如果你进行多值插入,insert_id 是 mysql 使用的第一个 ID
-10
drburnett at mail dot com
7 年前
msqli_insert_id();
这似乎会返回最后插入的 ID。
但是,如果你有多个用户运行相同的代码,根据服务器或处理器,我曾看到它返回错误的 ID。

测试用例
两个用户向他们的列表添加了一项。
我有过几次 ID 是来自另一个用户的 ID 的情况。
这种情况非常罕见,只发生在我的测试服务器上,而没有发生在我的主服务器上。

我猜测这是因为多核(可能是超线程)或操作系统处理多线程的方式。

这种情况很少见,但确实会发生。
To Top