如何在PostgreSQL中向现有表添加自动递增的主键?


Answers:


354

(已更新-感谢发表评论的人

PostgreSQL的现代版本

假设您有一个名为的表test1,您想要向其中添加一个自动递增的主键id(代理)列。在最新版本的PostgreSQL中,以下命令应该足够了:

   ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

旧版本的PostgreSQL

在旧版本的PostgreSQL(8.x之前的版本?)中,您必须完成所有肮脏的工作。以下命令序列可以解决问题:

  ALTER TABLE test1 ADD COLUMN id INTEGER;
  CREATE SEQUENCE test_id_seq OWNED BY test1.id;
  ALTER TABLE test ALTER COLUMN id SET DEFAULT nextval('test_id_seq');
  UPDATE test1 SET id = nextval('test_id_seq');

同样,在最新版本的Postgres中,这大致等同于上面的单个命令。


3
我使用的是ORACLE,因此与ORACLE的人员共享可能非常有用。UPDATE TEST1 SET ID = TEST1_SEQ.NEXTVAL; ALTER TABLE TEST1添加主键(ID);在执行UPDATE语句之前创建一个序列TEST1_SEQ
msbyuva 2011年

请注意,这ADD PRIMARY KEY还会NOT NULL按照预期和需要创建约束(在postgres 9.3中进行了测试)。
Jared Beck

19
在Postgres中,您完全可以使用单个命令ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;
resnyanskiy 2015年

1
除了@resnyanskiy的注释,即使表中有数据,此操作也将起作用。填充ID,但未设置null约束。整个答案可以替换为该注释中的行。
Synesso,2015年

1
@EricWang谢谢,埃里克(Eric),您是对的-我认为这在几年前的某些版本中不起作用,但我不确定。答案变成了社区维基。
leonbloy

57
ALTER TABLE test1 ADD COLUMN id SERIAL PRIMARY KEY;

这就是您所需要的:

  1. 添加id
  2. 用从1到count(*)的序列填充它。
  3. 将其设置为主键/不为空。

感谢@resnyanskiy,他在评论中给出了此答案。


2
这应该标记为答案,答案应该属于@resnyanskiy
Eric Wang

我必须先放下pkey,然后再运行它。 ALTER TABLE <table> DROP CONSTRAINT <pkey_name>;
乔什·罗伯逊

10

要在v10中使用标识列,

ALTER TABLE test 
ADD COLUMN id { int | bigint | smallint}
GENERATED { BY DEFAULT | ALWAYS } AS IDENTITY PRIMARY KEY;

有关标识列的说明,请参见https://blog.2ndquadrant.com/postgresql-10-identity-columns/

有关GENERATED BY DEFAULT和GENERATED ALWAYS之间的区别,请参见https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/

有关更改顺序的信息,请参见https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/


该解决方案的问题在于,如果表已包含行,则会出现错误:SQL Error [23502]: ERROR: column "id" contains null values
isapir

3
@isapir:早期版本(第10和10.1版)中有一个错误会产生此错误。它已在第10.2页中修复。此处的详细信息:dba.stackexchange.com/q/200143/3684
Erwin Brandstetter

感谢@ erwin-brandstetter
isapir

一年后,我又找到了这个答案,错误已修复,已被驳回;)
isapir

2

我登陆这里是因为我也在寻找类似的东西。就我而言,我是将一组具有许多列的登台表中的数据复制到一个表中,同时还将行ID分配给目标表。这是我使用的上述方法的一种变体。我在目标表的末尾添加了序列列。这样,我就不必在Insert语句中为其使用占位符。然后将一个简单的select *插入目标表中,即可自动填充此列。这是我在PostgreSQL 9.6.4上使用的两条SQL语句。

ALTER TABLE target ADD COLUMN some_column SERIAL;
INSERT INTO target SELECT * from source;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.