Search code examples
arrayspostgresqlsql-insertbulkinsertjsonb

Insert unique values from array of objects in postgres


I have been trying to input an array of unique codes into postgres from an array of objects. This is what I have so far but it keeps on failing near INTO. I have tried a loop version before but it never ended up insert anything but would not create an error either. The below would be ideal, bulk-inserting without the need for any FOR loops.

CREATE OR REPLACE FUNCTION "InsertCodes" (
  "@codes"                  JSONB,
  "@type"                   TEXT
)
RETURNS void AS
$func$
DECLARE "id"                UUID;
BEGIN
  "id" = uuid_generate_v4();
  SELECT * FROM (
    SELECT *
    FROM jsonb_array_elements("@codes")
  ) AS c (
-- fails below
    INSERT INTO
      "codes" (
        "id",
        "code",
        "name",
        "type"
      )
    VALUES (
      "id",
      c."code",
      c."name",
      "@type"
    );
    ON CONSTRAINT ("code")
    DO NOTHING
    RETURNING 1;
  );
END;
$func$ LANGUAGE PLPGSQL;

@codes looks like the below:

[
  {
    "code": 1234,
    "name": "numeric"
  },
  {
    "code": "1k1l2k",
    "name": "alphanumeric"
  }
]

Solution

  • The query should look like this:

    "id" = uuid_generate_v4();
    INSERT INTO "codes" ("id", "code", "name", "type")
    SELECT "id", item->>'code', item->>'name', "@type"
    FROM jsonb_array_elements("@codes") AS item
    ON CONFLICT ("code") DO NOTHING;
    

    Note that the same "id" will be inserted for all codes passed as jsonb array. If it is a primary key you should rather generate the "id" for each code separately:

    INSERT INTO "codes" ("id", "code", "name", "type")
    SELECT uuid_generate_v4(), item->>'code', item->>'name', "@type"
    FROM jsonb_array_elements("@codes") AS item
    ON CONFLICT ("code") DO NOTHING;