以下是一个函数,它是用于定期将许多CSV(可以更改)上传到Postgres 9.6 db的过程的一部分。任何人对如何改进此功能或您想要分享的其他数据上传流程有任何建议?
该功能有效(我认为),所以我想我会分享,以防其他人有用。作为一个新手,这让我永远地翻转,所以希望我可以节省一些时间。
我从各种来源+++中提取代码来创建此函数,该函数插入源表中具有匹配目标表列的所有列,在插入期间将源列中的数据类型转换为目标列的数据类型。我计划将其转换为在更新源表时执行的触发器函数。
更大的图片:1)批处理文件运行dbf2csv以将DBF导出为CSV,2)批处理文件运行csvkit以将许多CSV加载到名为dataloader的模式中的单独表中,并为CSV日期添加新列,3)下面的函数将数据从dataloader表移动到位于公共模式中的主表。我曾考虑使用PGloader,但我不懂Python。我将遇到的一个问题是,如果将新列添加到源CSV(此函数将忽略它们),但我可以手动监视,因为列的变化不大。
+++我记得一些(谢谢!)
我尝试使用FDW并且不记得为什么我没有使用这种方法。
CREATE OR REPLACE FUNCTION dataloader.insert_des3 (
tbl_des pg_catalog.regclass,
tbl_src pg_catalog.regclass
)
RETURNS void AS
$body$
DECLARE
tdes_cols text;
tsrc_cols text;
BEGIN
SET search_path TO dataloader, public;
SELECT string_agg( c1.attname, ',' ),
string_agg( quote_ident( COALESCE( c2.attname, 'NULL' ) ) || '::' || format_type(c1.atttypid, c1.atttypmod), ',' )
INTO tdes_cols,
tsrc_cols
FROM pg_attribute c1
LEFT JOIN pg_attribute c2
ON c2.attrelid = tbl_src
AND c2.attnum > 0 --attnum is the column number of c2
AND NOT c2.attisdropped
AND c1.attname = lower(c2.attname)
WHERE c1.attrelid = tbl_des
AND c1.attnum > 0
AND NOT c1.attisdropped
AND c1.attname <> 'id';
EXECUTE format(
' INSERT INTO %I (%s)
SELECT %s
FROM %I
',
tbl_des,
tdes_cols,
tsrc_cols,
tbl_src
);
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
调用功能
SELECT dataloader.insert_des('public.tbl_des','dataloader.tbl_src')