I would like to add a generated column to a very large table without locking it:
alter table customer alter column foo text generated always as ((infos_json->'customerinfos'->>'redirect')) stored;
Is there a way to do this without locking? Maybe concurrently?
Related
Is there a method to do an ALTER COLUMN in postgres 12 on an huge table without waiting a lifetime?
I try to convert a field from bigint to smallint :
ALTER TABLE huge ALTER COLUMN result_code TYPE SMALLINT;
It takes 28 hours, is there a smarter method?
The table has sequences, keys and foreign keys
The table has to be rewritten, and you have to wait.
If you have several columns whose data type you want to change, you can use several ALTER COLUMN clauses in a single ALTER TABLE statement and save time that way.
An alternative idea would be to use logical replication: set up an empty copy of the database (pg_dump -s), where your large table is defined with smallint columns. Replicate your database to that database, and switch over as soon as replication has caught up.
In database dump created with pg_dump, some tables have DEFAULTs in the CREATE TABLE statement, i.e.:
CREATE TABLE test (
f1 integer DEFAULT nextval('test_f1_seq'::regclass) NOT NULL
);
But others have an additional ALTER statement:
ALTER TABLE ONLY test2 ALTER COLUMN f1 SET DEFAULT nextval('test2_f1_seq'::regclass);
What is the reason of this? All sequential fields were created with type SERIAL, but in the dump they look different, and I can't guess any rule for this.
The difference must be that in the first case, the sequence is “owned” by the table column.
You can specify this dependency using the OWNED BY clause when you create a sequence. A sequence that is owned by a column will automatically be dropped when the column is.
If a sequence is implicitly created by using serial, it will be owned by the column.
I am backing up my schema and stored procedures by running pg_dump -s database. This works, but it seems to show every change I've made (an ALTER for every time I've altered something, each new declaration of stored procedures I've changed over time, etc.)
I'd like just the current schema so that I can restore things should something go wrong. Is this possible?
TL/DR: This doesn't happen. pg_dump produces output that is optimized to make imports faster.
Are you sure about that? postgresql does not store at all the history of schema changes, so it would not be possible for pg_dump to output that. Here are some reasons that might have caused the confusion. Firstly, pg_dump typically breaks up create table statements into multiple statements. For example, consider this create table statement:
CREATE TABLE t (
id integer primary key,
q integer not null references q
);
pg_dump will convert it to
CREATE TABLE t (
id integer NOT NULL,
q integer NOT NULL
);
ALTER TABLE ONLY t
ADD CONSTRAINT t_pkey PRIMARY KEY (id);
ALTER TABLE ONLY t
ADD CONSTRAINT t_q_fkey FOREIGN KEY (q) REFERENCES q(id);
This is equivalent to the original one. Typically pg_dump creates statements for create table that in this order: (1) create the table without the constrains/indexes, (2) import the table data, and finally (3) create the constraints/indexes with alter table/create index. The reason that it does it in that order, is because it is faster to import the table data without indexes and create the indexes afterwards. But this doesn't mean that postgresql remembers the full history of changes to the table. If you add another column and call pg_dump afterwards, you will see the column in the resulting create table. Now, if you use the -s flag, this breaking up might be unnecessary but pg_dump does not change how it outputs the statements to create tables. It simply skips step (2) from above and it does steps (1) & (3).
Finally, the is another issue that might cause confusion. Function in postgresql can be overloaded by providing multiple definitions that have different types of arguments or different numbers of arguments. So if you do
CREATE OR REPLACE FUNCTION foo(x int) ...
and then later on you do
CREATE OR REPLACE FUNCTION foo(x text, y boolean) ...
then second statement will not delete the function created in the first one because the two functions are treated as different functions. So pg_dump will output them both. Again, this does not mean that postgresql remembers your old delete functions.
Assume I have a table named tracker with columns (issue_id,ingest_date,verb,priority)
I would like to add 50 columns to this table.
Columns being (string_ch_01,string_ch_02,.....,string_ch_50) of datatype varchar.
Is there any better way to add columns with single procedure rather than executing the following alter command 50 times?
ALTER TABLE tracker ADD COLUMN string_ch_01 varchar(1020);
Yes, a better way is to issue a single ALTER TABLE with all the columns at once:
ALTER TABLE tracker
ADD COLUMN string_ch_01 varchar(1020),
ADD COLUMN string_ch_02 varchar(1020),
...
ADD COLUMN string_ch_50 varchar(1020)
;
It's especially better when there are DEFAULT non-null clauses for the new columns, since each of them would rewrite the entire table, as opposed to rewriting it only once if they're grouped in a single ALTER TABLE.
My database has severals table with some column type 'money'. I would like to alter all these columns (in different tables) in a single statement rather than change type column by column, to avoid omissions.
You'll have to repeat the altering query for every column.
You might want to create a program code to do that for you. You know, with loops.
In order for the database to alter all the tables atomically you should enclose all the altering queries in a transaction (PostgreSQL supports transactional DDL).