我可以从带有标题的csv文件中自动在PostgreSQL中创建一个表吗?

iho*_*ugh 48 csv postgresql

我在OS X 10.6.8上运行PostgreSQL 9.2.6.我想将带有列标题的CSV文件中的数据导入数据库.我可以使用该COPY语句执行此操作,但前提是我首先手动创建一个包含CSV文件中每列的列的表.有没有办法根据CSV文件中的标题自动创建此表?

根据这个问题,我试过了

COPY test FROM '/path/to/test.csv' CSV HEADER;

但我只是得到这个错误:

ERROR: relation "test" does not exist

如果我首先创建一个没有列的表:

CREATE TABLE test ();

我明白了:

ERROR: extra data after last expected column

我在PostgreSQL COPY文档中找不到有关自动创建表的任何内容.是否有其他方法可以自动从带有标题的CSV文件创建表格?

Wol*_*lfi 36

有一个非常好的工具可以从csv文件中将表导入Postgres.它是一个名为pgfutter的命令行工具(带有用于windows,linux等的二进制文件).它的一大优点是它也能识别属性/列名.

该工具的使用很简单.例如,如果您要导入myCSVfile.csv:

pgfutter --db "myDatabase" --port "5432" --user "postgres" --pw "mySecretPassword" csv myCSVfile.csv
Run Code Online (Sandbox Code Playgroud)

这将创建一个表(称为myCSVfile),其列名取自csv文件的标题.此外,将从现有数据中识别数据类型.

一些注意事项:命令pgfutter因您使用的二进制文件而异,例如它可能是pgfutter_windows_amd64.exe(如果您打算经常使用此命令,则重命名).上述命令必须在命令行窗口中执行(例如,在Windows中运行cmd并确保pgfutter可以访问).如果您想要添加不同的表名--table "myTable"; 我们选择一个特定的数据库模式--schema "mySchema".如果您正在访问外部数据库使用--host "myHostDomain".

的更详细的例子pgfutter导入myFilemyTable是这一个:

pgfutter --host "localhost" --port "5432" --db "myDB" --schema "public" --table "myTable" --user "postgres" --pw "myPwd" csv myFile.csv
Run Code Online (Sandbox Code Playgroud)

最有可能在导入后您将更改一些数据类型(从文本到数字):

alter table myTable
  alter column myColumn type numeric
    using (trim(myColumn)::numeric)
Run Code Online (Sandbox Code Playgroud)

  • 在检查 --help 后,我使用各种选项运行此命令,它什么也不做,也不输出任何内容。一个错误就好了 (3认同)
  • 如果指定架构名称,则需要创建目标表和列。令人沮丧 (2认同)
  • 当您尝试导入 CSV 文件时,此工具目前因“索引超出范围”异常而失败。 (2认同)

Cok*_*aka 34

使用 sqlite 作为中间步骤。

脚步:

  1. 在命令提示符下键入:sqlite3
  2. 在 sqlite3 CLI 中输入:.mode csv
  3. .import my_csv.csv my_table
  4. .output my_table_sql.sql
  5. .dump my_table
  6. 最后在 Postgresql 中执行该 sql

  • TIL sqlite 有很好的导入工具!谢谢这对我来说非常有用。 (2认同)
  • 这是一个很好的解决方案,值得称赞 (2认同)

Erw*_*ter 24

您无法在COPY文档中找到任何内容,因为COPY 无法为您创建表格.
你需要先做到这COPY一点.

  • 这个答案实际上并没有回答他的问题 (39认同)
  • 该答案应该是评论,不应被接受,因为它没有回答问题。 (17认同)

小智 21

csvsql用来生成表格布局(它会自动猜测格式):

head -n 20 table.csv | csvsql --no-constraints --tables table_name 
Run Code Online (Sandbox Code Playgroud)

然后我\COPYpsql. 这对我来说是导入 CSV 文件的最快方法。

您还可以使用sedwithcsvsql以获得所需的数据类型:

head -n 20 table.csv | csvsql --no-constraints --tables table_name  | sed 's/DECIMAL/NUMERIC/' | sed 's/VARCHAR/TEXT/'
Run Code Online (Sandbox Code Playgroud)


Wol*_*lfi 18

还有第二种方法,我在这里找到(来自mmatt).基本上你在Postgres中调用一个函数(最后一个参数指定列数).

select load_csv_file('myTable','C:/MyPath/MyFile.csv',24)
Run Code Online (Sandbox Code Playgroud)

这是mmatt的功能代码,我不得不稍微修改,因为我正在处理公共模式.(复制并粘贴到PgAdmin SQL编辑器并运行它以创建函数)

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;
Run Code Online (Sandbox Code Playgroud)

注意:导入与编码相关的文本文件存在一个常见问题.csv文件应为UTF-8格式.但是,有时候尝试进行编码的程序并没有完全实现这一点.我通过在Notepad ++中打开文件并将其转换为ANSI并返回到UTF8来克服此问题.

  • 这是一个整洁的解决方案.注意确保没有列保留关键字名称 - 例如,如果CSV文件有一个名为`order`的列(例如,对于订单号),请将其更改为`order_num`.另外,请记住根据需要更改"TYPE"列. (2认同)

add*_*lor 9

使用Python+Pandas自动创建似乎很容易

在 Python 环境中安装 sqlalchemy 库 pip install SQLAlchemy==1.4.31

import pandas as pd
from sqlalchemy import create_engine
engine = create_engine('postgresql://username:password@localhost:5432/mydatabase')
df=pd.read_csv('example.csv')
df.to_sql('table_name', engine)
Run Code Online (Sandbox Code Playgroud)