I tried to do the following:
CREATE TABLE test_table
(
column_1 varchar(255),
column_2 varchar(255),
combined varchar(255) DEFAULT concat(column_1, '_', column_2)
);
It produces the following error:
ERROR: cannot use column reference in DEFAULT expression
This similar question uses an update query for the entire table: Insert value into a column in PostgreSQL
I would like to know if there is a way to do this as part of the insert?
With the following as an example of input and expected output:
insert into test_table ('column_1', 'column_2')
values ('Alpha', 'Beta')
select * from test_table;
('Alpha', 'Beta', 'Alpha_Beta')
Notes:
- Inputs are always strings
- They will likely always be under 20 characters
- I can't create a because I don't know how to create the table
Conclusion The answers by @JoeStefanelli and @Charlieface both answer the question with the original intention in mind of having a third column with the composite value. I think that the answer by @jarlh may actually be more optimal though? By using the view the duplicate information is not stored in the database. Also in my case I know that the inputs will never be null or empty, I did not think to include that in the initial question though as I was focused on the combined value solution.
GENERATED ALWAYS Solutions:
VIEW Solution:
I tried to do the following:
CREATE TABLE test_table
(
column_1 varchar(255),
column_2 varchar(255),
combined varchar(255) DEFAULT concat(column_1, '_', column_2)
);
It produces the following error:
ERROR: cannot use column reference in DEFAULT expression
This similar question uses an update query for the entire table: Insert value into a column in PostgreSQL
I would like to know if there is a way to do this as part of the insert?
With the following as an example of input and expected output:
insert into test_table ('column_1', 'column_2')
values ('Alpha', 'Beta')
select * from test_table;
('Alpha', 'Beta', 'Alpha_Beta')
Notes:
- Inputs are always strings
- They will likely always be under 20 characters
- I can't create a https://dbfiddle.uk/HuZKDYgb because I don't know how to create the table
Conclusion The answers by @JoeStefanelli and @Charlieface both answer the question with the original intention in mind of having a third column with the composite value. I think that the answer by @jarlh may actually be more optimal though? By using the view the duplicate information is not stored in the database. Also in my case I know that the inputs will never be null or empty, I did not think to include that in the initial question though as I was focused on the combined value solution.
GENERATED ALWAYS Solutions:
- https://stackoverflow/a/79413015/14179793
- https://stackoverflow/a/79413372/14179793
VIEW Solution:
- https://stackoverflow/a/79412921/14179793
3 Answers
Reset to default 5You can create a VIEW
that combines the columns:
CREATE TABLE test_base_table (
column_1 varchar(255),
column_2 varchar(255)
);
create view test_table
as select column_1, column_2, column_1 || '_' || column_2 as combined
from test_base_table;
insert into test_table (column_1, column_2) values ('Alpha', 'Beta');
select * from test_table;
column_1 column_2 combined
======== ======== ==========
Alpha Beta Alpha_Beta
Demo: https://dbfiddle.uk/VohrDmeq
You want to define that combined
column as a generated column. NOTE: The CONCAT function is not immutable, so you have to roll your own with a CASE statement for the generated column.
CREATE TABLE test_table
(
column_1 varchar(255),
column_2 varchar(255),
combined varchar(255) GENERATED ALWAYS AS
(CASE WHEN column_1 IS NULL THEN column_2
WHEN column_2 IS NULL THEN column_1
ELSE column_1 || '_' || column_2 END) STORED
);
You can use concat_ws
to simplify the expression, as it deals with nulls and inserts a separator only when necessary.
Unfortunately it's only marked as SAFE
not IMMUTABLE
so it wouldn't be allowed in a STORED
column. But we can create an IMMUTABLE
alias for it. Do not use any other data types apart from text
, as there may be unstable conversions involved.
CREATE OR REPLACE FUNCTION immutable_concat_ws(text, VARIADIC text[])
RETURNS text
LANGUAGE internal IMMUTABLE PARALLEL SAFE AS
'text_concat_ws';
Then
CREATE TABLE test_table
(
column_1 varchar(255),
column_2 varchar(255),
combined varchar(511) GENERATED ALWAYS AS (
immutable_concat_ws('_', column_1, column_2)
) STORED
);
db<>fiddle
GENERATED ALWAYS AS ( generation_expr ) STORED |
. This works in all currently supported Postgres versions 13+. – Adrian Klaver Commented Feb 4 at 19:51GENERATED
column work – Charlieface Commented Feb 4 at 19:51insert into test_table (column_1, column_2, combined) values ('Alpha', 'Beta', 'different')
to insert? – jarlh Commented Feb 4 at 19:55