如何在 PostgreSQL 中的现有表中添加自增主键?
我有一个包含现有数据的 PostgreSQL 表。
如何在不删除并重新创建表的情况下添加自增主键?
I have a PostgreSQL table with existing data.
How do I add an auto-incrementing primary key without deleting and re-creating the table?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
PostgreSQL v10+ 的版本
假设您有一个表
table_name
,您想要向其中添加一个自动递增的主键id
(代理)列。 推荐的方法是使用形式GENERATED { ALWAYS |默认} AS IDENTITY [(sequence_options)]
。例如(ref)
或
旧版本的 PostgreSQL
不建议这样做但自 PostgreSQL v16 起继续受支持。
注意:旧的
SERIAL
形式已替换为GENERATED ... AS IDENTITY
在 PostgreSQL v10 中,因为SERIAL
可能会导致问题,例如允许意外覆盖该值以及需要更多授权才能允许插入(PostgreSQL:串行与身份)。使用以下形式:
在内部,此
SERIAL
未保留,它在解析时扩展为SEQUENCE
和SET DEFAULT nextval({sequence_name})< /code> (更详细的讨论),让您免于显式地键入旧版本中所需的内容,如下所述:
甚至旧版本的 PostgreSQL
在旧版本的 PostgreSQL(8.x 之前?)中,您必须完成所有脏工作:
Versions of PostgreSQL v10+
Suppose you have a table
table_name
, to which you want to add an auto-incrementing, primary-keyid
(surrogate) column. The recommended way is using the formGENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
.e.g. (ref)
or
Older versions of PostgreSQL
This is not recommended but continues to be supported as of PostgreSQL v16.
Note: The older
SERIAL
form was replaced withGENERATED ... AS IDENTITY
in PostgreSQL v10 becauseSERIAL
could cause problems, such as allowing an accidental override of the value and requiring more grants to allow inserts (PostgreSQL: serial vs identity).The following form was used:
Internally this
SERIAL
is not preserved, it is expanded at parse time into aSEQUENCE
and aSET DEFAULT nextval({sequence_name})
(more detailed discussion), saving you from explicitly typing those as was required in older versions, as outlined here:Even Older Versions of PostgreSQL
In old versions of PostgreSQL (prior to 8.x?) you had to do all the dirty work:
您需要做的就是:
id
列感谢 @resnyanskiy,他在评论中给出了这个答案。
This is all you need to:
id
columnCredit is given to @resnyanskiy who gave this answer in a comment.
要在 v10 中使用标识列,
有关标识列的说明,请参阅 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/。
To use an identity column in v10,
For an explanation of identity columns, see https://blog.2ndquadrant.com/postgresql-10-identity-columns/.
For the difference between GENERATED BY DEFAULT and GENERATED ALWAYS, see https://www.cybertec-postgresql.com/en/sequences-gains-and-pitfalls/.
For altering the sequence, see https://popsql.io/learn-sql/postgresql/how-to-alter-sequence-in-postgresql/.
我来到这里是因为我也在寻找类似的东西。就我而言,我将数据从一组具有许多列的临时表复制到一个表中,同时还将行 ID 分配给目标表。这是我使用的上述方法的变体。
我在目标表的末尾添加了序列列。这样我就不必在 Insert 语句中为其添加占位符。然后简单的 select * into 目标表自动填充此列。这是我在 PostgreSQL 9.6.4 上使用的两条 SQL 语句。
I landed here because I was looking for something like that too. In my case, I was copying the data from a set of staging tables with many columns into one table while also assigning row ids to the target table. Here is a variant of the above approaches that I used.
I added the serial column at the end of my target table. That way I don't have to have a placeholder for it in the Insert statement. Then a simple select * into the target table auto populated this column. Here are the two SQL statements that I used on PostgreSQL 9.6.4.
我知道已经过去很多年了,但这可能会对其他用户有所帮助。
尝试使用第一个查询:
第二个查询更新当前值:
其中“Users” - 表,“UserID” - 主键
I understand it's been a lot of years, but this may help other users.
Try to use first query:
second query for update current value:
where "Users" - table, "UserID" - primary key
我有 Postgres 15.4
例如
1 - 添加
GENERATED IDENTITY
2 - 设置
MAX(id)
的序列值,如果没有记录,则设置1
读取:
GENERATED
BY DEFAULT
和ALWAYS
序列I have Postgres 15.4
For example
1 - Add
GENERATED IDENTITY
2 - Set sequence value of
MAX(id)
or1
if there is no recordRead about:
GENERATED
BY DEFAULT
andALWAYS
ALTER TABLE test1 ADD id int8 NOT NULL GENERATED ALWAYS AS IDENTITY;
ALTER TABLE test1 ADD id int8 NOT NULL GENERATED ALWAYS AS IDENTITY;