2016-09-12 3 views
0

Я ищу динамически вставлять набор столбцов из одной таблицы в другую в PostgreSQL. Я думаю, что я хотел бы сделать, это прочитать «контрольный список» заголовков столбцов (те столбцы, которые существуют в таблице 1 - таблица хранения), и если они существуют в таблице экспорта (таблица 2), тогда вставьте их во все сразу же из таблицы 1. Таблица 2 будет переменной в ее столбцах, хотя - после импорта плохое падение и импорт новых данных для импорта с потенциально другой структурой столбцов. Поэтому мне нужно импортировать его на основе имен столбцов.PostgreSQL - динамический INSERT для имен столбцов

например.

Таблица 1. - Стол для хранения

ID  NAME  YEAR  LITH_AGE PROV_AGE SIO2 TIO2 CAO MGO COMMENTS 
1  John  1998  2000  3000  65  10  5  5  comment1 
2  Mark  2005  2444  3444  63  8  2  3  comment2 
3  Luke  2001  1000  1500  77  10  2  2  comment3 

Таблица 2. - Таблица экспорта

ID  NAME  MG# METHOD SIO2 TIO2 CAO MGO 
1  Amy  4  Method1 65  10  5  5  
2  Poe  3  Method2 63  8  2  3 
3  Ben  2  Method3 77  10  2  2  

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

Я хочу вставить все эти столбцы сразу, как я нашел, если я делаю это по отдельности по столбцу, он расширяет количество строк каждый раз на вставке (может быть, кто-то может решить эту проблему вместо этого? ve записала функцию, чтобы проверить, существует ли имя столбца в таблице 2, если это так, вставьте ее, но, как сказано, это каждый раз увеличивает строки таблицы и NULL остальные столбцы). ВСТАВИТЬ линия от моей функции:

EXECUTE format('INSERT INTO %s (%s) (SELECT %s::%s FROM %s);',_tbl_import, _col,_col,_type,_tbl_export); 

Как тип «Пример кода» для моего вопроса:

EXECUTE FORMAT('INSERT INTO table1 (%s) (SELECT (%s) FROM table2)',columns) 

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

Это идеально обновить таблицу 1:

ID  NAME  YEAR  LITH_AGE PROV_AGE SIO2 TIO2 CAO MGO COMMENTS 
1  John  1998  2000  3000  65  10  5  5  comment1 
2  Mark  2005  2444  3444  63  8  2  3  comment2 
3  Luke  2001  1000  1500  77  10  2  2  comment3 
4  Amy  NULL  NULL  NULL  65  10  5  5  NULL 
5  Poe  NULL  NULL  NULL  63  8  2  3  NULL 
6  Ben  NULL  NULL  NULL  77  10  2  2  NULL 

ответ

0

Обновлено ответ

Как мой первоначальный ответ не соотвествовать вышел позже, но попросили опубликовать альтернативный пример information_schema решения так вот.

Я сделал две версии для решений:

V1 - эквивалентно уже дали пример с использованием INFORMATION_SCHEMA. Но это решение основывается на table1 column DEFAULT s. Значение, если table1 столбец, который не существует на table2 не имеет DEFAULT NULL, тогда он будет заполнен любым значением по умолчанию.

V2 - модифицирован, чтобы заставить 'NULL' в случае несоответствия двух столбцов таблицы и не наследует table1 собственные DEFAULTS

Version1:

CREATE OR REPLACE FUNCTION insert_into_table1_v1() 
RETURNS void AS $main$ 

DECLARE 
    columns text; 

BEGIN 

    SELECT string_agg(c1.attname, ',') 
    INTO columns 
    FROM pg_attribute c1 
    JOIN pg_attribute c2 
    ON  c1.attrelid = 'public.table1'::regclass 
    AND  c2.attrelid = 'public.table2'::regclass 
    AND  c1.attnum > 0 
    AND  c2.attnum > 0 
    AND  NOT c1.attisdropped 
    AND  NOT c2.attisdropped 
    AND  c1.attname = c2.attname 
    AND  c1.attname <> 'id'; 

    --  Following is the actual result of query above, based on given data examples: 
    --  -[ RECORD 1 ]---------------------- 
    --  string_agg | name,si02,ti02,cao,mgo 

    EXECUTE format(
     ' INSERT INTO table1 (%1$s) 
      SELECT %1$s 
      FROM table2 
     ', 
     columns 
    ); 

END; 
$main$ LANGUAGE plpgsql; 

Version2:

CREATE OR REPLACE FUNCTION insert_into_table1_v2() 
RETURNS void AS $main$ 

DECLARE 
    t1_cols text; 
    t2_cols text; 

BEGIN 

    SELECT string_agg(c1.attname, ','), 
      string_agg(COALESCE(c2.attname, 'NULL'), ',') 
    INTO t1_cols, 
      t2_cols 
    FROM pg_attribute c1 
    LEFT JOIN pg_attribute c2 
    ON  c2.attrelid = 'public.table2'::regclass 
    AND  c2.attnum > 0 
    AND  NOT c2.attisdropped 
    AND  c1.attname = c2.attname 
    WHERE c1.attrelid = 'public.table1'::regclass 
    AND  c1.attnum > 0 
    AND  NOT c1.attisdropped 
    AND  c1.attname <> 'id'; 

    --  Following is the actual result of query above, based on given data examples: 
    --        t1_cols       |     t2_cols 
    --  --------------------------------------------------------+-------------------------------------------- 
    --  name,year,lith_age,prov_age,si02,ti02,cao,mgo,comments | name,NULL,NULL,NULL,si02,ti02,cao,mgo,NULL 
    --  (1 row) 

    EXECUTE format(
     ' INSERT INTO table1 (%s) 
      SELECT %s 
      FROM table2 
     ', 
     t1_cols, 
     t2_cols 
    ); 

END; 
$main$ LANGUAGE plpgsql; 

также ссылки на документацию о pg_attribute столбцов таблицы, если что-то неясно: https://www.postgresql.org/docs/current/static/catalog-pg-attribute.html

Надеется, что это помогает :)

+0

К сожалению, я должен был указан выше (добавлено в настоящее время), почему мне нужно сделать это на колонке имя. «Таблица 2» будет отброшена и часто изменена, по существу моя временная таблица для импорта данных в таблицу 1. В таблице 2 не всегда будут одинаковые комбинации столбцов, поэтому я не могу сделать здесь NULL, так как я не знаю, какая структура будет. Я знаю только имена столбцов, которые «ищут» из таблицы 1, и если они существуют, импортируйте. – MattGeo

+0

Ack, тогда это совсем другая история. Я вижу, у тебя уже есть anwser :) –

Смежные вопросы