Вы, вероятно, не хотите делать это вообще, так как последовательности без пробелов проблематичны для производительности .
Если вы хотите сделать это в качестве шага очистки позже, вы можете использовать rank()
оконная функция для достижения желаемого эффекта.
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;
Результат:
regress=# select * from table1 ;
id
----
1
2
3
4
(4 rows)
Если ваши ФК не ON UPDATE CASCADE
, вы можете ALTER TABLE
сделать их так.Это будет довольно медленно, особенно если на внешних ключах нет индексов.Более быстрый подход состоит в том, чтобы выполнить изменение в два прохода:
- Начать транзакцию
LOCK TABLE table1;
- Добавить столбец new_id в table1 и заполнить егоновые идентификаторы, использующие
row_number()
, как показано выше - Удаление ограничений внешнего ключа, ссылающихся на table1 (id)
- Обновление всех внешних ключей для ссылки на значения в
new_id
- drop
id
в table1 - переименовать столбец
new_id
таблицы1 в id
- заново создать ограничения внешнего ключа
- commit