MySQL AUTO_INCREMENT with Examples

โšก Smart Summary

MySQL AUTO_INCREMENT generates sequential numbers automatically for a numeric column each time a row is inserted. The attribute removes the need to calculate unique identifiers by hand, which makes it the standard way to populate a primary key.

  • ๐Ÿ”ข Core Behaviour: AUTO_INCREMENT issues the next number in sequence whenever a new row is inserted, starting at 1 and stepping by 1.
  • ๐Ÿ”‘ Primary Key Role: The attribute guarantees a unique identifier without a lookup query, so it is the standard choice for a surrogate primary key.
  • ๐Ÿงฑ Column Requirements: The column must be an integer type and must be indexed, which the PRIMARY KEY declaration already satisfies.
  • โž• Insert Pattern: Omit the identifier column from the INSERT statement and MySQL supplies the value, then LAST_INSERT_ID() returns it.
  • ๐ŸŽš๏ธ Custom Start Value: CREATE TABLE or ALTER TABLE accepts AUTO_INCREMENT = 10 to begin the sequence at a chosen number.
  • ๐Ÿ•ณ๏ธ Expect Gaps: Deleted rows and rolled-back transactions consume numbers permanently, so the sequence stays unique but not contiguous.

MySQL AUTO_INCREMENT

What is auto increment?

Auto Increment is a function that operates on numeric data types. It automatically generates sequential numeric values every time that a record is inserted into a table for a field defined as auto increment.

The attribute works on any integer type, from TINYINT through to BIGINT. The column must also be indexed, which happens automatically when it is declared as the primary key.

When use auto increment?

In the lesson on database normalization, we looked at how data can be stored with minimal redundancy, by storing data into many small tables, related to each other using primary and foreign keys.

MySQL AUTO_INCREMENT with Examples

A primary key must be unique, as it uniquely identifies a row in a database. But how can we ensure that the primary key is always unique?

One of the possible solutions would be to use a formula to generate the primary key, which checks for the existence of the key in the table before adding data. This may work, but the approach is complex and not foolproof. Two sessions inserting at the same moment can still read the same maximum value and collide.

In order to avoid such complexity, and to ensure that the primary key is always unique, we can use the MySQL auto increment feature to generate primary keys. Auto increment is used with the INT data type. The INT data type supports both signed and unsigned values. Unsigned data types can only contain positive numbers. As a best practice, it is recommended to define the unsigned constraint on the auto increment primary key.

Auto increment syntax

With the reasoning settled, look at the script used to create the movie categories table.

CREATE TABLE `categories` (
  `category_id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `category_name` varchar(150) DEFAULT NULL,
  `remarks` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`category_id`)
);

Notice the “AUTO_INCREMENT” on the category_id field. This causes the category id to be automatically generated every time a new row is inserted into the table. It is not supplied when inserting data into the table, MySQL generates it.

Note: the UNSIGNED keyword doubles the positive range of the column, and the display width once written as int(11) is deprecated from MySQL 8.0.17 onward. Plain int is the current form.

By default, the starting value for AUTO_INCREMENT is 1, and it will increment by 1 for each new record.

Let us examine the current contents of the categories table.

SELECT * FROM `categories`;

Executing the above script in MySQL Workbench against the myflixdb gives us the following results.

category_id category_name remarks
1 Comedy Movies with humour
2 Romantic Love stories
3 Epic Story acient movies
4 Horror NULL
5 Science Fiction NULL
6 Thriller NULL
7 Action NULL
8 Romantic Comedy NULL

Eight rows exist, so the next generated id should be 9. Let us now insert a new category into the categories table, supplying only the name.

INSERT INTO `categories` (`category_name`) VALUES ('Cartoons');

Executing the above script against the myflixdb in MySQL workbench gives us the following results shown below.

category_id category_name remarks
1 Comedy Movies with humour
2 Romantic Love stories
3 Epic Story acient movies
4 Horror NULL
5 Science Fiction NULL
6 Thriller NULL
7 Action NULL
8 Romantic Comedy NULL
9 Cartoons NULL

Note that we did not supply the category id. MySQL generated it automatically, because the category id is defined as auto increment.

If you want to get the last insert id that was generated by MySQL, you can use the LAST_INSERT_ID function to do that. The script shown below gets the last id that was generated.

SELECT LAST_INSERT_ID();

Executing the above script gives the last auto increment number generated by the INSERT query. The results are shown below.

MySQL AUTO_INCREMENT

Tip: LAST_INSERT_ID() is scoped to your own connection, so a value generated by another user’s insert can never be returned to you by mistake.

How to Set or Reset the AUTO_INCREMENT Start Value

The default sequence begins at 1, but that is not always what a project needs. Invoice numbers may have to continue from a legacy system, and a test table often has to be reset. MySQL exposes the counter directly, so both cases are handled with a single clause. Follow these steps to control the starting number.

  1. Set the value at creation time. Append the AUTO_INCREMENT clause to the CREATE TABLE statement. The first row inserted then receives that number instead of 1.
  2. Change the value on an existing table. Use ALTER TABLE with the same clause. MySQL accepts the new number only if it is higher than the largest identifier currently stored.
  3. Reset a table you have emptied. TRUNCATE TABLE removes all rows and returns the counter to 1 in one operation, which DELETE alone does not do.
  4. Confirm the change. Insert a row and read the identifier back with LAST_INSERT_ID() before relying on the new sequence.
-- Start a brand-new table at 1000
CREATE TABLE `invoices` (
  `invoice_id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `amount` decimal(10,2),
  PRIMARY KEY (`invoice_id`)
) AUTO_INCREMENT = 1000;

-- Move the counter on an existing table
ALTER TABLE `categories` AUTO_INCREMENT = 100;

-- Empty the table and reset the counter to 1
TRUNCATE TABLE `categories`;

The step size can also be changed with the auto_increment_increment system variable, but it applies to the whole server rather than to one table. It is used mainly in replication, where two servers must not generate the same identifier.

Why Do Gaps Appear in an AUTO_INCREMENT Sequence?

Sooner or later a table shows identifiers such as 1, 2, 5, 6. Nothing is broken. The counter is designed to guarantee uniqueness, not to guarantee an unbroken run of numbers, and it never issues the same value twice.

Gaps appear for the following reasons.

  • Deleted rows: when a row is deleted from a table, its auto incremented id is not re-used. MySQL continues generating new numbers sequentially.
  • Rolled-back transactions: the number is claimed the moment the insert runs. If the transaction is rolled back, the row disappears but the number is already spent.
  • Failed inserts: a statement rejected by a UNIQUE constraint can still consume an identifier before it fails.
  • Bulk inserts: InnoDB may reserve a block of numbers for a multi-row insert and discard the ones it does not use.

Trying to close these gaps is a mistake. Renumbering rows breaks every foreign key that points at them, and the value itself carries no business meaning. If a report needs a continuous list, generate the row number in the query instead of rewriting stored data.

FAQs

No. MySQL permits exactly one AUTO_INCREMENT column per table, and that column must be indexed. Declaring it as the primary key satisfies the index requirement.

Inserts fail with a duplicate key error, because the counter cannot advance past the maximum of the data type. An unsigned TINYINT stops at 255. Change the column to a wider type such as BIGINT before that point.

Yes, from MySQL 8.0 onward. InnoDB writes the counter to the redo log, so it is restored after a restart. Earlier versions recalculated it and could re-issue numbers freed by deletions.

Partly. AI schema assistants inside tools such as MySQL Workbench suggest an unsigned integer wide enough for the volume you describe. The estimate is only as good as the growth figure you supply, so verify it.

Often, yes. AI query assistants point to rolled-back transactions, failed INSERT statements, and deleted rows as the usual causes. Treat the explanation as a starting point and confirm it against the server logs.

Summarize this post with: