【问题标题】:How to alter PostgreSQL column with entries to be a nextval id如何将带有条目的 PostgreSQL 列更改为 nextval id
【发布时间】:2020-11-04 14:03:31
【问题描述】:

我对一个非常大的数据库有以下问题:

id | date | other columns...

id 列来自integer 类型。如果它来自具有nextval 约束的integer 类型,那将是理想的。许多id 条目在添加时都有唯一的id

问题是添加的所有行,因为特定的 date 没有 id 并且值为 null

是否可以将此类约束添加到具有现有值(加上null 值)的表中,以便用integer id 填充null 值?

这是否可能在不丢失旧的id 的情况下以及在最好的情况下相对于日期列按升序排列?

感谢和问候

【问题讨论】:

标签: sql postgresql


【解决方案1】:

您需要先使用唯一的非空值更新现有行:

update the_table
  set id = new_id
from (
  select ctid, 
         (select max(id) from the_table)  + row_number() over (order by date) as new_id
  from the_table
  where id is null
) t
where t.ctid = the_table.ctid;

我不确定使用这种方法是否能保证 ID 的顺序,但很可能确实如此。

现在,该列不包含任何 NULL 值,我们可以更改它自动分配新值。

接下来的步骤取决于您是想将其设为identity 列,还是仅将其设为具有序列默认值的列(本质上是 (discouraged) serial 列)

留在“连续剧”

我们需要创建一个序列并将其与列中的最大值同步。

create sequence the_table_id_seq;
select setval('the_table_id_seq', max(id))
from the_table;

然后将其用作默认值并将序列链接到列。

alter table the_table
  alter id set not null,
  alter id set default nextval('the_table_id_seq') ;
  
alter sequence the_table_id_seq owned by the_table.id;

使用identity 列(推荐)

要使其成为正确的(推荐)identity 列(Postgres 10 及更高版本),您可以这样做:

alter table the_table
  alter id set not null,
  alter id add generated always as identity;

现在添加身份属性创建了一个新序列,我们需要与列中的现有值同步:

select setval(pg_get_serial_sequence('the_table', 'id'), max(id))
from the_table;

或者,您可以手动查找当前最大值并在指定 identity 默认值时直接提供:

alter table the_table
  alter id set not null,
  alter id add generated always as identity (start with 42);

【讨论】:

  • 非常感谢,这正是我想要的。
猜你喜欢
  • 2021-10-10
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 2022-10-07
  • 2021-10-08
  • 2011-01-12
  • 2010-12-15
  • 1970-01-01
相关资源
最近更新 更多