我希望在PostgreSQL中从一个表动态插入一组列到另一个表。我想我想做的是在列标题的'核对表'中读取(表1中存在的那些列 - 存储表),如果它们存在于导出表(表2)中,则将它们插入所有列表2将在其列中变量 - 一旦导入,则删除它并导入要导入的具有可能不同列结构的新数据。所以我需要根据列名称导入它。
e.g。
表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)
其中'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 :(得分:0)
更新回答
由于我原来的答案不符合要求后来出来,但被要求发布一个信息解决方案的另一个例子,所以在这里。
我为解决方案制作了两个版本:
V1 - 等同于使用 information_schema 已经给出的示例。但该解决方案依赖于 table1 列 DEFAULT 。这意味着,如果 table2 中不存在的 table1 列没有 DEFAULT NULL ,那么它将填充默认值。
V2 - 被修改为强制“空白”'如果两个表列不匹配并且没有继承 table1 自己的DEFAULTs
<强>版本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
希望这有助于:)