PHP/MySQL insert row then get 'id'

Solution 1:

$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);

See mysqli_insert_id().

Whatever you do, don't insert and then do a "SELECT MAX(id) FROM mytable". Like you say, it's a race condition and there's no need. mysqli_insert_id() already has this functionality.


Another way would be to run both queries in one go, and using MySQL's LAST_INSERT_ID() method, where both tables get modified at once (and PHP does not need any ID), like:

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

Note that Each connection keeps track of ID separately (so, conflicts are prevented already).

Solution 2:

The MySQL function LAST_INSERT_ID() does just what you need: it retrieves the id that was inserted during this session. So it is safe to use, even if there are other processes (other people calling the exact same script, for example) inserting values into the same table.

The PHP function mysql_insert_id() does the same as calling SELECT LAST_INSERT_ID() with mysql_query().

Solution 3:

As to PHP's website, mysql_insert_id is now deprecated and we must use either PDO or MySQLi (See @Luke's answer for MySQLi). To do this with PDO, proceed as following:

$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();