Difference between INT PRIMARY KEY and INTEGER PRIMARY KEY SQLite
INT PRIMARY KEY vs. INTEGER PRIMARY KEY in SQLite: A Deep Dive

Explore the subtle yet significant differences between INT PRIMARY KEY and INTEGER PRIMARY KEY in SQLite, focusing on their impact on rowid behavior and auto-increment functionality.
When defining primary keys in SQLite, you might encounter two seemingly similar syntaxes: INT PRIMARY KEY and INTEGER PRIMARY KEY. While both will successfully create a primary key, there's a crucial distinction that affects how SQLite manages the underlying rowid and auto-incrementing behavior. Understanding this difference is vital for efficient database design and avoiding unexpected issues, especially when dealing with auto-generated identifiers.
The Implicit ROWID and Primary Keys
SQLite is unique in that every table, by default, has a special 64-bit signed integer column called rowid. This rowid acts as a unique identifier for each row within the table. If you declare a column as PRIMARY KEY, SQLite will attempt to use that column as the rowid if certain conditions are met. This is where the difference between INT and INTEGER becomes apparent.
flowchart TD
A[Table Creation] --> B{Primary Key Defined?}
B -- Yes --> C{PK Type is INTEGER?}
C -- Yes --> D[PK becomes ROWID Alias]
C -- No (e.g., INT, TEXT) --> E[PK is separate column, ROWID still exists]
B -- No --> F[ROWID implicitly created]SQLite's ROWID assignment logic based on Primary Key type.
INT PRIMARY KEY: A Separate Column
When you declare a column as INT PRIMARY KEY, SQLite treats it as a regular column with a PRIMARY KEY constraint. It will enforce uniqueness and non-nullability, but it will not automatically alias this column to the internal rowid. Instead, the rowid will still exist as a separate, hidden column, and your INT PRIMARY KEY column will be distinct from it. This means SQLite will manage two separate unique identifiers for each row: your declared INT PRIMARY KEY and the internal rowid.
CREATE TABLE my_table_int (
id INT PRIMARY KEY,
name TEXT
);
INSERT INTO my_table_int (id, name) VALUES (1, 'Alice');
INSERT INTO my_table_int (id, name) VALUES (2, 'Bob');
-- You can still access rowid explicitly
SELECT id, name, rowid FROM my_table_int;
Example of a table with INT PRIMARY KEY.
INTEGER PRIMARY KEY: The ROWID Alias
The magic happens with INTEGER PRIMARY KEY. When a column is declared with the exact type INTEGER PRIMARY KEY (case-insensitive, so integer primary key also works), SQLite treats this column as an alias for the internal rowid. This means that your declared INTEGER PRIMARY KEY column is the rowid. There isn't a separate rowid column; instead, any reference to your INTEGER PRIMARY KEY column is effectively a reference to the rowid.
CREATE TABLE my_table_integer (
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO my_table_integer (name) VALUES ('Charlie'); -- id is auto-assigned by rowid
INSERT INTO my_table_integer (name) VALUES ('David');
-- id and rowid will be the same value
SELECT id, name, rowid FROM my_table_integer;
Example of a table with INTEGER PRIMARY KEY.
INTEGER PRIMARY KEY syntax is what enables SQLite's built-in auto-incrementing behavior by default. If you omit a value for an INTEGER PRIMARY KEY column, SQLite automatically assigns the next available rowid value, which is typically one greater than the largest rowid currently in use.AUTOINCREMENT Keyword and Performance
While INTEGER PRIMARY KEY provides auto-incrementing behavior by default, the AUTOINCREMENT keyword adds an extra layer of guarantee. When AUTOINCREMENT is used with INTEGER PRIMARY KEY, SQLite ensures that rowid values are always strictly increasing and never reused, even after deletions. This comes with a slight performance overhead, as SQLite must maintain a separate table to track the largest rowid ever used. For most applications, INTEGER PRIMARY KEY without AUTOINCREMENT is sufficient and more performant.
CREATE TABLE my_table_autoincrement (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data TEXT
);
INSERT INTO my_table_autoincrement (data) VALUES ('Item A');
INSERT INTO my_table_autoincrement (data) VALUES ('Item B');
DELETE FROM my_table_autoincrement WHERE id = 1;
INSERT INTO my_table_autoincrement (data) VALUES ('Item C');
-- id values will be 2, 3 (1 is not reused)
SELECT id, data FROM my_table_autoincrement;
Using AUTOINCREMENT to prevent rowid reuse.
AUTOINCREMENT if you have a strict requirement for non-reused rowid values, such as when external systems rely on them remaining unique over the lifetime of the database. For most cases, INTEGER PRIMARY KEY alone is sufficient and offers better performance.Summary of Differences
The choice between INT PRIMARY KEY and INTEGER PRIMARY KEY boils down to whether you want your primary key to be an alias for SQLite's internal rowid or a completely separate column. The INTEGER PRIMARY KEY approach is generally preferred for simple auto-incrementing integer primary keys due to its efficiency and direct mapping to rowid.

Key differences between INT PRIMARY KEY and INTEGER PRIMARY KEY.