intro
Let’s dive into the PostgreSQL truncate table reset sequence issue and how to clear the values of sequences when clearing table data!
Truncating a table does not completely reset it. Specifically, the Postgres TRUNCATE
command does not affect the values of table sequences. To reset the sequences, you need to follow a specific PostgreSQL truncate table reset sequence approach. Follow this article to learn how to do it!
What Is a PostgreSQL Sequence?
As covered in our blog post, a sequence is essentially a database object that generates numbers. Postgres uses sequences to produce a series of progressive numbers, which is typically used in auto-incremental numeric primary keys.
For those familiar with MySQL, sequences in PostgreSQL function similarly to the AUTO_INCREMENT
behavior. However, a key distinction is that PostgreSQL sequences can be configured to start from a specified value and decrement with each INSERT
, if desired. In contrast, AUTO_INCREMENT
in MySQL only increments the value automatically by one unit.
You can create a sequence in PostgreSQL using the CREATE SEQUENCE
statement. Alternatively, the special data type SERIAL
sets up an auto-incrementing numeric primary key by employing a sequence under the hood. Find out more in your guide on PostgreSQL data types.
The Effect of TRUNCATE on Sequences
In most cases, a TRUNCATE
command for a single table looks like this:
1
TRUNCATE table_name;
Or, if you are truncating multiple tables at once, it may appear as follows:
1
TRUNCATE table_1, table_2;
But do not forget that the PostgreSQL TRUNCATE
command offers additional options. Here is its complete syntax:
1
TRUNCATE [ TABLE ] [ ONLY ] table_1 [, ..., table_n]
2
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
CASCADE
truncates all tables that have foreign-key references to any of the specified tables or any tables included through CASCADE
. Instead, RESTRICT
prevents truncation if any of the specified tables have foreign-key references from tables not included in the command. RESTRICT
is the default behavior.
For this article, what matters are the [RESTART IDENTITY | CONTINUE IDENTITY
] options:
So, consider this query:
1
TRUNCATE table_name;
When you launch it, PostgreSQL is actually running:
1
TRUNCATE table_name CONTINUE IDENTITY RESTRICT;
Thus, Postgres executes the TRUNCATE
command without modifying the sequence values by default. Let’s confirm this behavior with an example.
Example
Suppose you have a products
table that contains the following data:

As you can see in a visual PostgreSQL database client like DbVisualizer, the table only contains 8 products.
Also, take a look at its SQL DDL definition:

Note how the column id
is of type SERIAL
, which means it is associated with a sequence. Thanks to DbVisualizer Pro, you can explore a table DDL with a single click.
Now, launch the TRUNCATE
query:
1
TRUNCATE products;
The table will now be empty:

Add a new product with the following INSERT
query:
1
INSERT INTO products (name, description, price) VALUES ('Noise-Cancelling Headphones', 'Over-ear headphones with active noise cancellation and 30-hour battery life.', 249.99);
Since TRUNCATE
did not reset the id
sequence, the new product will have 9 (the next number) as its ID. Verify that with a simple SELECT *
query:
1
SELECT * FROM products;
The result will be:

Notice how the id
column has value 9
. Behavior confirmed!
PostgreSQL Truncate Table Reset Sequence Instructions
As it should now be clear, the PostgreSQL truncate table reset sequence trick is to specify the RESTART IDENTITY
option in the TRUNCATE
query:
1
TRUNCATE table_name RESTART IDENTITY;
Let’s verify that it works!
Example
Suppose you are dealing again with a populated products
table:

Now, execute the PostgreSQL TRUNCATE
query to reset the sequence:
1
TRUNCATE products RESTART IDENTITY;
Next, insert a new product:
1
INSERT INTO products (name, description, price) VALUES ('Noise-Cancelling Headphones', 'Over-ear headphones with active noise cancellation and 30-hour battery life.', 249.99);
This time, the new product will have an id
of 1
, as the sequence has been reset:

Et voilà! You have just learned how to truncate a table and reset sequences in PostgreSQL!
Conclusion
In this guide, you learned what a PostgreSQL sequence is and why the TRUNCATE
command does not reset it by default. You then explored a simple yet effective PostgreSQL truncate table reset sequence approach.
As shown here, DbVisualizer greatly simplifies query execution, data exploration, and table definition discovery. This full-featured visual database client supports various DBMS technologies and offers advanced capabilities such as query optimization, SQL formatting, and ERD-like schema generation. Try DbVisualizer for free today!
FAQ
How do you truncate tables and reset sequences in PostgreSQL?
By default, the TRUNCATE
command in PostgreSQL does not reset the values of sequences. To modify this behavior, you can use the command with the following syntax:
1
TRUNCATE table_name RESTART IDENTITY;
The RESTART IDENTITY
option instructs PostgreSQL to reset the sequences associated with the columns of the truncated table.
What are some scenarios where PostgreSQL can go out of sync?
The main reasons a PostgreSQL sequence can go out of sync are:
How do you fix sequences that went out of sync in PostgreSQL?
To fix all out-of-sync sequences, run the following query:
1
SELECT 'SELECT SETVAL(' ||
2
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
3
', COALESCE(MAX(' || quote_ident(C.attname) || '), 1)) FROM ' ||
4
quote_ident(PGT.schemaname) || '.' || quote_ident(T.relname) || ';'
5
FROM pg_class AS S
6
JOIN pg_depend AS D ON S.oid = D.objid
7
JOIN pg_class AS T ON D.refobjid = T.oid
8
JOIN pg_attribute AS C ON D.refobjid = C.attrelid AND D.refobjsubid = C.attnum
9
JOIN pg_tables AS PGT ON T.relname = PGT.tablename
10
WHERE S.relkind = 'S'
11
ORDER BY S.relname;
This query generates the necessary SETVAL
commands to update all sequences based on the maximum values of the corresponding columns. Learn more about how to fix a sequence when it goes out of sync in PostgreSQL.
How can you retain sequence values after a TRUNCATE instruction in PostgreSQL?
By default, TRUNCATE
retains the current values of sequences. To explicitly enforce that behavior, you need to use the CONTINUE IDENTITY
option:
1
TRUNCATE table_name CONTINUE IDENTITY;
This ensures that sequences associated with the truncated table(s) are not reset.
Why should you use a database client?
Using an SQL client like DbVisualizer allows you to visually deal with data in your databases. A powerful SQL client provides a range of tools that simplify data management and analysis, no matter which database management system you are using. These features enhance productivity, streamline workflows, and help you gain insights from your data more effectively.