404

Let's say I am doing a MySQL INSERT into one of my tables and the table has the column item_id which is set to autoincrement and primary key.

How do I get the query to output the value of the newly generated primary key item_id in the same query?

Currently I am running a second query to retrieve the id but this hardly seems like good practice considering this might produce the wrong result...

If this is not possible then what is the best practice to ensure I retrieve the correct id?

Lii
  • 11,553
  • 8
  • 64
  • 88
Amy Neville
  • 10,067
  • 13
  • 58
  • 94
  • 9
    Well, if the process is executed by 2 people seperately then you could get an overlapping process list I think - since you have to execute 2 separate queries? – Amy Neville Jun 14 '13 at 16:19
  • Possible duplicate of [PHP/MySQL insert row then get 'id'](http://stackoverflow.com/questions/897356/php-mysql-insert-row-then-get-id) – Jim Fell May 23 '16 at 13:58
  • @JimFell yes it's basically the same question, but this one has much better answers in general – RozzA Dec 06 '16 at 19:33
  • 1
    Use postgresql then do like this INSERT INTO table (col1,col2) VALUES (val1,val2) RETURNING id or INSERT INTO table (col1,col2) VALUES (val1,val2) RETURNING * or UPDATE table SET col1=val1, col2=val2 WHERE statement RETURNING id or UPDATE table SET (col1,col2)=(val1,val2) WHERE statement RETURNING id or UPDATE table SET (col1,col2)=(val1,val2) WHERE statement RETURNING * – gdarcan Mar 07 '20 at 23:10

13 Answers13

509

You need to use the LAST_INSERT_ID() function: http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

Eg:

INSERT INTO table_name (col1, col2,...) VALUES ('val1', 'val2'...);
SELECT LAST_INSERT_ID();

This will get you back the PRIMARY KEY value of the last row that you inserted:

The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client.

So the value returned by LAST_INSERT_ID() is per user and is unaffected by other queries that might be running on the server from other users.

Duncan Lock
  • 12,351
  • 5
  • 40
  • 47
  • 20
    yes but what if in the interim (between queries in the process list) some other row has been inserted? Is there any way to write the insert query so that it outputs this? – Amy Neville Jun 14 '13 at 16:19
  • Ok, I see...the last insert id of the query is recorded even if it isn't logged in the result...$mysqli->insert_id – Amy Neville Jun 14 '13 at 16:26
  • 75
    This will get you back the `PRIMARY KEY` value of the last row that *you* inserted, because it's per connection - each connection to the server will maintain it's own value for this. I've updated the answer to clarify this. – Duncan Lock Jun 14 '13 at 16:31
  • 1
    So suppose 3 users simultaneously posted their forms and my database has to enter them. I want to add a row corresponding to each newly created ID of table1 in table2. Is concurrency taken care of or will I have to do it in PHP manually, for incoming database write requests? – bad_keypoints Sep 16 '13 at 07:46
  • If, at the point that you do the table1 insert, the database knows all the information that you want to insert into table2, then you could use a trigger to do this, or combine this into a query. If not, then you'd need to use multiple queries - i.e. do it in PHP. It depends on what the data is and where it's coming from for the second insert. – Duncan Lock Sep 25 '13 at 17:41
  • nice... plain and simple explanation – Houston Jan 25 '14 at 13:02
  • how does that work with a failed insert ie `insert ignore` or `insert on duplicate key`? ie the insert failed ie does LAST_INSERT_ID() return the failed ID, null or the last successful id that's actually unrelated to the current query – MikeT Feb 10 '17 at 10:20
  • According to the documentation (https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_last-insert-id): "The value of LAST_INSERT_ID() remains unchanged if no rows are successfully inserted." - so, it will return the value of the last successfully inserted row. – Duncan Lock Feb 12 '17 at 08:07
  • How about wrapping the insert statement and the `SELECT LAST_INSERT_ID()` in a stored procedure? – Keiron Stoddart Nov 19 '21 at 21:48
  • @KeironStoddart It works the same way: "MySQL :: MySQL 5.6 Reference Manual :: 20.2.4 Stored Procedures, Functions, Triggers, and LAST_INSERT_ID()" https://dev.mysql.com/doc/refman/5.6/en/stored-routines-last-insert-id.html – Duncan Lock Nov 20 '21 at 02:10
  • 1
    @DuncanLock, right on - I appreciate the reference. I was just commenting on the request to do the insert and the id select at the same time. – Keiron Stoddart Nov 20 '21 at 18:36
  • Isn't the more secure way doing this in a transaction inside a stored procedure? – Oliver Voutat May 19 '22 at 22:08
37

BEWARE !! of LAST_INSERT_ID() if trying to return this primary key value within PHP.

I know this thread is not tagged PHP, but for anybody who came across this answer looking to return a MySQL insert id from a PHP scripted insert using standard mysql_query calls - it wont work and is not obvious without capturing SQL errors.

The newer mysqli supports multiple queries - which LAST_INSERT_ID() actually is a second query from the original.

IMO a separate SELECT to identify the last primary key is safer than the optional mysql_insert_id() function returning the AUTO_INCREMENT ID generated from the previous INSERT operation.

Lii
  • 11,553
  • 8
  • 64
  • 88
Martin Sansone - MiOEE
  • 4,281
  • 1
  • 29
  • 31
  • 14
    `LAST_INSERT_ID` is a per-connection MySQL function. If you query for the last insert ID it is possible a separate connection will have performed a write and you will have the wrong ID. – Explosion Pills Aug 07 '14 at 17:19
  • @ExplosionPills `mysql_insert_id()` also works on a per connection basis, but it also suffers strange behaviour as seen here http://stackoverflow.com/a/897374/1305910 in the comment by Cliffordlife -- nevermind we should all have been using `mysqli` – RozzA Dec 06 '16 at 19:32
  • 2
    can you clarify what you mean when you stay 'it wont work'? – john k Jun 12 '18 at 20:23
27

From the LAST_INSERT_ID() documentation:

The ID that was generated is maintained in the server on a per-connection basis

That is if you have two separate requests to the script simultaneously they won't affect each others' LAST_INSERT_ID() (unless you're using a persistent connection perhaps).

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • 3
    I think it is dubious if your table has a trigger on it that does an insert into another table.... LAST_INSERT_ID() will return the id value of the other table.. – bgies Sep 23 '18 at 11:34
27

You will receive these parameters on your query result:

    "fieldCount": 0,
    "affectedRows": 1,
    "insertId": 66,
    "serverStatus": 2,
    "warningCount": 1,
    "message": "",
    "protocol41": true,
    "changedRows": 0

The insertId is exactly what you need.

(NodeJS-mySql)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MESepehr
  • 758
  • 6
  • 19
24

Here what you are looking for !!!

select LAST_INSERT_ID()

This is the best alternative of SCOPE_IDENTITY() function being used in SQL Server.

You also need to keep in mind that this will only work if Last_INSERT_ID() is fired following by your Insert query. That is the query returns the id inserted in the schema. You can not get specific table's last inserted id.

For more details please go through the link The equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?

Community
  • 1
  • 1
PVR
  • 2,534
  • 18
  • 38
20

If in python using pymysql, from the cursor you can use cursor.lastrowid.

It is a documented extension in PEP-249 DB API standard, and also works with other Python MySQL implementations.

MarSoft
  • 3,555
  • 1
  • 33
  • 38
mojoken
  • 1,256
  • 1
  • 15
  • 27
  • 4
    Dude, you deserve a medal for this comment. This post was the best thing that happened today. – DeadSec Jul 13 '20 at 19:59
19

You need to use the LAST_INSERT_ID() function with transaction:

START TRANSACTION;
  INSERT INTO dog (name, created_by, updated_by) VALUES ('name', 'migration', 'migration');
  SELECT LAST_INSERT_ID();
COMMIT;

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id

This function will be return last inserted primary key in table.

10

Simply use:

$last_id = mysqli_insert_id($conn);
AlexSp3
  • 2,201
  • 2
  • 7
  • 24
Curious Flower
  • 347
  • 3
  • 7
  • 3
    I actually stumbled here looking for the php version of this answer thanks to google, so I voted this answer up. While technically the OP didn't ask for php, this could be helpful to a lot of people who stumble here as well. – Photographer Britt Jul 31 '18 at 01:03
  • Thank you very much Arnav! I – JuanSedano May 21 '19 at 16:10
5

If you need the value before insert a row:

CREATE FUNCTION `getAutoincrementalNextVal`(`TableName` VARCHAR(50))
    RETURNS BIGINT
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

    DECLARE Value BIGINT;

    SELECT
        AUTO_INCREMENT INTO Value
    FROM
        information_schema.tables
    WHERE
        table_name = TableName AND
        table_schema = DATABASE();

    RETURN Value;

END

You can use this in a insert:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( concat (convert ( now() , char), ' ',   getAutoincrementalNextval ('document') ) ),
    'Title',
    'Body'
);
Paulo Costa
  • 182
  • 3
  • 12
  • 5
    This one doesn't seem to be a good idea? If 2 clients call that function at the same time, they'll think they're inserting the same id when in reality they are not.... one will be slightly slower on the insert and get the next ID without it knowing. – CarCar Jul 07 '17 at 07:45
4

If you are using PHP: On a PDO object you can simple invoke the lastInsertId method after your insert.

Otherwise with a LAST_INSERT_ID you can get the value like this: SELECT LAST_INSERT_ID();

Olafnyr
  • 41
  • 2
3

i used return $this->db->insert_id(); for Codeigniter

0

Do this:

$idc = DB::table('tb_clients')->insertGetId([
                'ide'                   => $ide,
                'nome'                  => $nome,
                'email'                 => $email 
            ]);

on $idc you will get the last id

Luciano Coelho
  • 89
  • 1
  • 11
-2

I just want to share my approach to this in PHP, some of you may found it not an efficient way but this is a 100 better than other available options.

generate a random key and insert it into the table creating a new row. then you can use that key to retrieve the primary key. use the update to add data and do other stuff.

doing this way helps to secure a row and have the correct primary key.

I really don't recommend this unless you don't have any other options.

Singh G
  • 45
  • 1
  • 7
  • 1
    You can use a PDO Object and get the last insert ID. You can also use SELECT LAST_INSERT_ID() inside the same transaction (it is very important to use the same transaction if you have several people inserting). Your proposed method have no guarantees - although unlikely, you could have collision on the keys. Also, adding all data via update means you can't have non-null fields, and this leads to worse data integrity as well. Finally, something may break betweek the insert of the random key and the update, and you are left with an unwanted state and no data integrity. – Enrico Feb 04 '21 at 00:12
  • I don't know why the poster suggests insertion and update as two different operations; when I had to use this approach I generated the random key by code and used it in the insert query along with all the records fields. Honestly with UUID it's statistically impossible to have collisions (16^32 possibilities). I found this approach a valid solution for the OP issue – Jack Dec 08 '21 at 20:55