I create table in PostgreSQL but I forgot to add auto increment.
How to alter empty Id column in Postgres to add auto increment?
Starting with Postgres 10 it's recommended to use identity columns for this.
You can turn an existing column into an identity column using an ALTER TABLE:
alter table the_table
alter id add generated always as identity;
If you already have data in the table, you will need to sync the sequence:
select setval(pg_get_serial_sequence('the_table', 'id'), (select max(id) from the_table));
You will need to create a sequence owned by that column and set that as the default value.
e.g.
CREATE TABLE mytable (id int);
CREATE SEQUENCE mytable_id_seq OWNED BY mytable.id;
ALTER TABLE mytable ALTER COLUMN id SET DEFAULT nextval('mytable_id_seq');
Related
I hit the int limit on a large table I use.
The table is in single user mode and has no FK constraints.
CREATE TABLE my_table_bigint (LIKE my_table INCLUDING ALL);
ALTER TABLE my_table_bigint ALTER id DROP DEFAULT;
ALTER TABLE my_table_bigint alter column id set data type bigint;
CREATE SEQUENCE my_table_bigint_id_seq;
INSERT INTO my_table_bigint SELECT * FROM my_table;
ALTER TABLE my_table_bigint ALTER id SET DEFAULT nextval('my_table_bigint_id_seq');
ALTER SEQUENCE my_table_bigint_id_seq OWNED BY my_table_bigint.id;
SELECT setval('my_table_bigint_id_seq', (SELECT max(id) FROM my_table_bigint), true);
At this point I tested that I could insert new rows without any problems. Success, I thought.
I went about renaming the tables.
alter table my_table rename my_table_old
alter table my_table_bigint rename my_table
ALTER INDEX post_comments_pkey RENAME TO post_comments_old_pkey
ALTER INDEX post_comments_pkey_bigint RENAME TO post_comments_pkey
Now, when I checked the schema.... the table ID type had changed BACK to integer, instead of bigint.
Copying took about 3 days - so I am really, really hoping that I don't need to do this again. This is postgres10 on RDS.
EDIT
I'm going to take care of this problem like this:
Create a new table - call it my_table_bigint2.
Do this:
CREATE TABLE my_table_bigint2 (LIKE my_table INCLUDING ALL);
ALTER TABLE my_table_bigint2 ALTER id DROP DEFAULT;
ALTER TABLE my_table_bigint2 alter column id set data type bigint;
CREATE SEQUENCE my_table_bigint2_id_seq;
ALTER TABLE my_table_bigint2 ALTER id SET DEFAULT nextval('my_table_bigint2_id_seq');
ALTER SEQUENCE my_table_bigint2_id_seq OWNED BY my_table_bigint2.id;
And start populating that table with the new data. (This is fine given the usecase.)
In the meantime, I'm going to run
ALTER TABLE post_comments alter column id set data type bigint;
And finally, once that's done, I'm going to
INSERT INTO my_table SELECT * FROM my_table_bigint2;
My follow-up question - is this allowed? Will this create some interaction between the sequences? Should I use a new sequence?
I would like to changes my existing column as Auto Identity in a Postgres Database.
I tried with below script but it won't worked.
Let me know if you have solution for the same
I don't want to use postgres SEQUENCE. I would like to use GENERATED ALWAYS AS IDENTITY.
ALTER TABLE public.patient ALTER COLUMN patientid Type int4
USING patientid::int4 GENERATED ALWAYS AS IDENTITY;
Following the documentation
ALTER TABLE patient
ALTER patientid SET NOT NULL, -- optional
ALTER patientid ADD GENERATED ALWAYS AS IDENTITY
(START WITH 2); -- optional
Add NOT NULL constraint if the column does not have the constraint yet. The optional clause START WITH start changes the recorded start value of the sequence.
Test it in DB<>Fiddle.
Suppose you have a table patient previously created as
CREATE TABLE patient( patientid int, col1 int );
and a row inserted as
INSERT INTO patient VALUES(1,5);
Firstly create a sequence starting +1 iterated from the max value of ID and make it default for your column
CREATE SEQUENCE mySeq START WITH 2;
ALTER TABLE patient ALTER COLUMN patientid SET DEFAULT nextval('mySeq');
and convert your column to a primary key
ALTER TABLE patient ALTER COLUMN patientid SET NOT NULL;
ALTER TABLE patient ADD CONSTRAINT uk_patientid UNIQUE (patientid);
whenever you insert new rows such as
INSERT INTO patient(col1) VALUES(10);
INSERT INTO patient(col1) VALUES(15);
you'll observe that you sucessfully made your column as an identity column
SELECT * FROM patient
patientid col1
--------- ----
1 5
2 10
3 15
I would like to changes my existing column as Auto Identity in a Postgres Database.
I used below script to set auto identity column and set default start with 1.
But here i would like to reset identity column value to table's last value.
Let me know if you have any solutions.
ALTER TABLE patient
ALTER patientid SET NOT NULL,
ALTER patientid ADD GENERATED ALWAYS AS IDENTITY (START WITH 1);
Here I'm setting up something like this:
ALTER TABLE Patient
ALTER COLUMN PatientId RESTART WITH (select Max(patientId) + 1 from patient);
An identity columns is also backed by a sequence, and pg_get_serial_sequence() will return that sequence name. That can be used together with setval().
After running the add generated always part you can adjust the sequence using this statement:
SELECT setval(pg_get_serial_sequence('patient', 'patientid'),
(select max(patientid) from patient));
Consider the following table with approximately 10M rows
CREATE TABLE user
(
id bigint NOT NULL,
...
CONSTRAINT user_pk PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
)
Then i applied the following alter
ALTER TABLE USER ADD COLUMN BUSINESS_ID VARCHAR2(50);
--OK
UPDATE USER SET BUSINESS_ID = ID; //~1500 sec
--OK
ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET NOT NULL;
ERROR: column "business_id" contains null values
SQL state: 23502
This is very strange since id column (which has been copied to business_id column) can't contain null values since it is the primary key, but to be sure i check it
select count(*) from USER where BUSINESS_ID is null
--0 records
I suspect that this is a bug, just wondering if i am missing something trivial
The only logical explanation would be a concurrent INSERT.
(Using tbl instead of the reserved word user as table name.)
ALTER TABLE tbl ADD COLUMN BUSINESS_ID VARCHAR2(50);
--OK
UPDATE tbl SET BUSINESS_ID = ID; //~1500 sec
--OK
-- concurrent INSERT HERE !!!
ALTER TABLE tbl ALTER COLUMN BUSINESS_ID SET NOT NULL;</code></pre>
To prevent this, use instead:
ALTER TABLE tbl
ADD COLUMN BUSINESS_ID VARCHAR(50) DEFAULT ''; -- or whatever is appropriate
...
You may end up with a default value in some rows. You might want to check.
Or run everything as transaction block:
BEGIN;
-- LOCK tbl; -- not needed
ALTER ...
UPDATE ...
ALTER ...
COMMIT;
You might take an exclusive lock to be sure, but ALTER TABLE .. ADD COLUMN takes an ACCESS EXCLUSIVE lock anyway. (Which is only released at the end of the transaction, like all locks.)
Maybe it wants a default value? Postgresql docs on ALTER:
To add a column, use a command like this:
ALTER TABLE products ADD COLUMN description text;
The new column is initially filled with whatever default value is given (null if you don't specify a DEFAULT clause).
So,
ALTER TABLE USER ALTER COLUMN BUSINESS_ID SET DEFAULT="",
ALTER COLUMN BUSINESS_ID SET NOT NULL;
You cannot do that at the same transaction. Add your column and update it. Then in a separate transaction set the not null constraint.
How do I add multiple columns in one query statement in PostgreSQL using pgadmin3?
Try this :
ALTER TABLE table ADD COLUMN col1 int, ADD COLUMN col2 int;
Use ALTER TABLE with ADD COLUMN subcommand.
ALTER TABLE:
This changes the definition of an existing table using a subcommand, for example: ADD COLUMN.
ADD COLUMN [ IF NOT EXISTS ]:
This form adds a new column to the table, using the same syntax as CREATE TABLE. If IF NOT EXISTS is specified and a column already exists with this name, no error is thrown.
Adding a Column
The most basic syntax is:
ALTER TABLE table_name
ADD COLUMN new_column_name data_type constraint;
In this syntax:
First, specify the name of the table that you want to add a new column to after the ALTER TABLE keyword.
Second, specify the name of the new column as well as its data type and constraint after the ADD COLUMN keywords.
Adding a Column using IF NOT EXIST clause
ALTER TABLE table_name
ADD COLUMN IF NOT EXISTS new_column_name data_type constraint;
This option gives PostgreSQL instructions to add the new column only in case the column name does not already exist in the table. If it does, you will receive a corresponding response; otherwise, it will create one.
ALTER TABLE IF EXISTS TABLEname
add ADD COLUMN IF NOT EXISTS column_name data_type [column_constraint];
detailed query where column_constraints are optional