PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Łączenie instrukcji INSERT w modyfikującym dane CTE z wyrażeniem CASE

Nie możesz zagnieździć INSERT instrukcje w CASE wyrażenie. Wychodząc z tego, co widzę, to zupełnie inne podejście powinno wystarczyć:

Założenia

  • W rzeczywistości nie potrzebujesz zewnętrznego SELECT .

  • dm_name / rm_name są zdefiniowane unikatowo w dm / rm i nie puste (<> '' ). Powinieneś mieć CHECK ograniczenie, aby się upewnić.

  • Domyślna kolumna dla obu d_id i r_id w z są NULL (domyślne).

dm_name i rm_name wzajemnie wykluczające się

Jeśli oba nie są obecne w tym samym czasie.

WITH d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm.dm_id 
   FROM   import
   JOIN   dm USING (dm_name)
   RETURNING d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm.rm_id 
   FROM   import
   JOIN   rm USING (rm_name)
   RETURNING r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d_id, r_id
   FROM d1 FULL JOIN r1 ON FALSE
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id
FROM   z1;

FULL JOIN .. ON FALSE tworzy tabelę pochodną ze wszystkimi wierszami z d1 i r1 z dodaną wartością NULL dla odpowiedniej drugiej kolumny (brak nakładania się między tymi dwoma). Potrzebujemy więc tylko jednego INSERT zamiast dwóch. Drobna optymalizacja.

dm_name i rm_name może współistnieć

WITH i AS (
   SELECT dm.dm_id, rm.rm_id
   FROM   import
   LEFT   JOIN dm USING (dm_name)
   LEFT   JOIN rm USING (rm_name)
   )
, d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm_id FROM i WHERE dm_id IS NOT NULL
   RETURNING dm_id, d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm_id FROM i WHERE rm_id IS NOT NULL
   RETURNING rm_id, r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d1.d_id, r1.r_id
   FROM   i
   LEFT   JOIN d1 USING (dm_id)
   LEFT   JOIN r1 USING (rm_id)
   WHERE  d1.dm_id IS NOT NULL OR
          r1.rm_id IS NOT NULL
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id FROM z1;

Notatki

Obie wersje działają również, jeśli żadna z nich nie istnieje.

INSERT nie wstawia niczego, jeśli SELECT nie zwraca wierszy.

Jeśli masz do czynienia z równoczesnym dostępem do zapisu, który mógłby kolidować z tą operacją, szybką poprawką byłoby zablokowanie zaangażowanych tabel przed uruchomieniem tej instrukcji w tej samej transakcji.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dla początkujących, czy jest duża różnica między MySQL a PostgreSQL?

  2. Ułatwianie zarządzania produkcyjną bazą danych PostgreSQL

  3. Testuj funkcję zerową przy różnych parametrach

  4. Jak sprawić, by wyliczenia Java i Postgres współpracowały ze sobą w celu aktualizacji?

  5. W mojej bazie danych PostgreSQL brakuje miejsca na dysku