Looks like you found a minor bug. I can recreate it in Postgres 9.6 and 10:
db<>fiddle here
In fact, it has been reported in Sept 2017. An attempt to fix has been rejected so far, since it would have introduced other oddities.
To circumvent, consider the advice in Laurenz' answer. Maybe automate with a DO
command like:
DO
$do$
BEGIN
IF NOT EXISTS (SELECT FROM pg_attribute
WHERE attrelid = 'public.tblname'::regclass -- table name here
AND attname = 'colname' -- column name here
AND NOT attisdropped
) THEN
ALTER TABLE public.tblname ADD COLUMN IF NOT EXISTS colname serial;
ELSE
RAISE NOTICE 'column "colname" of relation "public.tblname" already exists, skipping';
END IF;
END
$do$;
A race condition between check and creation is possible if more than one transaction can change the same table structure concurrently.
The generated notice is exactly what you'd get with IF NOT EXISTS
, too.
Wrap that into a plpgsql function with dynamic SQL taking parameters for repeated use with arbitrary table and column names.
Related:
Schema-qualify the table name to avoid ambiguity. Strings are case-insensitive here. You can't use the CaMeL-case spelling you have in your question. See: