144

How to get the next id in mysql to insert it in the table

INSERT INTO payments (date, item, method, payment_code)
VALUES (NOW(), '1 Month', 'paypal', CONCAT("sahf4d2fdd45", id))
Markus Malkusch
  • 7,738
  • 2
  • 38
  • 67
faressoft
  • 19,053
  • 44
  • 104
  • 146
  • 1
    use an `auto_increment` column – knittl Jul 20 '11 at 11:55
  • Do you want the *next* id, or the id of the row that you are currently inserting? That is, should the id at the end of the payment code be the id of the row in which the payment code is stored? – Mike Jul 20 '11 at 12:30
  • id of the row that I am currently inserting – faressoft Jul 20 '11 at 12:49
  • 7
    In that case, concatenate the values when you retrieve them, not when you insert them. It's far easier that way, and you rule out getting the wrong id, or having to run an update - think what would happen if the row you have just inserted is requested by another client, before the update has had chance to run: the client would end up with an invalid payment code. On a low-traffic system, that might not occur, but I don't see the point of taking the risk. – Mike Jul 20 '11 at 12:53
  • ...or as @binaryLV points out, resource locking might also solve the problem. See: http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html – Mike Jul 20 '11 at 13:05
  • **All the other answers that use `MAX` will fail if the most recent record is deleted from the table. On the other hand, most databases setups lock down `information_schema` and for this reason @ravi404's answer may fail but speaking in terms of robustness it is the best answer so far.** – Peter Chaula Feb 16 '17 at 09:54
  • https://www.bram.us/2008/07/30/mysql-get-next-auto_increment-value-fromfor-table/ – Alex Mar 16 '17 at 12:44

21 Answers21

287

You can use

SELECT AUTO_INCREMENT
FROM information_schema.tables
WHERE table_name = 'table_name'
AND table_schema = DATABASE( ) ;

or if you do not wish to use information_schema you can use this

SHOW TABLE STATUS LIKE 'table_name'
ravi404
  • 7,119
  • 4
  • 31
  • 40
  • Thanks for the first two options.. But the third is just number two called from PHP.. Not sure what makes that faster on large databases... – Gerard ONeill Feb 12 '16 at 15:26
  • 1
    @GerardONeill Removed it – ravi404 Feb 15 '16 at 07:05
  • @JohnIsaiahCarmona there is a big list of functions you might also need to take a look at. [Mysql function reference](https://dev.mysql.com/doc/refman/5.7/en/functions.html "5.7 docs") – Peter Chaula Feb 16 '17 at 09:49
  • All the other answers that use `MAX` will fail if the most recent record is deleted from the table. On the other hand, most databases setups lock down `information_schema` and for this reason this may fail but speaking in terms of robustness. This is the best answer so far. – Peter Chaula Feb 16 '17 at 09:53
  • 7
    because a cache is used to retrieve the data from information_schema.tables, this solution do no more work for mysql 8. – Bruno Feb 06 '19 at 16:39
  • 1
    @Bruno can you post a reference? – mvorisek Sep 02 '19 at 19:24
  • Is the query guaranteed to be atomic, i.e. select the same ID to be inserted in an insert query? – mvorisek Sep 02 '19 at 19:25
  • 3
    This official doc state that `TABLES.AUTO_INCREMENT` is cached https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_information_schema_stats_expiry . Mysql blog also has several post about it, but the system varaible they mention seems outdated: https://mysqlserverteam.com/mysql-8-0-scaling-and-performance-of-information_schema/ https://mysqlserverteam.com/mysql-8-0-improvements-to-information_schema/ – Bruno Sep 03 '19 at 13:35
  • 1
    _Is the query guaranteed to be atomic_ : No you cannot have such guarantee, but since the primary key has a unique index, you just can try until the write succeed ;) – Bruno Sep 03 '19 at 13:37
  • 1
    I got NULL value in `Auto_increment` upon executing `SHOW TABLE STATUS LIKE 'table_name'`. There is definitely good amount of rows in table. Engine value is `MemSql` – IsmailS Jul 17 '20 at 05:47
  • 1
    @IsmailS if you get `NULL` when selecting `AUTO_INCREMENT` that means that your table is not set up to `Auto-increment`. – user11809641 Dec 04 '20 at 02:51
  • 2
    the second query does return the next auto increment value, but it is cached (default cache duration is 24h). To get the UP TO DATE auto increment value just run `SET information_schema_stats_expiry = 0;` before the query. – aetonsi May 12 '22 at 07:57
56

You can get the next auto-increment value by doing:

SHOW TABLE STATUS FROM tablename LIKE Auto_increment
/*or*/
SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = 'tablename'

Note that you should not use this to alter the table, use an auto_increment column to do that automatically instead.
The problem is that last_insert_id() is retrospective and can thus be guaranteed within the current connection.
This baby is prospective and is therefore not unique per connection and cannot be relied upon.
Only in a single connection database would it work, but single connection databases today have a habit of becoming multiple connection databases tomorrow.

See: SHOW TABLE STATUS

Johan
  • 74,508
  • 24
  • 191
  • 319
  • 9
    I didn't downvote it, but the problem with attempting to use the last auto incrementing value is that it might not be the last one by the time you come to use it - no matter how quickly the SELECT and subsequent INSERT is carried out. – Mike Jul 20 '11 at 12:33
  • @Mike, what if it is done in single query? Something like `insert into table_name (field1, field2) select 'constant', auto_increment from information_schema.tables where table_name = 'table_name'`? I would use updating in `after insert` trigger and `last_insert_id()`, though... – binaryLV Jul 20 '11 at 12:37
  • 1
    @binaryLV: The smaller the gap between the SELECT and the INSERT, the smaller the chance that the value will have changed, but it doesn't rule it out completely. Imagine a system with thousands of hits per minute on the database - the chances of the value having changed increase dramatically. Table or row locking may prevent this if it is done as a single query, but that's relying on a particular behaviour of the database engine which may not be well documented. I'd go with a subsequent `UPDATE` if I had too. But I'd rather just concatenate the two at display time, and save all the hassle. – Mike Jul 20 '11 at 12:44
  • ...fixing a SELECT query or line of app code where someone forgot to concatenate a couple of values is simple. Fixing randomly corrupted rows in the database is much harder. – Mike Jul 20 '11 at 12:47
  • @Mike, it's not about gaps, it's about locking/unlocking resources. As for depending on behavior of the DB engine - depending on behavior is the same as depending on features (recursive queries, triggers, `insert .. on duplicate key update ..` etc) that are provided by DBMS. P.S. Trying to remember that fields have to be concatenated is **not simple**. It gets even more difficult, if many developers have to remember that (and tell to newcomers) for few years. – binaryLV Jul 20 '11 at 12:52
  • @binaryLV: as I said, table or row locking may prevent the problem. If it is clearly documented that the locking behaviour of an `INSERT INTO ... SELECT` would prevent a race condition, then yes, go ahead and use it that way. I guess the tables could be manually locked to ensure that this is the case. – Mike Jul 20 '11 at 13:01
  • @binaryLV: Okay,I think [this is the relevant InnoDB documenation](http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html) - see "INSERT INTO T SELECT ... FROM S WHERE ...". I'm not entirely sure what it all means yet ;-) – Mike Jul 20 '11 at 13:23
  • 1
    basically need to see what the next autoincrement will be. This is the best option because I haven't inserted anything yet! Just be sure to lock the table where the records will be inserted BEFORE calling this and using it later (after you unlock of course!) ex. LOCK TABLES t1 READ; – Bretticus Aug 08 '13 at 22:32
  • 7
    `SHOW TABLE STATUS` expects to see `database name` after `FROM` and `'table name pattern'` after `LIKE`. – x-yuri Dec 08 '14 at 13:49
  • usually in where clause we use a column level constrain. why did you use table name in their ? – asela daskon Mar 12 '16 at 12:58
  • @aselanuwan, the `information_schema` is a table that happens to store table names in its columns. So I'm really using a column constrain. – Johan Mar 13 '16 at 00:01
  • 4
    because a cache is used to retrieve the data from information_schema.tables, this solution do no more work for mysql 8. – Bruno Feb 06 '19 at 16:40
  • @Bruno the query does return the next auto increment value, but it is cached (default cache duration is 24h). To get the UP TO DATE auto increment value just run `SET information_schema_stats_expiry = 0;` before the query. – aetonsi May 12 '22 at 07:59
21

This will return auto increment value for the MySQL database and I didn't check with other databases. Please note that if you are using any other database, the query syntax may be different.

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = 'your_database_name';

SELECT AUTO_INCREMENT 
FROM information_schema.tables
WHERE table_name = 'your_table_name'
     and table_schema = database();
Chaminda Bandara
  • 2,067
  • 2
  • 28
  • 31
  • 1
    SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'your_table_name' and table_schema = 'your_database_name'; – LJay Jan 17 '20 at 11:10
11

The top answer uses PHP MySQL_ for a solution, thought I would share an updated PHP MySQLi_ solution for achieving this. There is no error output in this exmaple!

$db = new mysqli('localhost', 'user', 'pass', 'database');
$sql = "SHOW TABLE STATUS LIKE 'table'";
$result=$db->query($sql);
$row = $result->fetch_assoc();

echo $row['Auto_increment'];

Kicks out the next Auto increment coming up in a table.

Hexchaimen
  • 341
  • 2
  • 9
  • because a cache is used to retrieve the data from information_schema.tables, this solution do no more work for mysql 8. – Bruno Feb 06 '19 at 16:40
10

In PHP you can try this:

$query = mysql_query("SELECT MAX(id) FROM `your_table_name`");
$results = mysql_fetch_array($query);
$cur_auto_id = $results['MAX(id)'] + 1;

OR

$result = mysql_query("SHOW TABLE STATUS WHERE `Name` = 'your_table_name'");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];
Naresh Jain
  • 157
  • 1
  • 7
7

Solution:

CREATE TRIGGER `IdTrigger` BEFORE INSERT ON `payments`
  FOR EACH ROW
BEGIN

SELECT  AUTO_INCREMENT Into @xId
    FROM information_schema.tables
    WHERE 
    Table_SCHEMA ="DataBaseName" AND
    table_name = "payments";

SET NEW.`payment_code` = CONCAT("sahf4d2fdd45",@xId);

END;

"DataBaseName" is the name of our Data Base

Tisho
  • 8,320
  • 6
  • 44
  • 52
Angel
  • 71
  • 1
  • 1
7

Use LAST_INSERT_ID() from your SQL query.

Or

You can also use mysql_insert_id() to get it using PHP.

Sarfraz
  • 377,238
  • 77
  • 533
  • 578
6

Simple query would do SHOW TABLE STATUS LIKE 'table_name'

Raa
  • 61
  • 1
  • 2
6

For MySQL 8 use SHOW CREATE TABLE to retrieve the next autoincrement insert id:

SHOW CREATE TABLE mysql.time_zone

Result:

CREATE TABLE `time_zone` (
  `Time_zone_id` int unsigned NOT NULL AUTO_INCREMENT,
  `Use_leap_seconds` enum('Y','N') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'N',
  PRIMARY KEY (`Time_zone_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1784 DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 ROW_FORMAT=DYNAMIC COMMENT='Time zones'

See the AUTO_INCREMENT=1784 at the last line of returned query.

Compare with the last value inserted: select max(Time_zone_id) from mysql.time_zone

Result:

+-------------------+
| max(Time_zone_id) |
+-------------------+
|              1783 |
+-------------------+

Tested on MySQL v8.0.20.

Alexeyer
  • 81
  • 2
  • 3
  • good to see the select max(), for a value that is likely indexed, and likely in buffer. – mckenzm Jan 01 '23 at 09:47
  • 1
    **It is wrong to use max()** to get the next auto-increment id. I've put it here just for result comparison. – Alexeyer Jan 05 '23 at 10:07
5
SELECT id FROM `table` ORDER BY id DESC LIMIT 1

Although I doubt in its productiveness but it's 100% reliable

Tebe
  • 3,176
  • 8
  • 40
  • 60
  • I too agree this is the simplest approach. Not sure why you were down-voted, but I'll offset with an upvote. – recurse Jul 25 '16 at 20:56
  • I didn't mention necessity of transaction, if you don't wrap it inside transaction this code is lousy asap it meets real loading. – Tebe Jul 25 '16 at 21:03
  • 1
    What if the latest row was deleted? Or multiple latest rows have been deleted? – Liam W Oct 26 '16 at 17:36
  • Non-issue, freed keys don't get used unless you specify it explicitly – Tebe Oct 26 '16 at 19:21
4

I suggest to rethink what you are doing. I never experienced one single use case where that special knowledge is required. The next id is a very special implementation detail and I wouldn't count on getting it is ACID safe.

Make one simple transaction which updates your inserted row with the last id:

BEGIN;

INSERT INTO payments (date, item, method)
     VALUES (NOW(), '1 Month', 'paypal');

UPDATE payments SET payment_code = CONCAT("sahf4d2fdd45", LAST_INSERT_ID())
     WHERE id = LAST_INSERT_ID();

COMMIT;
Markus Malkusch
  • 7,738
  • 2
  • 38
  • 67
  • I can tell one such use-case, I am trying to diagnose a production issue, so I need to find out if the last row in a table is really the last row or if there was one added after that which somehow got deleted, table has an auto_increment field in it, so by finding this information I can conclude if the row was deleted or never added. – Usman Nov 01 '18 at 19:00
  • 1
    That might maybe work for you, but I wouldn't rely on that as I don't think you have any guarantee on that: https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html "when the AUTO_INCREMENT column is part of a multiple-column index), AUTO_INCREMENT values are reused if you delete the row with the biggest AUTO_INCREMENT value in any group." – Markus Malkusch Nov 17 '18 at 21:52
  • Thanks, useful information, also as per your shared link auto_increment can be reset be manually inserting a number, so yes not reliable. – Usman Nov 19 '18 at 23:10
4

You have to connect to MySQL and select a database before you can do this

$table_name = "myTable"; 
$query = mysql_query("SHOW TABLE STATUS WHERE name='$table_name'"); 
$row = mysql_fetch_array($query); 
$next_inc_value = $row["AUTO_INCREMENT"];  
Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
jondinham
  • 8,271
  • 17
  • 80
  • 137
3

What do you need the next incremental ID for?

MySQL only allows one auto-increment field per table and it must also be the primary key to guarantee uniqueness.

Note that when you get the next insert ID it may not be available when you use it since the value you have is only within the scope of that transaction. Therefore depending on the load on your database, that value may be already used by the time the next request comes in.

I would suggest that you review your design to ensure that you do not need to know which auto-increment value to assign next

Stephen Senkomago Musoke
  • 3,528
  • 2
  • 29
  • 27
  • It is not a good idea to assume the kind of application that requires the ID. There are applications like the one I am working on at the moment which needs the next incremental ID and the value retrieved is in no danger of being allocated to another script. – JG Estiot Jan 31 '16 at 06:37
3

You can't use the ID while inserting, neither do you need it. MySQL does not even know the ID when you are inserting that record. You could just save "sahf4d2fdd45" in the payment_code table and use id and payment_code later on.

If you really need your payment_code to have the ID in it then UPDATE the row after the insert to add the ID.

Jacob
  • 41,721
  • 6
  • 79
  • 81
  • +1 To make this a little more explicit: if you grab the 'latest' value from a column, it is only guaranteed to be the latest value at the exact moment you grab it. It may not be the latest value when you come to use that value in a subsequent insert. In the case of an auto increment column, there's always the chance that another value has been added between the time that you retrieved the id and the time that you insert it elsewhere. If you are referencing a row that you have just inserted, using LAST_INSERT_ID() is fine. If you are trying to ensure a unique value, it is not. – Mike Jul 20 '11 at 12:24
  • 1
    @cularis, MySQL does know the next auto_increment id, it's listed in the `information_schema.tables` table. – Johan Jul 20 '11 at 12:27
  • 1
    @faressoft: If the idea is to have a payment code that comprises a unique string plus the id of the row that contains that payment code, just combine the two when you retrieve the row - either with a `SELECT ... CONCAT(payment_code, id)`, or in your application code. You could even wrap the `SELECT` in a `VIEW`, so that you always return the right value, without worrying about the CONCAT in every SELECT from your app. – Mike Jul 20 '11 at 12:27
2

use "mysql_insert_id()". mysql_insert_id() acts on the last performed query, be sure to call mysql_insert_id() immediately after the query that generates the value.

Below are the example of use:

<?php
    $link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
    die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');

mysql_query("INSERT INTO mytable  VALUES('','value')");
printf("Last inserted record has id %d\n", mysql_insert_id());
    ?>

I hope above example is useful.

Sagar Chavda
  • 125
  • 1
  • 2
  • 12
2

If return no correct AUTO_INCREMENT, try it:

ANALYZE TABLE `my_table`;
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE (TABLE_NAME = 'my_table');

This clear cache for table, in BD

Vanom
  • 31
  • 1
  • If you dont clear the cache it keeps grabbing the first one it found over and over, so this is good information . – easleyfixed Sep 20 '22 at 16:27
1

using the answer of ravi404:

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

using in your insert query, to create a SHA1 Hash. ex.:

INSERT INTO
    document (Code, Title, Body)
VALUES (                
    sha1( getAutoincrementalNextval ('document') ),
    'Title',
    'Body'
);
Paulo Costa
  • 182
  • 3
  • 12
  • Does this always work? Is there a race conditions if two inserts happen at the same time? – Jmons Oct 27 '16 at 10:07
0

Improvement of @ravi404, in case your autoincrement offset IS NOT 1 :

SELECT (`auto_increment`-1) + IFNULL(@@auto_increment_offset,1) 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = your_table_name
AND table_schema = DATABASE( );

(auto_increment-1) : db engine seems to alwaus consider an offset of 1. So you need to ditch this assumption, then add the optional value of @@auto_increment_offset, or default to 1 : IFNULL(@@auto_increment_offset,1)

Olivier
  • 3,465
  • 2
  • 23
  • 26
0

For me it works, and looks simple:

 $auto_inc_db = mysql_query("SELECT * FROM my_table_name  ORDER BY  id  ASC ");
 while($auto_inc_result = mysql_fetch_array($auto_inc_db))
 {
 $last_id = $auto_inc_result['id'];
 }
 $next_id = ($last_id+1);


 echo $next_id;//this is the new id, if auto increment is on
  • Quite unnecessary to assign `$last_id` repetitively when you can just `DESC`. Your `while` block did loads of useless work. – Til Jan 18 '19 at 11:40
  • 1
    yes, right...I've just realized it's not perfect...:( end one can repeat the id, if it was deleted before... :( – Toncsiking Jan 18 '19 at 11:44
0

SELECT AUTO_INCREMENT AS next_id FROM information_schema.tables WHERE table_name = 'table name' AND table_schema = 'database name of table name'

-1
mysql_insert_id();

That's it :)

MPelletier
  • 16,256
  • 15
  • 86
  • 137
user3814281
  • 49
  • 1
  • 4