2016-09-12 3 views
0

PostgreSQL의 한 테이블에서 다른 테이블로 열 집합을 동적으로 삽입하려고합니다. 내가하고 싶다고 생각하는 것은 열 표제 (테이블 1 - 스토리지 테이블에있는 열)의 '체크리스트'에서 읽고, 내보내기 테이블 (표 2)에있는 경우 모두에 삽입하십시오 표 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  

당신은 스토리지 테이블에 존재하지 않는 열을 포함 할 수 수출 테이블을 볼 수 있듯이 , 이것들은 무시됩니다.

개별적으로 열로 삽입하면 매번 삽입 할 때 행 수가 늘어날 것입니다 (어쩌면 누군가이 문제를 대신 해결할 수 있을까요? 테이블 2에 열 이름이 있는지 확인하는 함수를 작성했습니다. 삽입 할 경우 매번 테이블 행이 확장되고 나머지 열은 NULL로 표시됩니다. 내 함수의 INSERT 라인 : 내 질문에 대한 '코드 예제'의 유형으로

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 솔루션에 대한 대체 예를 게시하도록 요청 받았다으로 여기있어. 이미 INFORMATION_SCHEMA를 사용하여 예제를 제공하는 것과 같습니다 -

V1 :

나는 솔루션에 대한 두 가지 버전을했다. 그러나 그 해결책은 표 1DEFAULT에 의존합니다. 의미, 테이블 1에 존재하지 않는 열 테이블 2의 경우 DEFAULT NULL이 없으면 기본값이 채워집니다.

V2 - 두 테이블 컬럼 불일치의 경우 'NULL'을 강제로 수정되고 자신의 기본값

버전 1 상속하지 않습니다

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; 

버전 2를 :

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

죄송하지만 지금은 같은 내가 열 그것을해야하는 이유에 (지금 추가) 이상 지정해야 이름. 'Table 2'는 삭제되고 종종 테이블 1로 데이터를 가져 오기위한 임시 테이블입니다. 테이블 2는 항상 같은 열 조합을 가지고 있지 않으므로 어떤 구조인지는 모르겠으므로 여기서 NULL을 수행하지 않습니다 가질거야. 나는 단지 컬럼 이름이 '테이블 1'에서 '찾고있는'것을 알고 있고, 존재한다면 수입한다. – MattGeo

+0

Ack, 그러면 그것은 다른 이야기입니다. 나는 당신이 anwser를 이미 가지고있는 것을 본다 :) –

관련 문제