可以压缩主键/序列号?

时间:2010-02-19 19:02:28

标签: postgresql foreign-keys primary-key auto-increment maintenance

我有一个数据库,其中所有内容都与外键相关联,因此Postgres确切知道数据库是如何布局的。

好吧,我们说我有Table1和Table2。

表1有3个字段。 RID,table2_rid,数据

因此table1.table2_rid引用table2.RID,这用外键表示。在RID字段中都是主键,并且是串行类型。

我想知道的是如何“压缩”主键?比如说你添加5条记录并删除了3号记录。你的主键看起来像是

1
2
4
5 

那么,如何在任何地方进行更新,以便将主键(和相应的外键)压缩到

1
2
3
4

4 个答案:

答案 0 :(得分:2)

最好是主键永远不会改变:重新编号是PITA。

如果你需要一个人类身份证,一个没有差距的人,A。Elein Mustain会显示how to create a gapless sequence

答案 1 :(得分:1)

查看on update cascadeon 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)
);

答案 2 :(得分:1)

除了非常罕见的情况,PK序列中的差距恰到好处,意图摆脱它们是一个坏主意。

答案 3 :(得分: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;
  • 向table1添加new_id列,并使用row_number()使用新ID填充它,如上所示
  • 删除引用table1(id)
  • 的外键约束
  • 更新所有外键以引用new_id
  • 中的值
  • 在table1中删除id
  • 将table1的new_id列重命名为id
  • 重新创建外键约束
  • 提交