在PostgreSQL中创建包含许多列的表
为了在我的例子中使用COPY,我需要首先从PostgreSQL中的csv文件函数创建目标表 例如,如果我的表有60列,手动编写以下内容会让人感到奇怪和低效:在PostgreSQL中创建包含许多列的表,postgresql,Postgresql,为了在我的例子中使用COPY,我需要首先从PostgreSQL中的csv文件函数创建目标表 例如,如果我的表有60列,手动编写以下内容会让人感到奇怪和低效: CREATE TABLE table_name( column1 datatype, column2 datatype, column3 datatype, ..... column60 datatype 那些使用PostgreSQL的人-如何解决这个问题?我通常使用文件扩展名从CSV文件读取数据 但不幸的是
CREATE TABLE table_name(
column1 datatype,
column2 datatype,
column3 datatype,
.....
column60 datatype
那些使用PostgreSQL的人-如何解决这个问题?我通常使用文件扩展名从CSV文件读取数据
但不幸的是,当您解决诸如从包含多个列的CSV文件读取之类的任务时,file_fdw并不是那么方便/灵活。CREATETABLE可以处理任意数量的列,但如果它与CSV文件不对应,则稍后在执行SELECT时将失败。所以表的显式创建问题仍然存在。然而,解决这个问题是可能的
这是一种暴力方法,除了博士后,它不需要任何东西。该函数用PL/pgSQL编写,尝试创建一个只有一列的表,并尝试从中进行选择。如果失败,它将删除该表并重试,但有2列。依此类推,直到选择确定为止。所有列都是文本类型–这是一个很大的限制,但它仍然解决了准备好选择表而不是手动操作的任务
create or replace function autocreate_table_to_read_csv(
fdw_server text,
csv text,
table_name text,
max_columns_num int default 100
) returns void as $$
declare
i int;
sql text;
rec record;
begin
execute format('drop foreign table if exists %I', table_name);
for i in 1..max_columns_num loop
begin
select into sql
format('create foreign table %I (', table_name)
|| string_agg('col' || n::text || ' text', ', ')
|| format(
e') server %I options ( filename \'%s\', format \'csv\' );',
fdw_server,
csv
)
from generate_series(1, i) as g(n);
raise debug 'SQL: %', sql;
execute sql;
execute format('select * from %I limit 1;', table_name) into rec;
-- looks OK, so the number of columns corresponds to the first row of CSV file
raise info 'Table % created with % column(s). SQL: %', table_name, i, sql;
exit;
exception when others then
raise debug 'CSV has more than % column(s), making another attempt...', i;
end;
end loop;
end;
$$ language plpgsql;
一旦找到适当数量的列,它将报告有关它的信息,请参见raise info
要查看更多详细信息,请运行set client_min_messages To debug;在使用该函数之前
使用示例:
test=# create server csv_import foreign data wrapper file_fdw;
CREATE SERVER
test=# set client_min_messages to debug;
SET
test=# select autocreate_table_to_read_csv('csv_import', '/home/nikolay/tmp/sample.csv', 'readcsv');
NOTICE: foreign table "readcsv" does not exist, skipping
DEBUG: SQL: create foreign table readcsv (col1 text) server csv_import options ( filename '/home/nikolay/tmp/sample.csv', format 'csv' );
DEBUG: CSV has more than 1 column(s), making another attempt...
DEBUG: SQL: create foreign table readcsv (col1 text, col2 text) server csv_import options ( filename '/home/nikolay/tmp/sample.csv', format 'csv' );
DEBUG: CSV has more than 2 column(s), making another attempt...
DEBUG: SQL: create foreign table readcsv (col1 text, col2 text, col3 text) server csv_import options ( filename '/home/nikolay/tmp/sample.csv', format 'csv' );
INFO: Table readcsv created with 3 column(s). SQL: create foreign table readcsv (col1 text, col2 text, col3 text) server csv_import options ( filename '/home/nikolay/tmp/sample.csv', format 'csv' );
autocreate_table_to_read_csv
------------------------------
(1 row)
test=# select * from readcsv limit 2;
col1 | col2 | col3
-------+-------+-------
1313 | xvcv | 22
fvbvb | 2434 | 4344
(2 rows)
更新:发现了非常类似的实现,但没有暴力,需要在CSV文件方法中明确指定列,以便复制。。发件人:
另外,事实上,这将是一个非常好的任务,以改善文件的fdw和复制。。由于Postgres的功能使其更加灵活——例如,对于Postgres_fdw,有一个非常方便的导入外来模式命令,它允许非常快速地定义远程外来对象,只需一行——它节省了大量工作。在CSV DTA中有类似的东西是很棒的。你可以使用ORM/驱动程序在你的语言选择中动态地做到这一点,虽然我会认真考虑如果你真的需要一个表中的60列,即使它们只有30,我也要频繁地打开各种CSV文件并进行各种数据操作。每次我想在csv文件上使用sql时,手动创建一个表对我来说没有什么意义。在这种情况下,实现自动化的最佳选择是用您喜欢的语言编写脚本。我会在Node+Knex中完成。