将自动增量列添加到按日期排序的现有表中

Posted

技术标签:

【中文标题】将自动增量列添加到按日期排序的现有表中【英文标题】:Add auto increment column to existing table ordered by date 【发布时间】:2019-04-21 13:02:55 【问题描述】:

我在数据库中有一个名为“tickets”的现有表,其中包含列:

id (string, Primary Key, contains UUID like e6c49164-545a-43a1-845f-73c5163962f2) 
date   (biginteger, stores epoch)
status (string)

我需要添加新的自动增量列ticket_id,但要生成的值应该根据“日期”列值。

我试过这个:

ALTER TABLE "tickets" ADD COLUMN "ticket_id" SERIAL;

问题是,它以某种奇怪的顺序生成“ticket_id”值,看起来它是基于作为表主键的“id”列。

是否可以生成按“日期”排序的序列值?这很重要,因为“ticket_id”需要根据票的生成顺序显示。

【问题讨论】:

您可以考虑创建一个新表并使用INSERT INTO newtable SELECT ctid, ... FROM tickets WHERE ... ORDER BY date 插入正确的值吗? 不相关,但是:为什么要使用 bigint 作为时间戳?在 SQL 中处理一个真正的 timestamp 列会容易得多。 【参考方案1】:

如果您添加这样的序列列,现有行将自动以“任意”顺序更新。

要控制生成 ID 的顺序,您需要分多个步骤执行此操作:

首先添加列没有默认值(serial 表示默认值)

ALTER TABLE tickets ADD COLUMN ticket_id integer;

然后创建一个序列来生成值:

create sequence tickets_ticket_id_seq;

然后更新现有的行

update tickets 
  set ticket_id = t.new_id
from (
   select id, nextval('tickets_ticket_id_seq') as new_id
   from tickets
   order by "date"
) t
where t.id = tickets.id;

然后将序列设为新列的默认值

alter table tickets alter column ticket_id set default nextval('tickets_ticket_id_seq');

最后,将序列与列关联(这也是serial 在后台所做的):

alter sequence tickets_ticket_id_seq owned by tickets.ticket_id;

如果表真的很大(“数十”或“数亿”),那么创建新表可能会更快:

create sequence tickets_ticket_id_seq;
create table tickets_new
as
select id, nextval('activities_ticket_id_seq') ticket_id, "date", status
from tickets
order by "date";

drop table tickets cascade;
alter table tickets_new rename to tickets;
alter table tickets add primary key (id);
alter sequence tickets_ticket_id_seq owned by tickets.ticket_id;

然后为该表重新创建所有外键和索引。

【讨论】:

很好的答案,您能否将“活动”更新为“门票”,这是我的错误,非常感谢。

以上是关于将自动增量列添加到按日期排序的现有表中的主要内容,如果未能解决你的问题,请参考以下文章

将自动增量列添加到现有表中,而无需扩展和重新导入

Oracle中如何将自动增量添加到现有表中

向oracle中的现有表添加自动增量主键[重复]

使用增量索引重命名目录中的文件

SQL 最佳实践 - 可以依靠自动增量字段按时间顺序对行进行排序吗?

如何将自动增量 ID 列添加到从 SQL 查询生成的表中? [复制]