0

I would like to have a generated column, which value will be the concated string from two other values:

 CREATE TABLE public.some_data (
    user_name varchar NULL,
    domain_name serial NOT NULL,

    email GENERATED ALWAYS AS (user_name ||'@'||domain_name) stored
 );

But that gives SQL Error [42601]: ERROR: syntax error at or near "ALWAYS"

2
  • You still have the declare the data type; Try email text GENERATED ALWAYS AS (user_name ||'@'||domain_name) stored Commented Aug 13, 2021 at 14:21
  • this produces an error dbfiddle.uk/… Commented Aug 13, 2021 at 14:55

3 Answers 3

1

You need to provide the data type for the column as @Belayer commented.

And then you need to explicitly cast domain_name as text (or some varchar). Otherwise you'll get an error that the expression isn't immutable as @nbk commented. serial is translated to be basically an integer and for whatever reason implicit casts of an integer in concatenations are considered not immutable by the engine. We had that just recently here.

So overall, using the given types for the columns, you want something like:

CREATE TABLE public.some_data
             (user_name varchar NULL,
              domain_name serial NOT NULL,
              email text GENERATED ALWAYS AS (user_name || '@' || domain_name::text) STORED);

But it's a little weird that a domain name is a serial? Shouldn't that be a text or similar? Then you wouldn't need the cast of course.

Sign up to request clarification or add additional context in comments.

Comments

0

You need to create an IMMUTABLE function to achieve the generate column, for example:

CREATE OR REPLACE FUNCTION generate_email_concat(varchar,int) returns text as 
$$
    select $1 ||'@'||$2::text;
$$
LANGUAGE SQL IMMUTABLE ;

CREATE TABLE public.some_data (
    user_name varchar NULL,
    domain_name serial NOT NULL,
    email text GENERATED ALWAYS AS (generate_email_concat(user_name,domain_name)) stored
 );

INSERT into some_data(user_name) values ('hello');

Comments

0

You try to concatenate varchar and integer. You have to cast domain_name. This works for me

CREATE TABLE public.some_data (
    user_name varchar NULL,
    domain_name serial NOT NULL,
    email varchar GENERATED ALWAYS AS (CASE WHEN user_name IS NULL THEN 'noname'||'@'||domain_name::text ELSE user_name ||'@'||domain_name::text END) STORED
 );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.