如何在PostgreSQL中设置自动递增主键?


259

我在PostgreSQL中有一个具有22列的表,并且我想添加一个自动增量主键。

我试图创建一个名为idBIGSERIAL类型的列,但是pgadmin响应了一个错误:

ERROR: sequence must have same owner as table it is linked to.

有人知道如何解决此问题吗?如何在PostgreSQL中添加创建自动递增主键而又不重新创建表的方法?

Answers:


292

试试这个命令:

ALTER TABLE your_table ADD COLUMN key_column BIGSERIAL PRIMARY KEY;

请使用与创建表相同的数据库用户来尝试。


75
(此处的关键是使用SERIAL或BIGSERIAL数据类型,该数据类型在幕后创建一个序列,并在插入时递增/使用它)
rogerdpack 2014年

16
如果要从另一个表引用它,请使用整数或bigint
Ward

2
@satishkilari:是的,语法为ALTER TABLE mytable ADD PRIMARY KEY (column);。Postgresql将检查该列是否不包含NULL。
AH

3
在pgAdmin 4中得到此错误。bigserialserial都给出相同的错误:ERROR: syntax error at or near "BIGSERIAL"
adi 2016年

5
还使用bigserial或serial获得语法错误。是否为此有一个最低的PostgreSQL版本?
dacDave

251

在PostgreSQL中自动递增主键:

步骤1,建立表格:

CREATE TABLE epictable
(
    mytable_key    serial primary key,
    moobars        VARCHAR(40) not null,
    foobars        DATE
);

第2步,像这样将值插入表中,请注意,第一个参数列表中未指定mytable_key,这将导致默认序列自动递增。

insert into epictable(moobars,foobars) values('delicious moobars','2012-05-01')
insert into epictable(moobars,foobars) values('worldwide interblag','2012-05-02')

步骤3,从表格中选择*:

el@voyager$ psql -U pgadmin -d kurz_prod -c "select * from epictable"

步骤4,解释输出:

mytable_key  |        moobars        |  foobars   
-------------+-----------------------+------------
           1 | delicious moobars     | 2012-05-01
           2 | world wide interblags | 2012-05-02
(2 rows)

观察到mytable_key列已自动增加。

专家提示:

您应该始终在表上使用主键,因为Postgresql在内部使用哈希表结构来提高插入,删除,更新和选择的速度。如果主键列(强制为唯一且非null)可用,则可以依赖它来为哈希函数提供唯一的种子。如果没有主键列可用,则哈希函数会因为选择其他一组列作为键而变得效率低下。


21
A小调挑剔,SERIAL确实建立了sequence:幕后postgresql.org/docs/9.2/static/...
碳正离子

1
是否有可能在不添加任何新列的情况下在表中创建主键(现有列)
satish kilari '16

声明的外键可以thing_id int references epictable(mytable_key)工作吗?

36

使用自定义序列在postgresql中创建一个自动递增的主键:

第1步,创建序列:

create sequence splog_adfarm_seq
    start 1
    increment 1
    NO MAXVALUE
    CACHE 1;
ALTER TABLE fact_stock_data_detail_seq
OWNER TO pgadmin;

步骤2,建立表格

CREATE TABLE splog_adfarm
(
    splog_key    INT unique not null,
    splog_value  VARCHAR(100) not null
);

步骤3,插入表格

insert into splog_adfarm values (
    nextval('splog_adfarm_seq'), 
    'Is your family tree a directed acyclic graph?'
);

insert into splog_adfarm values (
    nextval('splog_adfarm_seq'), 
    'Will the smart cookies catch the crumb?  Find out now!'
);

步骤4,观察行

el@defiant ~ $ psql -U pgadmin -d kurz_prod -c "select * from splog_adfarm"

splog_key |                            splog_value                             
----------+--------------------------------------------------------------------
        1 | Is your family tree a directed acyclic graph?
        2 | Will the smart cookies catch the crumb?  Find out now!
(3 rows)

两行的键从1开始,并按顺序定义递增1。

奖励精英ProTip:

程序员讨厌打字,而讨厌打字nextval('splog_adfarm_seq')。您可以DEFAULT改为输入该参数,如下所示:

insert into splog_adfarm values (
    DEFAULT, 
    'Sufficient intelligence to outwit a thimble.'
);

为了使以上方法起作用,您必须为splog_adfarm表上的该键列定义默认值。哪个更漂亮。


2
自定义序列的好处是什么?可能是安全性吗?
莱奥波德·赫兹(LéoLéopoldHertz)2015年

1
@Masi自定义序列的一种用法是使主-主复制更容易-如果两个数据中心之间的数据链接断开,这将很有用-允许在两个具有不同ID的服务器上创建记录然后可以轻松同步数据库备份,同时将生成的ID保留在单独的位置。
Vincent McNabb

16

如果要在pgadmin中执行此操作,则要容易得多。在postgressql中,似乎要向列添加自动递增,我们首先需要创建一个自动递增序列并将其添加到所需的列。我确实喜欢这样。

1)首先,您需要确保您的表有一个主键。还要将主键的数据类型保留在bigint或smallint中。(我使用bigint,找不到其他答案中提到的名为serial的数据类型)

2)然后通过右键单击sequence-> add new sequence添加一个序列。如果表中没有数据,请保持顺序不变,不要进行任何更改。只需保存即可。如果存在现有数据,则将“主键”列中的最后一个或最大值添加到“定义”选项卡中的“当前值”,如下所示。 在此处输入图片说明

3)最后,将行添加nextval('your_sequence_name'::regclass)到主键中的默认值,如下所示。

在此处输入图片说明 确保此处的序列名称正确。这就是全部,并且自动递增应该起作用。


9

如果要在序列中使用数字,请使用以下内容定义一个新序列

CREATE SEQUENCE public.your_sequence
    INCREMENT 1
    START 1
    MINVALUE 1
;

然后更改表以使用ID的顺序:

ALTER TABLE ONLY table ALTER COLUMN id SET DEFAULT nextval('your_sequence'::regclass);

我必须为每个表创建一个新序列吗?
巴拉特·查布拉

您可以为不同的表共享相同的序列,但是对于每个表中的每个记录,该序列都会增加。
acaruci

1

我尝试了以下脚本来成功自动增加PostgreSQL中的主键。

CREATE SEQUENCE dummy_id_seq
    START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;

CREATE table dummyTable (
    id bigint DEFAULT nextval('dummy_id_seq'::regclass) NOT NULL,
    name character varying(50)
);

编辑:

CREATE table dummyTable (
    id SERIAL NOT NULL,
    name character varying(50)
)

SERIAL关键字自动为各个列创建一个序列。


您是否可以像对SEQUENCE一样重置SERIAL?
thoroc

1
是的,我已经检查了ALTER SEQUENCE dummytable_id_seq RESTART WITH 1;它的工作原理。
Asad Shakeel

0

也许我回答这个问题有点晚了,但是我正在工作这个问题:)

我想写一列'a_code'= c1,c2,c3,c4 ...

首先,我用名称ref_id和类型打开一列serial。然后我用以下命令解决了我的问题:

update myschema.mytable set a_code=cast('c'||"ref_id" as text) 

是否有可能在不添加任何新列的情况下在表中创建主键(现有列)
satish kilari '16
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.