I have a database where everything is linked with foreign keys, so the Postgres knows exactly how the database is layed out..
Well, Lets say I have Table1 and Table2.>
You probably don't want to do this generally, as gapless sequences are problematic for performance.
If you want to do it as a cleanup step later you can use the rank()
window function to achieve the desired effect.
CREATE TABLE table1 (id integer primary key);
INSERT INTO table1 values (1),(2),(4),(5);
CREATE TABLE table2 (
id serial primary key,
rid integer references table1(id) ON UPDATE CASCADE
);
insert into table2 (rid) values (1),(1),(4),(4),(4),(5);
UPDATE table1
SET id = gapless_id
FROM (
SELECT *, row_number() OVER () FROM table1
) AS x(old_id, gapless_id)
WHERE id = x.old_id;
Result:
regress=# select * from table1 ;
id
----
1
2
3
4
(4 rows)
If your FK's aren't ON UPDATE CASCADE
you can ALTER TABLE
to make them so. This will be quite slow though, especially if there are no indexes on the foreign keys. A faster approach is to do the change in two passes:
LOCK TABLE table1;
row_number()
as shown abovenew_id
id
in table1new_id
column of table1 to id