简体   繁体   English

如何将条目更改为 nextval id 的 PostgreSQL 列

[英]How to alter PostgreSQL column with entries to be a nextval id

I have a problem with a really big database with following scheme:我有一个非常大的数据库有以下方案的问题:

id | date | other columns...

The id column is from type integer . id列来自integer类型。 It would be ideal if it where from type integer with a nextval constraint.如果它来自具有nextval约束的integer类型,那将是理想的。 Many of the id entries have unique id 's incremented when they where added.许多id条目在添加时都有唯一的id递增。

The problem is all rows added since a specific date have no id and the value is null .问题是自特定date以来添加的所有行都没有id并且值为null

Is it possible to add such constraints to tables with existing values (plus null values) so that the null values are filled with integer id 's?是否可以将此类约束添加到具有现有值(加上null值)的表中,以便用integer id填充null值?

And is this possible without losing the old id 's and in the best case with ascending order in relation to the date column?这可能不会丢失旧的id并且在最好的情况下与日期列相关的升序?

thanks and greetings谢谢和问候

You need to first update the existing rows with a unique, non-null value:您需要首先使用唯一的非空值更新现有行:

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;

I am not sure if the order of the IDs is guaranteed using this approach, but it's likely that it does.我不确定使用这种方法是否可以保证 ID 的顺序,但很可能是这样。

Now, that the column doesn't contain any NULL values, we can either change it automatically assign new values.现在,该列不包含任何 NULL 值,我们可以更改它自动分配新值。

The next steps depend on whether you want to make this an identity column or simply a column with a default from a sequence (essentially a ( discouraged ) serial column)接下来的步骤取决于您是要将此列作为identity列还是只是具有序列默认值的列(本质上是( 不鼓励的serial列)

Staying with a "serial"留在“连续剧”

We need to create a sequence and sync it with the highest value in the column.我们需要创建一个序列并将其与列中的最高值同步。

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

Then use this for the default and link the sequence to the column.然后将其用作默认值并将序列链接到列。

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;

Using an identity column (recommended)使用identity列(推荐)

To make this a proper (recommended) identity column (Postgres 10 and later) you can do it like this:要使其成为适当的(推荐的) identity列(Postgres 10 及更高版本),您可以这样做:

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

Now adding the identity attribute created a new sequence which we need to sync with the existing values in the column:现在添加身份属性创建了一个新序列,我们需要与列中的现有值同步:

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

Alternatively, you could have manually looked up the current max value and provide that directly when specifying the identity default:或者,您可以手动查找当前最大值并在指定identity默认值时直接提供该值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM