Can I automatically create a table in PostgreSQL from a csv file with headers?
我在OS X 10.6.8上运行PostgreSQL 9.2.6。 我想将带有列标题的CSV文件中的数据导入数据库。 我可以使用
根据这个问题,我试过了
但我只是得到这个错误:
如果我首先创建一个没有列的表:
我明白了:
我在PostgreSQL COPY文档中找不到有关自动创建表的任何内容。 是否有其他方法可以自动从带有标题的CSV文件创建表格?
有一个非常好的工具可以从csv文件将表导入Postgres。
它是一个名为pgfutter的命令行工具(带有用于windows,linux等的二进制文件)。它的一大优点是它也能识别属性/列名。
该工具的使用很简单。例如,如果您要导入
1 | pgfutter --db"myDatabase" --port"5432" --user"postgres" --pw"mySecretPassword" csv myCSVfile.csv |
这将创建一个表(名为
一些注意事项:命令
将
1 | pgfutter --host"localhost" --port"5432" --db"myDB" --schema"public" --table"myTable" --user"postgres" --pw"myPwd" csv myFile.csv |
最有可能在导入后您将更改一些数据类型(从文本到数字):
1 2 3 | ALTER TABLE myTable ALTER COLUMN myColumn TYPE NUMERIC USING (TRIM(myColumn)::NUMERIC) |
您无法在
你需要在
还有第二种方法,我在这里找到了(来自mmatt)。基本上你在Postgres中调用一个函数(最后一个参数指定列数)。
1 | SELECT load_csv_file('myTable','C:/MyPath/MyFile.csv',24) |
这是mmatt的功能代码,我不得不稍微修改,因为我正在处理公共模式。 (复制并粘贴到PgAdmin SQL编辑器并运行它以创建函数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | CREATE OR REPLACE FUNCTION load_csv_file( target_table text, csv_path text, col_count INTEGER) RETURNS void AS $BODY$ DECLARE iter INTEGER; -- dummy integer to iterate columns with col text; -- variable to keep the column name at each iteration col_first text; -- first column name, e.g., top left corner on a csv file or spreadsheet BEGIN SET schema 'public'; CREATE TABLE temp_table (); -- add just enough number of columns FOR iter IN 1..col_count loop EXECUTE format('alter table temp_table add column col_%s text;', iter); END loop; -- copy the data from csv file EXECUTE format('copy temp_table from %L with delimiter '','' quote ''"'' csv ', csv_path); iter := 1; col_first := (SELECT col_1 FROM temp_table LIMIT 1); -- update the column names based on the first row which has the column names FOR col IN EXECUTE format('select unnest(string_to_array(trim(temp_table::text, ''()''), '','')) from temp_table where col_1 = %L', col_first) loop EXECUTE format('alter table temp_table rename column col_%s to %s', iter, col); iter := iter + 1; END loop; -- delete the columns row EXECUTE format('delete from temp_table where %s = %L', col_first, col_first); -- change the temp table name to the name given as parameter, if not blank IF LENGTH(target_table) > 0 THEN EXECUTE format('alter table temp_table rename to %I', target_table); END IF; END; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION load_csv_file(text, text, INTEGER) OWNER TO postgres; |
注意:导入与编码相关的文本文件存在一个常见问题。 csv文件应为UTF-8格式。但是,有时候尝试进行编码的程序并没有完全实现这一点。我通过在Notepad ++中打开文件并将其转换为ANSI并返回到UTF8来克服此问题。
我通过以下步骤实现了它:
1 | iconv -f ISO-8859-1 -t UTF-8 file.txt -o file.csv |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #!/usr/bin/env python3 import csv, os #pip install python-slugify FROM slugify import slugify origem = 'file.csv' destino = 'file.sql' arquivo = os.path.abspath(origem) d = OPEN(destino,'w') WITH OPEN(origem,'r') AS f: header = f.readline().split(';') head_cells = [] FOR cell IN header: VALUE = slugify(cell,separator="_") IF VALUE IN head_cells: VALUE = VALUE+'_2' head_cells.append(VALUE) #cabecalho ="{} ".format(';'.join(campos)) #print(cabecalho) FIELDS= [] FOR cell IN head_cells: FIELDS.append(" {} text".format(cell)) TABLE = origem.split('.')[0] SQL ="create table {} ( {} );".format(origem.split('.')[0],", ".join(FIELDS)) SQL +=" COPY {} FROM '{}' DELIMITER ';' CSV HEADER;".format(TABLE,arquivo) print(SQL) d.write(SQL) |
3.运行脚本
1 | python3 importar.py |
可选:编辑sql脚本以调整字段类型(默认情况下都是文本)
1 | sudo -H -u postgres bash -c"psql mydatabase < file.sql" |
对于单个表格,我通过网络上可以找到的众多优秀转换器中的一个非常简单,快速和在线完成。
只需谷歌将csv转换为sql在线并选择一个。