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

Комбиниране на изрази INSERT в CTE за модифициране на данни с израз CASE

Не можете да вложите INSERT изрази в CASE изразяване. Излизайки от това, което виждам, този напълно различен подход би трябвало да го направи:

Предположения

  • Всъщност не се нуждаете от външния SELECT .

  • dm_name / rm_name са дефинирани уникални в dm / rm и не е празен (<> '' ). Трябва да имате CHECK ограничение, за да се уверите.

  • Колоната по подразбиране и за двата d_id и r_id в z са NULL (по подразбиране).

dm_name и rm_name взаимно изключващи се

Ако и двете никога не присъстват едновременно.

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 произвежда извлечена таблица с всички редове от d1 и r1 добавен с NULL за съответната друга колона (без припокриване между двете). Така че имаме нужда само от един INSERT вместо две. Незначителна оптимизация.

dm_name и rm_name може да съществува едновременно

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;

Бележки

И двете версии също работят, ако нито една не съществува.

INSERT не вмъква нищо, ако SELECT не връща ред(ове).

Ако трябва да се справите с едновременен достъп за запис, който може да е в конфликт с тази операция, бързото решение би било да заключите включени таблици, преди да изпълните този израз в същата транзакция.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да актуализирате масив в PostgreSQL

  2. Oracle към PostgreSQL:ANSI външен синтаксис на присъединяване в PostgreSQL

  3. Сравнителен анализ, управлявани PostgreSQL облачни решения – Google Cloud:Част трета

  4. Postgresql агрегатен масив

  5. Контролен списък за съответствие с SOx за PostgreSQL