Intereting Posts
Как настроить SQLite Присоединиться к данным столбца переменной Как мне найти вторую по величине зарплату из таблицы сотрудников? Каковы практические различия между `REPLACE` и` INSERT … ON DUPLICATE KEY UPDATE` в MySQL? MySQL выбирает MAX (datetime), не возвращая максимальное значение Расширенный SQL в Rails Как импортировать образец базы данных Oracle HR в SQL Developer? Oracle SQL Developer, как динамически запускать SQL-скрипты Преобразование SSIS – разделение одного столбца на несколько столбцов Получение sqlresult в переменную bash без заголовка / нижнего колонтитула oracle Как создать и выполнить динамический запрос в хранимой процедуре oracle? Oracle PL / SQL, как рассчитать возраст с даты рождения с помощью простой переменной замещения и months_between Триггер SQL Server вставляет значения из новой строки в другую таблицу с отношением «многие ко многим» Объединение нескольких строк результата из одного столбца в один, группы по другому столбцу mysql объединяет две таблицы с разделенными запятыми идентификаторами Для общих элементов, как найти значение на основе двух столбцов? SQL

Как вставить INTO в таблицу с несколькими столбцами из динамического запроса?

Как и в предыдущем вопросе для сопоставления «один-к-одному», мне нужно решение для нескольких столбцов в источнике и получателе.
Все еще работая с Postgres 9.4.4, запрос и схема изменены и представлены ниже:

Предположим, что у меня эти две таблицы Table1 и Table2 :

 Create table Table1(col1 int, col2 varchar(100), col3 varchar(100)); Create table Table2(col1 int, col2 varchar(100), col3 varchar(100)); 

Существует другая таблица Table3 хранится формула для переноса данных из Table1 в Table2 :

 CREATE TABLE Table3 ( tbl_src character varying(200), col_src character varying(500), tbl_des character varying(200), col_des character varying(100), condition character varying(500) ); Insert into Table3(tbl_src, col_src, tbl_des, col_des, condition) VALUES ('Table1','col1','Table2','col1', 'WHERE col1>=1') , ('Table1','col2','Table2','col2', NULL) , ('Table1','col3','Table2','col3', NULL); 

Как скомпилировать эту формулу в динамическом запросе и вставить в таблицу назначения?

Основной запрос для построения оператора для нескольких столбцов динамически – игнорирование столбца condition :

 SELECT format( 'INSERT INTO %I (%s) SELECT %s FROM %I' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src) AS sql FROM table3 WHERE tbl_des = 'Table2' AND tbl_src = 'Table1' GROUP BY tbl_des, tbl_src; 

Результат:

 INSERT INTO "Table2" (col1, col2, col3) SELECT CASE col1, col2, col3 FROM "Table1" 

Это предполагает единственный источник и единую таблицу назначения. Или все усложняется. Я добавил, что условия, чтобы сделать это ясно. Заметки о чувствительности к регистру, которые я добавил к моему предыдущему ответу, по- прежнему применяются.

Вышеупомянутое все еще игнорирует condition . Прежде всего, не включайте ключевое слово WHERE в столбец condition . Это просто шум и не полезно:

 INSERT INTO Table3(tbl_src, col_src, tbl_des, col_des, condition) VALUES ('Table1','col1','Table2','col1', 'col1>=1' ) -- without WHERE! , ('Table1', ... 

Предупреждение

Этот подход по своей сути является небезопасным. condition содержит выражения, которые должны быть объединены «как есть», поэтому вы полностью открыты для атак SQL-инъекций . Вы должны убедиться, что ненадежные пользователи не могут писать в table3 , чтобы избежать этого.

Исходя из этого и предполагая, что каждое условие применяется только к соответствующему столбцу , мы можем решить его, обернув столбец в выражении CASE :

 SELECT format( 'INSERT INTO %I (%s) SELECT %s FROM %I' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg( CASE WHEN condition IS NULL THEN quote_ident(col_src) ELSE format('CASE WHEN %s THEN %I END' , condition, col_src) -- condition is unsafe! END, ', ') , tbl_src) AS sql FROM table3 WHERE tbl_des = 'Table2' AND tbl_src = 'Table1' GROUP BY tbl_des, tbl_src; 

Выдает заявление о форме:

 INSERT INTO "Table2" (col1, col2, col3) SELECT CASE WHEN col1>=1 THEN col1 END, col2, col3 FROM "Table1" 

Или, как вы добавили в более позднем комментарии, условия могут применяться ко всем строкам . Логично, что это еще одна серая область. Условие сохраняется с определенным столбцом, но применяется ко всей строке …

Как бы то ни было, вы можете добавлять универсальные условия в предложение WHERE .

 SELECT format( 'INSERT INTO %I (%s) SELECT %s FROM %I%s' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src , ' WHERE ' || string_agg(condition, ' AND ')) AS sql FROM table3 WHERE tbl_des = 'Table2' AND tbl_src = 'Table1' GROUP BY tbl_des, tbl_src; 

Условиями являются ANDed, а WHERE добавляется только при наличии каких-либо условий – иначе результирующие значения NULL проглатывают добавленное ключевое слово в выражении ' WHERE ' || string_agg(condition, ' AND ')) ' WHERE ' || string_agg(condition, ' AND '))

Используйте это в команде DO или plpgsql для выполнения динамически, как указано в моем предыдущем ответе:

  • Как вставить INTO таблицу из динамического запроса?

Основная функция plpgsql:

 CREATE OR REPLACE FUNCTION f_test() RETURNS void AS $func$ BEGIN EXECUTE ( SELECT format( 'INSERT INTO %I (%s) SELECT %s FROM %I%s' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src , ' WHERE ' || string_agg(condition, ' AND ')) AS sql FROM table3 WHERE tbl_des = 'Table2' AND tbl_src = 'Table1' GROUP BY tbl_des, tbl_src ); END $func$ LANGUAGE plpgsql; 

SQL Fiddle.