2

У меня есть база данных, где все связано с внешними ключами, поэтому Postgres точно знает, как выкладывается база данных.Возможна конденсация первичного ключа/серийного номера?

Ну, скажем, у меня есть таблица1 и таблица2.

Таблица 1 имеет 3 поля. RID, table2_rid, data

Так table1.table2_rid ссылается на таблицу2.RID, и это выражается внешним ключом. В поле RID используется первичный ключ и является серийным.

Что я хотел бы знать, так это как «конденсировать» первичные ключи? Как вы добавили 5 записей и удалил номер записи 3. Ваши первичные ключи будут выглядеть

1 
2 
4 
5 

Ну, как я могу получить обновления везде так, что первичный ключ (и соответствующие внешние ключи) может быть сжата в

1 
2 
3 
4 
+0

Важна держать все конденсируется? Если у вас 1000 записей в вашей базе данных, и вы удаляете запись 1, у вас есть как минимум 2 дополнительных обновления для запуска. – thetaiko

+0

Я больше говорю о том, что вы делаете на столе, в котором много вставок/удалений в день, и делайте это как ежемесячная задача обслуживания или что-то в этом роде. – Earlz

ответ

2

Лучше, если первичный ключ никогда не изменится: перенумеровать их является PITA.

Если вам нужен идентификатор для людей, у которого нет пробелов, A. Elein Mustain показывает how to create a gapless sequence.

+0

Ну, я думаю, впереди, потому что у нас есть таблица или две, которые, как правило, свертывают транзакции (которые увеличивают значение первичного ключа из-за того, как работает «serial»), и у него много вложений и обновлений, и я просто хотел бы знать если через год или два мы начнем сталкиваться с проблемой перевертывания с 32 бит, если будет способ борьбы с ним. – Earlz

+2

2^31 - одна вставка в секунду для * 68 лет *. Но если 32 бита могут быть недостаточными, то используйте serial8/bigserial вместо обычного последовательного интерфейса, и вы сможете делать 1000 вложений в секунду для 0.1 terrayears. –

1

Ознакомиться с on update cascade и on delete cascade.

create table table_1 (
    id integer 
     primary key, 
    name char(30) 
); 
create table table_2 (
    id integer 
     primary key, 
    table_1_id integer 
     references table_1 
     on update cascade 
     on delete cascade, 
    detail char(30) 
); 
1

За исключением очень редких сценариев, пробелы в последовательности PK являются правильными, а намерение избавиться от них - плохая идея.

1

Возможно, вы не хотите делать это вообще, как gapless sequences are problematic for performance.

Если вы хотите сделать это как шаг очистки позже, вы можете использовать функцию окна 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) 

Если FK не являются ON UPDATE CASCADE вы можете ALTER TABLE сделать их так. Это будет довольно медленным, особенно, если на внешних ключах нет индексов.Более быстрый подход, чтобы сделать изменения в два прохода:

  • Начните транзакцию
  • LOCK TABLE table1;
  • Добавить в new_id столбец table1 и заполнить его с новыми идентификаторами с использованием row_number(), как показано выше
  • Капля ограничения внешнего ключа со ссылкой на table1 (ID)
  • Обновить все внешние ключи для обозначения значений в new_id
  • капли id в табл e1
  • переименовать new_id столбец table1 в id
  • Пересоздайте внешнего ключа
  • совершают
Смежные вопросы