Project: YugabyteDB (App Definition and Development / Database)
File: ddl_truncate.md

title: TRUNCATE headerTitle: TRUNCATE linkTitle: TRUNCATE description: Use the TRUNCATE statement to remove all rows from one or several tables. menu: v2.18: identifier: ddl_truncate parent: statements type: docs Use the `TRUNCATE` statement to remove all rows from the specified table or, optionally, to remove all rows from all the tables in the closure with foreign key references to the specified table. Applying `TRUNCATE` to a set of tables produces the same ultimate outcome as does using an unrestricted `DELETE` on each table in the set; but it doesn't scan the tables. `TRUNCATE` is therefore faster than `DELETE`. It also reclaims disk space immediately. This means that the larger is the table, the more greater the performance benefit of `TRUNCATE` is. {{%ebnf%}} truncate {{%/ebnf%}} {{< note title="Table inheritance is not yet supported" >}} The rule specifies syntax that is useful only when at least one other table inherits one of the tables that the `truncate` statement lists explicitly. See for more detail. Until inheritance is supported, use a bare . {{< /note >}} {{< note title="Truncate is not transactional" >}} `TRUNCATE` in the current implementation is not transactional. You should avoid using TRUNCATE in the following circumstances: inside of a multi-step transaction concurrently with read and write operations in the same table If your use case is mostly for CI/CD on smaller datasets, you can use `DELETE FROM table;`. This is heavier weight (and also not recommended for very large data sets) but will be transactional. Note that even in PostgreSQL truncate is not . {{< /note >}} Specify the name of the table to be truncated. `TRUNCATE` acquires `ACCESS EXCLUSIVE` lock on the tables to be truncated. The `ACCESS EXCLUSIVE` locking option is not yet fully supported. `TRUNCATE` is not supported for foreign tables. `CASCADE` and `RESTRICT` affect what happens when the table that the `TRUNCATE` statement targets has dependent tables. A dependent table (and, in turn, its dependent tables) have that status because they have direct or transitive foreign key constrains to the target table. `CASCADE` causes the closure of dependent tables all to be truncated. And `RESTRICT` causes the `TRUNCATE` attempt to fail if the target table has any dependent tables. This error outcome is the same even when all of the tables are empty. If neither `CASCADE` nor `RESTRICT` is written, then the effect is as if `RESTRICT` had been

First create a parent-child table pair and populate them: ```plpgsql drop table if exists children cascade; drop table if exists parents cascade; create table parents(k int primary key, v text not null); create table children( parent_k int not null, k int not null, v text not null, constraint childrenpk primary key(parentk, k), constraint childrenfk foreign key(parentk) references parents(k) match full on delete cascade on update restrict); insert into parents(k, v) values (1, 'dog'), (2, 'cat'), (3, 'frog'); insert into children(parent_k, k, v) values (1, 1, 'dog-child-a'), (1, 2, 'dog-child-b'), (1, 3, 'dog-child-c'), (2, 1, 'cat-child-a'), (2, 2, 'cat-child-b'), (2, 3, 'cat-child-c'), (3, 1, 'frog-child-a'), (3, 2, 'frog-child-b'), (3, 3, 'frog-child-c'); select p.v as "parents.v", c.v as "children.v" from parents p inner join children c on c.parent_k = p.k order by p.k, c.k; ``` This is the result: ```output parents.v | children.v --+-- dog | dog-child-a dog | dog-child-b dog | dog-child-c cat | cat-child-a cat | cat-child-b cat | cat-child-c frog | frog-child-a frog | frog-child-b frog | frog-child-c ``` The `\d children` meta-command shows that it has a foreign key constraint to the `parents` table. This makes it a (transitive) dependent object of that table: ```output Indexes: "childrenpk" PRIMARY KEY, lsm (parentk HASH, k ASC) Foreign-key constraints: "childrenfk" FOREIGN KEY (parentk) REFERENCES parents(k) MATCH FULL ON UPDATE RESTRICT ON DELETE CASCADE ``` Notice that the effect of the `on delete cascade` clause is limited to what the `delete` statement does. It has no effect on the behavior of `truncate`. (There is no `on truncate cascade` clause.) Try `delete from parents`. It quietly succeeds and removes all the rows from both the `parents` table and the `children` table. With all the rows that the setup code above inserts, try this: ```plpgsql do $body$ declare message text not null := ''; detail text not null := ''; begin -- Causes error 'cos "cascade" is required. truncate table parents; assert false, 'Should not get here'; exception -- Error 0A000 when featurenotsupported then get stacked diagnostics message = message_text, detail = pgexceptiondetail; assert message = 'cannot truncate a table referenced in a foreign key constraint', 'Bad message'; assert detail = 'Table "children" references "parents".', 'Bad detail'; end; $body$; ``` It finishes without error, showing that the bare `truncate table parents`, without `cascade`, fails and causes the message and hint that the code presents. Now repeat the attempt with `cascade` and observe the result: ```plpgsql truncate table parents cascade; select (select count(*) from parents) as "parents count", (select count(*) from children) as "children count"; ``` The `truncate` statement now finishes without error. This is the result: ``` parents count | children count +- 0 | 0 ``` Finally, try `truncate table parents` again. As promised, it still fails with the 0A000 error, even though the transitively dependent table, children, is empty.