5

I have the following tables Projects and ProjectFields. I am trying to populate one with values from another plus some other values, this way:

INSERT INTO "ProjectFields" ("projectId", name, type, "isDefault")
      (SELECT "projectId", 'Notes', 'textarea', true FROM "Projects"), -- creates one field called 'Notes' for every project.
      (SELECT "projectId", 'Bio', 'textarea', true FROM "Projects"), -- creates one field called 'Bio' for every project.
      (SELECT "projectId", 'Photo', 'text', true FROM "Projects"); -- creates one field called 'Photo' for every project.

The idea is that every project must have three referenced fields in the ProjectFields table. I know that the code above doesn't work, is there any way to do this using PostgreSQL ?

If you have a better idea please tell me, thank you.

1 Answer 1

6

You're almost there! Just use UNION and voilá:

INSERT INTO "ProjectFields" ("projectId", name, type, "isDefault")
      SELECT "projectId", 'Notes', 'textarea', true FROM "Projects"
        UNION ALL
      SELECT "projectId", 'Bio', 'textarea', true FROM "Projects"
        UNION ALL
      SELECT "projectId", 'Photo', 'text', true FROM "Projects";

--As you asked, using only one SELECT on Projects (but using a CTE)
--But I didn't recommend this solution, why increase complexity of a query just to avoid the 3 SELECTS?
INSERT INTO "ProjectFields" ("projectId", name, "isDefault")
    WITH tmp (proj_id, field_name, is_default) AS (     
        SELECT "projectId", UNNEST(ARRAY['Notes','Bio', 'Photo']), true FROM "Projects"
    )
    SELECT proj_id, field_name, CASE field_name WHEN 'Notes' THEN 'textarea' WHEN 'Bio' THEN 'textarea' ELSE 'text' END,is_default FROM tmp;

--Or perhaps in a more cleaner way as stated by @Marth:
INSERT INTO "ProjectFields" ("projectId", name, "isDefault")
    SELECT * FROM projects, (VALUES ('notes', 'textarea'), ('bio', 'textarea'), ('Photo', 'text')) AS t(name, "type");
Sign up to request clarification or add additional context in comments.

7 Comments

Is there a way to do only one select instead of three? thank you one more time @michel.milezzi.
Yes, but IMHO not worth it. See my updated answer. Regards!
@michel.milezzi: Your "1-SELECT" solution is a bit over-complicated, you could do select ... from project, (values ('notes', 'textarea'), ('bio', 'text')) as t(name, "type"). But yes, using UNION ALL is, I believe, the most common solution (and the easiest/most readable too).
@RafaelBerro: Purely out of curiosity, why are you looking for a "single select" way to do this?
@Marth you're right, I've updated my answer pointing it. Thanks
|

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.