Create an Auto-Increment Column in SQLite

SQLite has an interesting way of handling auto-increment columns. By auto-incrementing columns, I mean columns that increment automatically whenever new data is inserted.

This is similar to an IDENTITY column in SQL Server or an AUTO_INCREMENT column in MySQL.

This article explains how to create AUTOINCREMENT columns in SQLite.

Automatically Create an Auto-Increment Column

By default, when you define a column as INTEGER PRIMARY KEY, it will auto-increment whenever you insert NULL into that column.

Example:

CREATE TABLE Cats( 
    CatId INTEGER PRIMARY KEY, 
    CatName
);

In this table, the CatId column is an autoincrement column. This is because it has been defined using INTEGER PRIMARY KEY.

Now, when I insert NULL into that column, the CatId column auto-increments:

INSERT INTO Cats VALUES 
    ( NULL, 'Brush' ),
    ( NULL, 'Scarcat' ),
    ( NULL, 'Flutter' );

SELECT * FROM Cats;

Result:

CatId       CatName   
----------  ----------
1           Brush     
2           Scarcat   
3           Flutter   

It’s important to note that you can override the AUTOINCREMENT value by inserting your own value. In other words, AUTOINCREMENT only inserts a value if you don’t.

The way it works is, the NULL is automatically converted into an integer which is one greater than the largest value of that column over all other rows in the table. If the table is empty, the value will be 1.

If the largest value of the column is the largest possible integer (9223372036854775807), then SQLite will choose an unused key at random. This typically means that it will reuse old keys that were previously deleted. If an unused key can’t be found, the INSERT operation fails with an SQLITE_FULL error.

Basically what this means is, if you allow DELETE operations in the table, then there’s no guarantee that all rows will be in order. There’s a possibility that some rows will have a higher value than rows inserted at a later date.

Therefore, in such cases, you can’t rely on this column if you need to order the table in ascending or descending order, based on the order of which the rows were inserted.

Fortunately, if this is a problem for you, there is a solution: The AUTOINCREMENT keyword.

Use the AUTOINCREMENT Keyword

Alternatively, you can choose to explicitly set the column to auto-increment by using the AUTOINCREMENT keyword.

One benefit of using this method is that it guarantees that all rows will be in ascending order. This is because it doesn’t reuse previously deleted keys. Each key will always be one more than the largest key that has ever existed in that table. If the largest possible key has previously existed in that table, then it won’t try to use previously deleted keys. The INSERT will fail with an SQLITE_FULL error code.

The downside of using the AUTOINCREMENT keyword is that it uses extra CPU, memory, disk space, and disk I/O overhead.

Here’s an example of creating an auto-incrementing column with the AUTOINCREMENT keyword:

CREATE TABLE Dogs( 
    DogId INTEGER PRIMARY KEY AUTOINCREMENT, 
    DogName
);

Now insert data and select it:

INSERT INTO Dogs VALUES 
    ( NULL, 'Yelp' ),
    ( NULL, 'Woofer' ),
    ( NULL, 'Fluff' );

SELECT * FROM Dogs;

Result:

DogId       DogName   
----------  ----------
1           Yelp      
2           Woofer    
3           Fluff     

If I were to delete Fluff from this table, then insert a new row (using NULL as the DogId), the new DogId would be 4. In other words, it would not reuse 3.

If the column had been created without the AUTOINCREMENT keyword, then the next row would reuse the DogId of 3.

If I were to insert a DogId of 9223372036854775807 (the largest possible integer), I would receive the following error upon the next insert that specifies NULL for that column:

Error: database or disk is full

However, I could explicitly insert a value that is lower than 9223372036854775807, as long as that value isn’t already being used by another row, and the INSERT operation should succeed without the above error.

Basically, once you reach 9223372036854775807, the auto-increment will no longer work.

Columns defined without the AUTOINCREMENT keyword don’t have this issue. They will automatically go back and try to find an unused integer to use instead. However, if all integers have been used (i.e. the table actually contains 9223372036854775807 rows), then even those columns will result in the above error.