I am trying to work out how an auto increment key is represented in Postgres, depending on whether you create it using the SERIAL type or using an IDENTITY.
When I create a table with a SERIAL primary key using this DDL:
CREATE TABLE public.test_change_column (
id SERIAL PRIMARY KEY NOT NULL
)
I get a sequence called ‘test_change_column_id_seq’ and gives the column id a default value of nextval('test_change_column_id_seq'::regclass)
If I create a table without SERIAL and a primary key using this DDL:
CREATE TABLE public.test_change_column (
id INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY,
)
The creates the sequence but the default value of id is not set to nextval(‘test_change_column_id_seq’::regclass). Instead the is_identity column is set to "YES".
If you create the column without an autoincrement, you cannot add it at a later stage using the SERIAL:
ALTER TABLE public.test_change_column ALTER COLUMN id TYPE serial;
this results in the error "type "serial" does not exist".
Using the IDENTITY method, you can add the auto increment using this DDL:
ALTER TABLE public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY;
This SQL will show how postgres stores the metadata for the 2 different methods:
SELECT column_name, column_default, is_identity
FROM information_schema.columns
WHERE table_name = 'test_change_column';
When it comes removing an auto increment, the auto increment is deleted differently depending on whether you used serial or identity.
If the auto increment was created using the serial type, you have to ALTER COLUMN id DROP DEFAULT. This does not delete the associated sequence table.
If the auto increment was created using IDENTITY, you have to ALTER COLUMN id DROP IDENTITY. This also removes the sequence table.
2
Answers
Changing the column to an identity column (and adding the PK constraint) is enough and the correct thing to do (the use of the
serial
pseudo type is discouraged)You can see that e.g.
psql
reports this correctly as an identity column:You can also verify that the default is working by inserting a row:
Will create a new row and will increment the
id
value.Such a column will be shown in
information_schema.columns
withis_identity = 'YES'
instead of having a default value.I recommend to use
generated always as identity
so that you can’t accidentally bypass the generation through the sequence (with the effect that the sequence and the values in the table are no longer "in sync").Create table.
Alter table in one line:
An
IDENTITY
column has a sequence associated with it that is used just like with aserial
column. It is just not shown as theDEFAULT
. To find underlying sequence:You can manipulate the above with the
IDENTITY
commands here ALTER TABLE:UPDATE
From here serial type:
So if you want to
ALTER
a table to replicate aserial
‘type’ you will need to do the individual steps above: