MySQL AUTO_INCREMENT automatically generates a numeric value when a new row is inserted. It is commonly used for surrogate primary keys such as user IDs, order IDs, ticket IDs and student IDs.
CREATE TABLE student (
student_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (student_id)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4;
Insert a row without supplying the auto-increment column:
INSERT INTO student
(name, email)
VALUES
('John', 'john@example.com');
MySQL generates the student_id value automatically.
A typical modern definition uses an integer column as the primary key:
CREATE TABLE student (
student_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
PRIMARY KEY (student_id)
);
For normal application tables, making the AUTO_INCREMENT column the PRIMARY KEY is the clearest design.
Omit the auto-increment column from the INSERT column list:
INSERT INTO student
(name, email)
VALUES
('John', 'john@example.com');
If the table is empty and the counter starts at its normal default, the first generated ID is usually 1, followed by later generated values.
You can inspect the rows with:
SELECT student_id, name, email
FROM student
ORDER BY student_id;
See SQL INSERT for more insert patterns.
At SQL level, MySQL provides LAST_INSERT_ID() for the most recent automatically generated value in the current session:
INSERT INTO student
(name, email)
VALUES
('Ravi', 'ravi@example.com');
SELECT LAST_INSERT_ID() AS new_student_id;
Application APIs also expose the generated value. With PHP PDO, use lastInsertId() after a successful INSERT.
The related MySQL insert ID tutorial covers retrieving the generated identifier from application code.
An AUTO_INCREMENT column must be indexed appropriately by MySQL. For the common one-ID-per-row design, use it as the primary key:
CREATE TABLE tickets (
ticket_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
subject VARCHAR(200) NOT NULL,
PRIMARY KEY (ticket_id)
);
A primary key also guarantees uniqueness and prevents NULL values in the identifier.
You can set an initial counter when creating a table:
CREATE TABLE student (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
class VARCHAR(10) NOT NULL,
mark INT NOT NULL DEFAULT 0,
gender VARCHAR(10) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB
AUTO_INCREMENT=100000
DEFAULT CHARSET=utf8mb4;
The first automatically generated ID will start from the configured counter, assuming no existing row requires a higher next value.
To request a higher next value for an existing table:
ALTER TABLE student
AUTO_INCREMENT = 50000;
If existing rows already contain IDs at or above the requested value, MySQL will not reuse an already occupied key. Do not use AUTO_INCREMENT settings as a mechanism for filling historical gaps.
An AUTO_INCREMENT column is designed to generate unique identifiers efficiently. It is not a gapless sequence generator.
For example, a table can contain:
1
2
4
7
without anything being wrong.
Gaps can appear because of:
A normal DELETE removes rows but should not be expected to restart the AUTO_INCREMENT sequence.
DELETE FROM student
WHERE id = 7;
MySQL does not normally reuse that deleted ID automatically.
TRUNCATE TABLE removes all rows and, for normal InnoDB tables, resets the AUTO_INCREMENT counter:
TRUNCATE TABLE student;
The maximum generated value depends on the integer datatype and whether it is signed or unsigned.
| Type | Signed maximum | Unsigned maximum |
|---|---|---|
TINYINT | 127 | 255 |
SMALLINT | 32,767 | 65,535 |
MEDIUMINT | 8,388,607 | 16,777,215 |
INT | 2,147,483,647 | 4,294,967,295 |
BIGINT | 9,223,372,036,854,775,807 | 18,446,744,073,709,551,615 |
Choose the datatype according to realistic lifetime growth, not only the number of rows expected today.
If an identifier never needs negative numbers, an unsigned integer can provide a larger positive range for the same storage size:
id INT UNSIGNED NOT NULL AUTO_INCREMENT
For extremely high-volume tables, consider BIGINT UNSIGNED rather than waiting until an INT counter approaches its limit.
Older MySQL examples often used definitions such as:
-- Legacy style: do not use for new schemas
id INT(5) UNSIGNED ZEROFILL AUTO_INCREMENT
Numeric display width and ZEROFILL are deprecated legacy features in modern MySQL. They should not be used as the default way to format identifiers.
Keep the ID as a numeric value:
id INT UNSIGNED NOT NULL AUTO_INCREMENT
If the user interface must display 00025, format the number for presentation instead of changing the database identifier.
For example, MySQL can format output with LPAD():
SELECT LPAD(
id,
5,
'0'
) AS display_id
FROM student;
The underlying ID remains numeric and can continue to be indexed and compared naturally.
The generated database ID is excellent as a technical key. If the business needs a public reference with prefixes, check digits, secrecy, or a gapless legal sequence, generate that as a separate business identifier.
INT(3) does not mean the integer can store only three digits. The old number in parentheses was a display-width concept, not a storage-range limit.
For the usual surrogate-ID design, define the AUTO_INCREMENT identifier as the primary key.
Gaps are normal and can occur even without manual deletion.
Deleting rows does not normally make MySQL restart the sequence or reuse those IDs.
Keep the stored key numeric and format leading zeros in SQL output or the application presentation layer.
Once the AUTO_INCREMENT value reaches the datatype's maximum, further automatic values cannot be generated normally. Plan for lifetime growth.
Do not use MAX(id) to determine which row your session inserted. Use LAST_INSERT_ID() or the database API's insert-ID function.
It automatically generates a numeric value for an AUTO_INCREMENT column when a new row is inserted without an explicit value for that column.
For the common surrogate-key design, yes. Defining it as the primary key provides a clear unique, non-NULL identifier for each row.
No. Gaps can occur because of deletes, failed inserts, rollbacks, concurrency and other normal database operations.
At SQL level use LAST_INSERT_ID() in the same session. In PHP PDO use lastInsertId() after the successful INSERT.
Yes. Set AUTO_INCREMENT=100000 when creating the table or use ALTER TABLE to request a higher next value.
No. A normal DELETE should not be expected to restart the counter. TRUNCATE TABLE normally resets it for an InnoDB table, but TRUNCATE removes all rows and has different semantics.
No for new schemas. Keep the ID numeric and add leading zeros only when formatting it for display.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.
| Senthu | 07-12-2009 |
| How to export the tables in .sql format from phpmysql db by using in phpMySQL ?? Thank you SENTHU | |
| dhananjay | 13-09-2010 |
| goto phpmyadmin, select database , select table using checkbox, go downward select option mysql then zip and click on go it will ask you where u want to save your table . | |
| Nitin | 09-11-2011 |
| is it compulsory to define auto increment field unique or primary key constraint ? | |