skip to Main Content

In my Postgres database I naively created a column in table Foos as a json[] that looks like this:

TABLE Foos

id | ... | baas
--------------------------------
1  | ... | [
   | ... |   {
   | ... |     "name": "a",
   | ... |     "property": "1",
   | ... |   },
   | ... |   {
   | ... |     "name": "b",
   | ... |     "property": "2",
   | ... |   },
   | ... |   ...
   | ... | ]
2  | ... | [ ... ]
3  | ... | [ ... ]

Now I want to populate table Baas with the items in my json array like this:

TABLE Baas

id | foo_id | name | property 
------------------------------
1  |      1 |    a |        1
2  |      1 |    b |        2 

How can I do this in simple SQL?

2

Answers


  1. Chosen as BEST ANSWER

    I solved it myself:

    INSERT INTO public.baas (foo_id, name, property)
    SELECT 
        foo_id,
        array_element ->> 'name',
        (array_element ->> 'property')::integer
    FROM (
        SELECT 
            id as foo_id, 
            unnest(baas) AS array_element
        FROM 
            public.foos
    ) AS subquery_alias;
    

  2. Use json_populate_record() or json_populate_recordset().
    Short, casts to target types implicitly, and fast.

    But get your setup and terminology straight!

    json[] is a Postgres array of json. While this is totally possible, it’s unlikely. Once you work with JSON, you would typically nest a JSON array in the plain Postgres type json.
    Depending on what you have exactly, setup and solution are subtly different:

    json[]: Postgres array of json

    (Less likely.)

    Setup

    CREATE TABLE foos (
      id int
    , baas json[]  -- type json[] - Postgres array of json (??)
    );
    
    INSERT INTO foos VALUES
      (1, '{"{"name": "a1", "property": "1"}"
           ,"{"name": "b1", "property": "2"}"}')    -- pg array with 2 json elements: JSON objects with two properites each
    , (2, '{"[{"name": "a2", "property": "1"}
             ,{"name": "b2", "property": "2"}]"}')  -- pg array with 1 json element: JSON array with 2 objects each, two properites each
    ;
    

    Wait, that syntax looks confusing! See:

    Queries

    One of these two:

    INSERT INTO baas (foo_id, name, property)
    SELECT f.id, b.name, b.property
    FROM   foos f, unnest(f.baas) a(baas), json_populate_record(null::baas, a.baas) b
    WHERE  f.id = 1;
    
    INSERT INTO baas (foo_id, name, property)
    SELECT f.id, b.name, b.property
    FROM   foos f, unnest(f.baas) a(baas), json_populate_recordset(null::baas, a.baas) b
    WHERE  f.id = 2;
    

    json: scalar type with nested JSON array

    (More likely.)

    Setup

    -- DROP TABLE IF EXISTS foos;
    CREATE TEMP TABLE foos (
      id int
    , baas json  -- type json (with nested JSON array)
    );
    
    INSERT INTO foos VALUES
      (3, '[{"name": "a", "property": "1"}
          , {"name": "b", "property": "2"}]')  -- 1 JSON array with 2 objects, each with 2 properties
    ;
    

    Query

    INSERT INTO baas (foo_id, name, property)
    SELECT f.id, b.name, b.property
    FROM   foos f, json_populate_recordset(null::baas, f.baas) b;
    

    fiddle

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search