Одна ВСТАВКА с несколькими строками из нескольких операторов SELECT

#sql #postgresql #sql-insert

Вопрос:

У меня есть несколько (> 100) INSERT операторов PostgreSQL>, которые все похожи на этот, но с разными вариантами выбора:

 INSERT INTO schema.table (geom, name, label, flag, type)
SELECT (geom, <complicated string concatenation from multiple fields>, the_label, TRUE, type_id)
FROM abc.xzy a WHERE a.changelog = 1
ORDER BY a.num;
 

SQL-запрос может измениться, но его вывод, конечно, выполняется в соответствии с INSERT требованиями.

Я бы хотел сделать все это с помощью одного INSERT . Возможно, используя предложение VALUES, например:

 INSERT INTO ... VALUES
  (val1,val2,val3,val4,...)
, (val11,val12,val13,val14,...)
 

Показано, что это работает здесь с простыми «статическими» значениями (не из SELECT операторов).

Но это не работает с SELECT тем, чтобы получить значения для INSERT :

 INSERT INTO schema.table (geom, name, label, flag, type)
VALUES
  (
    SELECT (geom, <complicated string concatenation from multiple fields>, the_label, TRUE, type_id)
    FROM abc.xzy a WHERE a.changelog = 1
    ORDER BY a.num
  ),
  (
    SELECT (geom, <complicated string concatenation from multiple fields>, a_label, FALSE, type_id)
    FROM def.uvt a WHERE a.typedf
    ORDER BY a.idx
  ),
...
);
 

Я получаю ошибку: subquery must return only one column в самой первой открывающей скобке, как раз перед самой первой SELECT .

Как я мог бы это исправить, если бы это было возможно?

Версия PG >= 9.6.

Ответ №1:

Попытка указывает на путаницу между значениями (полями) и строками (записями).

Тебе не нужно VALUES выражение лица. Просто используйте SELECT утверждения напрямую. Цепочка, кратная SELECT с UNION ALL :

 INSERT INTO schema.table (geom, name, label, flag, type)
(
SELECT geom, <complicated string concatenation from multiple fields>, the_label, TRUE, type_id
FROM   abc.xzy a WHERE a.changelog = 1
ORDER  BY a.num
)
UNION ALL
(
SELECT geom, <complicated string concatenation from multiple fields>, a_label, FALSE, type_id
FROM   def.uvt a WHERE a.typedf
ORDER  BY a.idx
);
 

Дополнительные скобки необходимы только для того, чтобы разрешить ORDER BY per SELECT . Но это полезно только в том случае, если важен физический порядок строк. (Для оптимизации производительности.) Порядок вставленных строк не имеет другого значения и может измениться позже с помощью операций записи. Так что вы, вероятно, просто хотите:

 INSERT INTO schema.table (geom, name, label, flag, type)
SELECT geom, <complicated string concatenation from multiple fields>, the_label, TRUE, type_id
FROM   abc.xzy a WHERE a.changelog = 1
UNION ALL
SELECT geom, <complicated string concatenation from multiple fields>, a_label, FALSE, type_id
FROM   def.uvt a WHERE a.typedf;