317

I have a table in PostgreSQL with many columns, and I want to add an auto increment primary key.

I tried to create a column called id of type BIGSERIAL but pgadmin responded with an error:

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

Does anyone know how to fix this issue? How do I add or create an auto-incrementing primary key in PostgreSQL without recreating the table?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
mkn
  • 12,024
  • 17
  • 49
  • 62

10 Answers10

358

Try this command:

ALTER TABLE your_table ADD COLUMN key_column BIGSERIAL PRIMARY KEY;

Try it with the same DB-user as the one you have created the table.

A.H.
  • 63,967
  • 15
  • 92
  • 126
  • 83
    (the key here is to use a SERIAL or BIGSERIAL data type, which creates a sequence behind the scenes and increments/uses it at insert time) – rogerdpack Apr 30 '14 at 13:53
  • 19
    and if you want to reference it from another table, use integer, or bigint – Ward May 18 '14 at 21:38
  • is it possible to make primary key(existing column) in a table without adding any new column – satish kilari Aug 03 '16 at 13:32
  • 2
    @satishkilari: yes, the syntax is `ALTER TABLE mytable ADD PRIMARY KEY (column);` . Postgresql will check that the column contains no NULLs. – A.H. Aug 05 '16 at 20:08
  • 3
    Getting this error in pgAdmin 4. Both `bigserial` and `serial` are giving the same error: `ERROR: syntax error at or near "BIGSERIAL"` – Adil Oct 30 '16 at 10:59
  • 5
    Also getting the syntax error using bigserial or serial. Is there a minimum postgresql verison for this? – dacDave Dec 21 '16 at 01:21
  • 1
    6 years later still getting use :) – Harry Oct 27 '17 at 01:40
  • there is one major problem with this, insert into x on conflict DO NOTHING still increments the serial, though there is a way to reset the max, I would prefer an increment type that does not increment the serial until the insert was successful – PirateApp Mar 01 '19 at 07:41
  • 2
    @PirateApp: The canonical answer to your issue is: A gapless counter cannot be used in concurrent transactions. You would force the DB to serialize the writes to the table hampering performance significantly. Therefore most DBs (and Postgres) default to non-gapless counters. – A.H. Mar 01 '19 at 18:00
  • @A.H. interesting...so when you do insert and if your insert fails , do you have to reset the sequence, are you aware of some technique to do that :) – PirateApp Mar 02 '19 at 03:01
  • 1
    @PirateApp: You can search for `postgresql gapless sequence`. For example you will stumble over https://dba.stackexchange.com/questions/119784/how-can-i-create-a-gapless-sequence and https://wiki.postgresql.org/wiki/FAQ#Why_are_there_gaps_in_the_numbering_of_my_sequence.2FSERIAL_column.3F_Why_aren.27t_my_sequence_numbers_reused_on_transaction_abort.3F – A.H. Mar 06 '19 at 22:54
315

Auto incrementing primary key in postgresql:

Create your table:

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

Insert values into your table:

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

select * from your table:

select * from epictable

mytable_key  |        moobars        |  foobars   
-------------+-----------------------+------------
           1 | delicious moobar      | 2012-05-01
           2 | WorldWideBlag         | 2012-05-02
(2 rows)

Observe that mytable_key column has been auto incremented.

ProTips:

You should always be using a primary key on your table because postgresql internally uses hash table structures to increase the speed of inserts, deletes, updates and selects. If a primary key column (which is forced unique and non-null) is available, it can be depended on to provide a unique seed for the hash function. If no primary key column is available, the hash function becomes inefficient as it selects some other set of columns as a key.

If you want more control over the behavior of the serial key, then see postgresql sequences.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • 24
    A minor nitpick, `SERIAL` does create a `sequence` behind the scenes: http://www.postgresql.org/docs/9.2/static/datatype-numeric.html#DATATYPE-SERIAL – carbocation Mar 17 '13 at 19:37
  • 1
    is it possible to make primary key(existing column) in a table without adding any new column – satish kilari Aug 03 '16 at 13:33
  • @satishkilari Yes, you can in-place add, modify and delete primary keys. https://docs.actian.com/psql/psqlv13/index.html#page/sqlref/sqlref.PRIMARY_KEY.htm But it's easier to 1. create a new table with the correct layout, 2. copy the data over, 3. finally delete the old table and rename the new table to the old tablename. – Eric Leschinski Jun 14 '22 at 14:51
  • @EricLeschinski I tried using COPY to add the data like this, but apparently that breaks the auto increment part of the table. Any suggestions how to do again or fix the ID column to start auto incrementing again? – gwhiz Oct 02 '22 at 17:36
44

Create an auto incrementing primary key in postgresql, using a custom sequence:

Step 1, create your sequence:

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

Step 2, create your table

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

Step 3, insert into your table

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!'
);

Step 4, observe the rows

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)

The two rows have keys that start at 1 and are incremented by 1, as defined by the sequence.

Bonus Elite ProTip:

Programmers hate typing, and typing out the nextval('splog_adfarm_seq') is annoying. You can type DEFAULT for that parameter instead, like this:

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

For the above to work, you have to define a default value for that key column on splog_adfarm table. Which is prettier.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • 2
    What are the benefits of custom sequences? Probably, security? – Léo Léopold Hertz 준영 Jul 03 '15 at 19:53
  • 2
    @Masi One use of a custom sequence could be to make it easier to do master-master replication - which would be useful if the data link between two data-centers is broken - allowing records to be created on both servers with different IDs, which then makes it easy to synch the databases back up while keeping the ids generated in the separate locations. – Vincent McNabb Sep 15 '15 at 04:46
23

serial is the old way to auto generate unique values and it is not part of the SQL standard.

After PostgreSQL 10, you can use generated as identity, it is compliant with SQL standard:

CREATE TABLE t1 (id integer primary key generated always as identity);

or

CREATE TABLE t1 (id integer primary key generated by default as identity); 

The difference between by default and always:

  • The GENERATED ALWAYS instructs PostgreSQL to always generate a value for the identity column. If you attempt to insert (or update) values into the GENERATED ALWAYS AS IDENTITY column, PostgreSQL will issue an error.
  • The GENERATED BY DEFAULT also instructs PostgreSQL to generate a value for the identity column. However, if you supply a value for insert or update, PostgreSQL will use that value to insert into the identity column instead of using the system-generated value.

For more information.

MM.
  • 2,653
  • 4
  • 26
  • 36
Ismail
  • 2,322
  • 1
  • 12
  • 26
22

If you want to do this in pgadmin, it is much easier. It seems in postgressql, to add a auto increment to a column, we first need to create a auto increment sequence and add it to the required column. I did like this.

1) Firstly you need to make sure there is a primary key for your table. Also keep the data type of the primary key in bigint or smallint. (I used bigint, could not find a datatype called serial as mentioned in other answers elsewhere)

2)Then add a sequence by right clicking on sequence-> add new sequence. If there is no data in the table, leave the sequence as it is, don't make any changes. Just save it. If there is existing data, add the last or highest value in the primary key column to the Current value in Definitions tab as shown below. enter image description here

3)Finally, add the line nextval('your_sequence_name'::regclass) to the Default value in your primary key as shown below.

enter image description here Make sure the sequence name is correct here. This is all and auto increment should work.

toing_toing
  • 2,334
  • 1
  • 37
  • 79
17

If you want to use numbers in a sequence, define a new sequence with something like

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

and then alter the table to use the sequence for the id:

ALTER TABLE ONLY table ALTER COLUMN id SET DEFAULT nextval('your_sequence'::regclass);
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
acaruci
  • 879
  • 9
  • 14
4

I have tried the following script to successfully auto-increment the primary key in 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)
);

EDIT:

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

SERIAL keyword automatically create a sequence for respective column.

Asad Shakeel
  • 1,949
  • 1
  • 23
  • 29
3

Steps to do it on PgAdmin:

  • CREATE SEQUENCE sequnence_title START 1; // if table exist last id
  • Add this sequense to the primary key, table - properties - columns - column_id(primary key) edit - Constraints - Add nextval('sequnence_title'::regclass) to the field default.
Baskovli
  • 530
  • 5
  • 13
0

Maybe I'm a bit of late to answer this question, but I'm working on this subject at my job :)

I wanted to write column 'a_code' = c1,c2,c3,c4...

Firstly I opened a column with the name ref_id and the type serial. Then I solved my problem with this command:

update myschema.mytable set a_code=cast('c'||"ref_id" as text) 
elias
  • 15,010
  • 4
  • 40
  • 65
0

You can use below code for auto increment

Create table public.EmployeeDapper
(
    Id int not null generated by default as identity(increment by 1 start 1 
    minvalue 1 maxvalue 2147483647 cache 1),

    Name varchar(50) not null,
    Age int not null,
    Position varchar(50)not null
)