PHP/MySQL插入行并获取'id'

205

我的表的'id'字段在插入一行时会自动增加。我想先插入一行,然后再获取那个ID。

我可以按照我说的那样做,但有没有一种方法可以不用担心插入行和获取ID之间的时间?

我知道我可以查询数据库以查找与输入信息匹配的行,但很可能存在重复项,唯一的区别就是id。

10个回答

266
$link = mysqli_connect('127.0.0.1', 'my_user', 'my_pass', 'my_db');
mysqli_query($link, "INSERT INTO mytable (1, 2, 3, 'blah')");
$id = mysqli_insert_id($link);

请参见mysqli_insert_id()

无论你做什么,不要先插入再执行"SELECT MAX(id) FROM mytable"。就像你所说的那样,这是竞争条件,并且没有必要。 mysqli_insert_id() 已经具有此功能。


另一种方法是将两个查询一起运行,并使用MySQL的LAST_INSERT_ID() 方法,同时修改两个表(PHP不需要任何ID),如下:

mysqli_query($link, "INSERT INTO my_user_table ...;
  INSERT INTO my_other_table (`user_id`) VALUES (LAST_INSERT_ID())");

注意,每个连接都单独跟踪ID(因此已经避免了冲突)。


59
PDO的等效函数是PDO::lastInsertId(http://us3.php.net/manual/zh/pdo.lastinsertid.php)。 - Matthew Flaschen
11
如果同时进行10000个异步插入,它仍然能正常工作吗? - zie1ony
17
是的,对于一百万个异步插入操作,MySQL能够正常工作,因为它符合ACID标准。在许多异步插入操作中的每个单独插入都在其自己的隔离会话中完成,当您从PHP调用mysql_insert_id()(或在MySQL中使用LAST_INSERT_ID())时,ID就来源于此。 - rodrigo-silveira
9
文档中需要注意的是:mysql_insert_id()函数将本地MySQL C API函数mysql_insert_id()的返回类型转换为长整型(long),在PHP中称为int。如果您的AUTO_INCREMENT列的列类型为BIGINT(64位),则转换可能会导致返回值不正确。相反,可以在SQL查询中使用内部MySQL SQL函数LAST_INSERT_ID()。有关PHP最大整数值的更多信息,请参见整数文档。 - Elbek
7
需要重新改写我曾经写过的所有内容 -_- - de_nuit
显示剩余6条评论

40

MySQL函数LAST_INSERT_ID()正是您所需要的:它检索在此会话期间插入的ID。因此,即使有其他进程(例如其他人调用完全相同的脚本)向同一表中插入值,也可以安全使用。

PHP函数mysql_insert_id()执行与使用mysql_query()调用SELECT LAST_INSERT_ID()相同的操作。


2
echo mysql_insert_id(); mysql_query('SELECT LAST_INSERT_ID(600)'); echo mysql_insert_id(); mysql_query('SELECT LAST_INSERT_ID()');第二个mysql_insert_id()不反映600,而mysql_query('SELECT LAST_INSERT_ID()')将反映。要使mysql_insert_id()反映更改,您必须首先进行插入或更新(可能会影响0行)。请参阅:http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id的最后一段。 - Cliffordlife

31

关于PHP的网站,mysql_insert_id现已弃用,我们必须使用PDOMySQLi(有关MySQLi,请参见@Luke's answer)。要使用PDO,请按照以下步骤进行:

$db = new PDO('mysql:dbname=database;host=localhost', 'user', 'pass');
$statement = $db->prepare('INSERT INTO people(name, city) VALUES(:name, :city)');
$statement->execute([':name' => 'Bob', ':city' => 'Montreal']);

echo $db->lastInsertId();

4
我们可以选择使用PDO MySQLi(我在另一个答案中进行了描述)。这是一个很好的比较文章:http://code.tutsplus.com/tutorials/pdo-vs-mysqli-which-should-you-use--net-24059。 - Luke

23

正如@NaturalBornCamper所说,mysql_insert_id现在已经被弃用,不应该再使用。现在的选择是使用PDO或mysqli。NaturalBornCamper在他的回答中解释了PDO,所以我将展示如何使用MySQLiMySQL Improved)和mysqli_insert_id

// First, connect to your database with the usual info...
$db = new mysqli($hostname, $username, $password, $databaseName);
// Let's assume we have a table called 'people' which has a column
// called 'people_id' which is the PK and is auto-incremented...
$db->query("INSERT INTO people (people_name) VALUES ('Mr. X')");
// We've now entered in a new row, which has automatically been 
// given a new people_id. We can get it simply with:
$lastInsertedPeopleId = $db->insert_id;
// OR
$lastInsertedPeopleId = mysqli_insert_id($db);

查看PHP文档以获取更多示例:http://php.net/manual/en/mysqli.insert-id.php


谢谢你指出来。我真的更喜欢JavaScript的点符号表示法,而不是PHP的箭头表示法。 :/ - Luke

7

我想补充一点关于lastInsertId()的小细节;

当一次插入多行时,它不会返回最后一个ID,而是返回最后插入的集合中的第一个ID。

考虑以下示例:

$sql = 'INSERT INTO my_table (varNumb,userid) VALUES
     (1, :userid),
     (2, :userid)';
$sql->addNewNames = $db->prepare($sql);
addNewNames->execute(array(':userid' => $userid));

echo $db->lastInsertId();

这里发生的是,我向my_table中插入两行新记录。表的ID是自增的。在这里,对于同一用户,我添加了两行具有不同varNumb值的记录。
最后输出的值将等于varNumb=1所在行的ID,这意味着它不是最后添加的行的ID,而是在上次请求中添加的第一行的ID。

一次只执行一个操作-似乎是所有方法的总体答案,以避免意外行为。 - RozzA

1

2
不安全的 mysql 答案,永远不要使用它。 - RozzA

1
一个例子。
    $query_new = "INSERT INTO students(courseid, coursename) VALUES ('', ?)";
    $query_new = $databaseConnection->prepare($query_new);
    $query_new->bind_param('s', $_POST['coursename']);
    $query_new->execute();
    $course_id = $query_new->insert_id;
    $query_new->close();

这行代码 $course_id = $query_new->insert_id; 将显示最后插入行的ID。 希望这能帮到你。

1
尝试这样做,你就可以得到答案:

<?php
$con=mysqli_connect("localhost","root","","new");
// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }

mysqli_query($con,"INSERT INTO new values('nameuser','2015-09-12')");

// Print auto-generated id
echo "New record has id: " . mysqli_insert_id($con);

mysqli_close($con);
?>

请看以下链接:

Have a look at following links:

http://www.w3schools.com/php/func_mysqli_insert_id.asp

http://php.net/manual/en/function.mysql-insert-id.php

请注意,此扩展在PHP 5.5中已被弃用并在PHP 7.0中被移除。


0

试试这个...对我有用!

$sql = "INSERT INTO tablename (row_name) VALUES('$row_value')";
    if (mysqli_query($conn, $sql)) {
    $last_id = mysqli_insert_id($conn);
    $msg1 = "New record created successfully. Last inserted ID is: " . $last_id;
} else {
    $msg_error = "Error: " . $sql . "<br>" . mysqli_error($conn);
    }

-1

另一个可能的答案是:

当您定义表格及其列和数据时,列id可以具有属性AUTO_INCREMENT

通过这种方法,您不必担心id,它将自动生成

例如(摘自w3schools

CREATE TABLE Persons
(
ID int NOT NULL AUTO_INCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (ID)
)

希望这对某些人有所帮助。

编辑:这只是定义如何生成自动ID的部分,在创建后获得它,之前的答案是正确的。


这不是可能的答案,OP已经声明他们正在使用自动增量(auto-increment)。OP想要检索自动生成的ID。 - RozzA
好的,在重新阅读后,我注意到问题不仅仅是生成id,OP也想获取该id。感谢定义 :D - neoSmith

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