PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Postgres групова INSERT функция, използваща JSON аргументи

За хиляди записи

1. Създайте временна таблица с входни редове, съставена от вашите стойности $1 , $2 , $3 . Най-бързият начин за качване е COPY - или \copy мета-команда на psql ако данните не са на същата машина. Да предположим, че тази таблица:

CREATE TEMP TABLE tmp(id int PRIMARY KEY, val1 text, val2 text);

Добавих PK ограничение, което е напълно незадължително, но гарантира, че имаме работа с уникални ненулеви int стойности. Ако можете да гарантирате за входни данни, нямате нужда от ограничението.

2. Свържете вашите команди с модифициращи данни CTE. Както установихме във вашия предишен въпрос , няма условия за състезание, за които да се грижим в тази конкретна операция.

WITH ins1 AS (
   INSERT INTO table1 AS t1 (id, val1, val2)
   SELECT id, val1, val2 FROM tmp ON CONFLICT DO NOTHING
   RETURNING t1.id, t1.val1, t1.val2  -- only actually inserted rows returned
   )
, ins2 AS (
   INSERT INTO table2 (table1_id, val1)
   SELECT id, val1 FROM ins1
   )
UPDATE table3 t3
SET    val2 = i.val2
     , time = now()
FROM   ins1 i
WHERE  t3.table1_id = i.id;

Стъпка 1. и 2. трябва да се изпълняват в същата сесия (не непременно същата транзакция), тъй като обхватът на временните таблици е обвързан с една и съща сесия.

Обърнете внимание, че UPDATE зависи само от първия INSERT , успех на втория INSERT е гарантирано, тъй като няма ON CONFLICT DO NOTHING и цялата операция ще бъде върната назад, ако има някакъв конфликт във 2-рия INSERT .

Свързани:

Само за няколко записа

Има различни варианти как. Вашата идея да предадете JSON масив към функция е една от тях. Ако обектите съответстват на целевата таблица, можете да използвате json_populate_recordset() в един INSERT заявка. Или просто използвайте INSERT (като подготвен израз) без обвивка на функция.

INSERT INTO target_tbl  -- it's ok to omit target columns here
SELECT *
FROM   json_populate_recordset(null::target_tbl,  -- use same table type
          json '[{ "id": "1", "val1": "1-val1", "val2": "1-val2" },
                 { "id": "2", "val1": "2-val1", "val2": "2-val2" },
                 { "id": "3", "val1": "3-val1", "val2": "3-val2" },
                 { "id": "4", "val1": "4-val1", "val2": "4-val2" }]');

Само за няколко колони можете също да подадете масив за всяка колона и да преминете през тях паралелно. Можете да направите това с обикновен цикъл върху индекса на масива. От Postgres 9.4 има и удобния unnest() с множество параметри, за да направите всичко в една заявка:

Най-доброто решение зависи от формата на данните, който имате .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails 4 session.id от време на време нула

  2. Свържете приложението iPhone към PostgreSQL с помощта на Libpq

  3. Вложени транзакции в postgresql 8.2?

  4. django.db.utils.IntegrityError:дублираната стойност на ключ нарушава уникалното ограничение spirit_category_category_pkey

  5. Копирайте данни от таблица от една DB в друга