相关文章推荐
苦恼的冲锋衣  ·  pytorch ...·  1 年前    · 
乐观的西瓜  ·  Troubleshooting ...·  2 年前    · 
英姿勃勃的饺子  ·  钱忠·  2 年前    · 
健壮的日光灯  ·  python - How can I ...·  2 年前    · 

如何将CSV文件数据导入到PostgreSQL的表中

731 人关注

我如何编写一个存储过程,从CSV文件导入数据并填充到表中?

5 个评论
为什么要用存储过程?复制 "可以做到这一点
我有一个上传csv文件的用户界面,为了连接这个,我需要一个实际从csv文件复制数据的存储过程。
你能详细说明如何使用 "复制 "吗?
Bozhidar Batsov已经给了你一个例子的链接,精美的手册也可以帮助你。 postgresql.org/docs/8.4/interactive/sql-copy.html
postgresql
csv
postgresql-copy
vardhan
vardhan
发布于 2010-06-07
23 个回答
Bozhidar Batsov
Bozhidar Batsov
发布于 2021-12-01
已采纳
0 人赞同

看一下这个 短文 .

解决办法在此转述。

创建你的表格。

CREATE TABLE zip_codes
(ZIP char(5), LATITUDE double precision, LONGITUDE double precision,
CITY varchar, STATE char(2), COUNTY varchar, ZIP_CLASS varchar);

从你的CSV文件中复制数据到表中。

COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' WITH (FORMAT csv);
    
实际上,如果你没有超级用户权限,使用 \copy 也会有同样的效果;在我的Fedora 16上,当用非root账户使用COPY时,就会有投诉。
提示:你可以用zip_codes(col1, col2, col3)表示你在CSV中的列。这些列必须按照它们在文件中出现的相同顺序列出。
@asksw0rder does \copy have the same syntax? bcoz I'm getting a syntax error with \copy.
我应该包括标题行吗?
你可以很容易地包括标题行 -- 只要在选项中加入HEADER。 【替换代码0 postgresql.org/docs/9.1/static/sql-copy.html
bjelli
bjelli
发布于 2021-12-01
0 人赞同

如果你没有权限使用 COPY (在数据库服务器上工作),你可以使用 \copy 代替(在数据库客户端工作)。使用同样的例子 饰演Bozidar Batsov :

创建你的表格。

CREATE TABLE zip_codes
(ZIP char(5), LATITUDE double precision, LONGITUDE double precision,
CITY varchar, STATE char(2), COUNTY varchar, ZIP_CLASS varchar);

从你的CSV文件中复制数据到表中。

\copy zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV

请注意:"...... "必须写在一行中,并且在结尾处没有";"。

你还可以指定要读取的列。

\copy zip_codes(ZIP,CITY,STATE) FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV

See the 复制的文件:

不要将COPY与psql指令\copy混淆。\COPY调用COPY FROM STDIN或COPY TO STDOUT,然后在psql客户端可访问的文件中提取/存储数据。因此,当使用\copy时,文件的可访问性和访问权限取决于客户端而不是服务器。

并注意到。

对于身份列,COPY FROM命令将始终写入输入数据中提供的列值,就像INSERT选项OVERRIDING SYSTEM VALUE一样。

JZ.
\copy voters(ZIP,CITY) FROM '/Users/files/Downloads/WOOD.TXT' DELIMITER ',' CSV HEADER; ERROR: extra data after last expected column CONTEXT: COPY voters, line 2:"OH0012781511,87,26953,户主,Sherry,Ligh,,11/26/1965,08/19/1988,,211 N Garfield St , ,Bloomd..."
@JZ.我有一个类似的错误。这是因为我有额外的空白列。检查你的csv,如果你有空白列,这可能是原因。
这有点误导: COPY \copy 之间的区别远不止是权限,你不能简单地添加一个``来使其神奇地工作。请看这里的描述(在出口的情况下)。 stackoverflow.com/a/1517692/157957
@IMSoP:你是对的,我加了一个服务器和客户端的提法来澄清
@Sebastian: 重要的区别是,copy是从客户端工作的,所以你仍然必须把所有的数据传输到服务器上。用COPY(没有斜线),你首先用其他方式(sftp,scp)把所有的数据上传到服务器上,然后在服务器上做导入。但传输1.5MB听起来不像是要讲3个小时--无论你用什么方式。
RobinL
RobinL
发布于 2021-12-01
0 人赞同

做到这一点的一个快速方法是使用Python 熊猫 库(0.15或以上版本效果最好)。 这将为你处理创建列的问题--尽管显然它对数据类型的选择可能不是你想要的。 如果它不能完全满足你的要求,你总是可以使用作为模板生成的 "创建表 "代码。

这里有一个简单的例子。

import pandas as pd
df = pd.read_csv('mypath.csv')
df.columns = [c.lower() for c in df.columns] # PostgreSQL doesn't like capitals or spaces
from sqlalchemy import create_engine
engine = create_engine('postgresql://username:password@localhost:5432/dbname')
df.to_sql("my_table_name", engine)

而这里有一些代码,告诉你如何设置各种选项。

# Set it so the raw SQL output is logged
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
df.to_sql("my_table_name2",
          engine,
          if_exists="append",  # Options are ‘fail’, ‘replace’, ‘append’, default ‘fail’
          index = False, # Do not output the index of the dataframe
          dtype = {'col1': sqlalchemy.types.NUMERIC,
                   'col2': sqlalchemy.types.String}) # Datatypes should be SQLAlchemy types
    
此外, if_exists 参数可以被设置为替换或追加到现有的表格中,例如 df.to_sql("fhrs", engine, if_exists='replace')
用户名和密码:需要创建Login并将DB分配给用户。如果使用pgAdmin,则使用GUI创建 "登录/组角色"。
Pandas是一种超级慢的加载到sql的方式(相对于csv文件)。可能会慢上几个数量级。
这可能是一种写数据的方式,但即使有批处理和良好的计算能力,它也是超级慢的。使用CSV是一个很好的方法来完成这个任务。
df.to_sql() 真的很慢,你可以使用 d6tstack.utils.pd_to_psql() d6tstack see 性能比较
mehmet
mehmet
发布于 2021-12-01
0 人赞同

这里的大多数其他解决方案要求你提前/手动创建表。这在某些情况下可能并不实用(例如,如果你在目标表中有很多列)。所以,下面的方法可能会很方便。

提供你的CSV文件的路径和列数,你可以使用以下函数将你的表加载到一个临时表,该表将被命名为 target_table

最上面的一行被假定为有列名。

create or replace function data.load_csv_file
    target_table text,
    csv_path text,
    col_count integer
returns void as $$
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
    create table temp_table ();
    -- add just enough number of columns
    for iter in 1..col_count
        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)
        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;
$$ language plpgsql;
    
嗨,Mehmet,感谢你发布的答案,但是当我运行你的代码时,我得到了以下错误信息:ERROR: schema "data" 不存在
user2867432 你需要相应地改变你使用的模式名称(例如, public )。
嗨,Mehmet,谢谢你的解决方案,它很完美,但这只有在postgres数据库用户是超级用户的情况下才有效,有什么方法可以让它在没有超级用户的情况下工作吗?
Geeme:改为 "安全定义者" here 但我自己并没有使用过它。
回答得很好!我不会在我的代码中太过泛泛而谈,以利于他人的阅读。
Paul
Paul
发布于 2021-12-01
0 人赞同

你也可以使用 pgAdmin ,它提供了一个GUI来进行导入。这显示在这个 SO线 .使用pgAdmin的好处是,它也适用于远程数据库。

和前面的解决方案一样,你需要在数据库中已经有了你的表。每个人都有自己的解决方案,但我通常在Excel中打开CSV文件,复制标题,在不同的工作表上粘贴特殊移位,将相应的数据类型放在下一列,然后将其复制并粘贴到文本编辑器中,再加上适当的SQL表创建查询,像这样。

CREATE TABLE my_table (
    /* Paste data from Excel here for example ... */
    col_1 bigint,
    col_2 bigint,
    /* ... */
    col_n bigint
    
请展示一下你粘贴的数据的几行样本
timxor
timxor
发布于 2021-12-01
0 人赞同
COPY table_name FROM 'path/to/data.csv' DELIMITER ',' CSV HEADER;
    
user9130085
user9130085
发布于 2021-12-01
0 人赞同
  • 先创建一个表

  • 然后使用复制命令来复制表的细节。

     copy table_name (C1,C2,C3....)
     from 'path to your CSV file' delimiter ',' csv header;
    

    NOTE:

  • columns and order are specified by C1,C2,C3.. in SQL
  • The header option just skips one line from the input, not according to columns' name.
  • Wes
    这怎么会不是公认的答案呢? 既然数据库已经有一个命令可以做到这一点,我为什么还要写一个python脚本呢?
    Andreas L.
    Andreas L.
    发布于 2021-12-01
    0 人赞同

    保罗提到 ,在pgAdmin中导入工作。

    右键点击表格→ Import

    选择一个本地文件、格式和编码。

    这里有一个德国pgAdmin GUI的截图。

    类似的事情你可以用DbVisualizer来做(我有许可证,不清楚免费版的情况)。

    右键点击一个表格→ 导入表数据...

    DBVisualizer花了50秒来导入1400行的三个字段--而且我不得不把所有的东西从一个字符串转换为它应该是的样子。
    djdere
    djdere
    发布于 2021-12-01
    0 人赞同

    Use this SQL code:

    copy table_name(atribute1,attribute2,attribute3...)
    from 'E:\test.csv' delimiter ',' csv header
    

    header关键字让DBMS知道CSV文件有一个带有属性的标题。

    For more, visit 将CSV文件导入到PostgreSQL表中.

    flowera
    flowera
    发布于 2021-12-01
    0 人赞同

    这是使用PostgreSQL的个人经验,我仍在等待更快的方法。

  • 如果文件存储在本地,首先创建一个表的骨架。

     drop table if exists ur_table;
     CREATE TABLE ur_table
         id serial NOT NULL,
         log_id numeric,
         proc_code numeric,
         date timestamp,
         qty    int,
         name varchar,
         price money
         ur_table(id, log_id, proc_code, date, qty, name, price)
     FROM '\path\xxx.csv' DELIMITER ',' CSV HEADER;
    
  • When the \csv文件是在服务器上,PostgreSQL没有访问服务器的 访问该服务器的权限。你将不得不通过以下方式导入.csv文件pgAdmin内置的功能。

    右击表名,选择导入。

    如果你仍然有问题,请参考本教程。将CSV文件导入到PostgreSQL表中

  • sivamani
    sivamani
    发布于 2021-12-01
    0 人赞同

    如何将CSV文件数据导入到PostgreSQL的表中

    Steps:

  • 需要在终端连接一个PostgreSQL数据库

     psql -U postgres -h localhost
    
  • 需要创建一个数据库

     create database mydb;
    
  • 需要创建一个用户

     create user siva with password 'mypass';
    
  • 与数据库连接

     \c mydb;
    
  • 需要创建一个模式

     create schema trip;
    
  • 需要创建一个表格

     create table trip.test(VendorID int,passenger_count int,trip_distance decimal,RatecodeID int,store_and_fwd_flag varchar,PULocationID int,DOLocationID int,payment_type decimal,fare_amount decimal,extra decimal,mta_tax decimal,tip_amount decimal,tolls_amount int,improvement_surcharge decimal,total_amount
    
  • 导入csv文件数据到postgresql

     COPY trip.test(VendorID int,passenger_count int,trip_distance decimal,RatecodeID int,store_and_fwd_flag varchar,PULocationID int,DOLocationID int,payment_type decimal,fare_amount decimal,extra decimal,mta_tax decimal,tip_amount decimal,tolls_amount int,improvement_surcharge decimal,total_amount) FROM '/home/Documents/trip.csv' DELIMITER ',' CSV HEADER;
    
  • 找到给定的表格数据

     select * from trip.test;
        
  • 为什么我们在复制命令上需要数据类型?我的意思是在步骤 7
    sal
    sal
    发布于 2021-12-01
    0 人赞同

    IMHO,最方便的方法是遵循" 将CSV数据导入postgresql,舒适的方式;-) ", using csvsql from csvkit ,它是一个可通过pip安装的Python包。

    链接腐烂是贪婪的!你所链接的文章已经失效了,这让我很不舒服 :(
    mountainclimber11
    你可能想说他的是py。
    对我来说,如果试图导入一个大的CSV,我会得到一个MemoryError,所以看起来它并没有流。
    sal
    @DavidC 有意思。你的文件有多大?你有多少内存?如果它不像看起来那样流,我建议在插入前将数据分块。
    该文件有5GB大小,而我有2GB内存。我放弃了,最后用一个脚本来生成CREATE TABLE和COPY命令。
    Vlad Dinulescu
    Vlad Dinulescu
    发布于 2021-12-01
    0 人赞同

    你也可以使用 pgfutter , or, even better, pgcsv .

    这些工具根据CSV的标题,从你那里创建表列。

    pgfutter有相当多的错误,我推荐pgcsv。

    Here's how to do it with pgcsv:

    sudo pip install pgcsv
    pgcsv --db 'postgresql://localhost/postgres?user=postgres&password=...' my_table my_file.csv
        
    Marc
    Marc
    发布于 2021-12-01
    0 人赞同

    在Python中,你可以使用这段代码来自动创建带有列名的PostgreSQL表。

    import pandas, csv
    from io import StringIO
    from sqlalchemy import create_engine
    def psql_insert_copy(table, conn, keys, data_iter):
        dbapi_conn = conn.connection
        with dbapi_conn.cursor() as cur:
            s_buf = StringIO()
            writer = csv.writer(s_buf)
            writer.writerows(data_iter)
            s_buf.seek(0)
            columns = ', '.join('"{}"'.format(k) for k in keys)
            if table.schema:
                table_name = '{}.{}'.format(table.schema, table.name)
            else:
                table_name = table.name
            sql = 'COPY {} ({}) FROM STDIN WITH CSV'.format(table_name, columns)
            cur.copy_expert(sql=sql, file=s_buf)
    engine = create_engine('postgresql://user:password@localhost:5432/my_db')
    df = pandas.read_csv("my.csv")
    df.to_sql('my_table', engine, schema='my_schema', method=psql_insert_copy)
    

    它的速度也比较快。我可以在大约4分钟内导入超过330万行。

    Mohammad Fallah
    Mohammad Fallah
    发布于 2021-12-01
    0 人赞同

    你可以创建一个Bash文件作为 import.sh (即你的CSV格式是一个制表符分隔符)。

    #!/usr/bin/env bash
    USER="test"
    DB="postgres"
    TBALE_NAME="user"
    CSV_DIR="$(pwd)/csv"
    FILE_NAME="user.txt"
    echo $(psql -d $DB -U $USER  -c "\copy $TBALE_NAME from '$CSV_DIR/$FILE_NAME' DELIMITER E'\t' csv" 2>&1 |tee /dev/tty)
    

    然后运行这个脚本。

    你的意思是 "你的CSV格式是一个制表符分隔符" ?
    Buffcoder
    Buffcoder
    发布于 2021-12-01
    0 人赞同

    你可以使用 熊猫 如果文件不是非常大的话,可以在库中使用。

    Be careful when using iter over 熊猫 dataframes. I am doing this here to demonstrate the possibility. One could also consider the pd.Dataframe.to_sql() function when copying from a dataframe to an SQL table.

    假设你已经创建了你想要的表,你可以。

    import psycopg2
    import pandas as pd
    data=pd.read_csv(r'path\to\file.csv', delimiter=' ')
    #prepare your data and keep only relevant columns
    data.drop(['col2', 'col4','col5'], axis=1, inplace=True)
    data.dropna(inplace=True)
    print(data.iloc[:3])
    conn=psycopg2.connect("dbname=db user=postgres password=password")
    cur=conn.cursor()
    for index,row in data.iterrows():
          cur.execute('''insert into table (col1,col3,col6)
        VALUES (%s,%s,%s)''', (row['col1'], row['col3'], row['col6'])
    cur.close()
    conn.commit()
    conn.close()
    print('\n db connection closed.')
        
    Rich Lysakowski PhD
    Rich Lysakowski PhD
    发布于 2021-12-01
    0 人赞同

    DBeaver社区版(dbeaver.io)使连接到数据库变得非常简单,然后导入CSV文件上传到PostgreSQL数据库。 它还可以轻松地发出查询,检索数据,并将结果集下载到CSV、JSON、SQL或其他常见的数据格式。

    它是一个为SQL程序员、DBA和分析师提供的FOSS多平台数据库工具,支持所有流行的数据库。MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto等。 它是TOAD for Postgres、TOAD for SQL Server或Toad for Oracle的一个可行的FOSS竞争者。

    我与DBeaver没有任何关系。 我喜欢它的价格(免费!)和完整的功能,但我希望他们能更多地开放这个DBeaver/Eclipse应用程序,并使其易于向DBeaver/Eclipse添加分析部件,而不是要求用户支付199美元的年度订阅费,只是为了在应用程序中直接创建图形和图表。 我的Java编码技能很生疏,我不想花几周时间重新学习如何构建Eclipse小工具,(只是发现DBeaver可能已经禁用了向DBeaver社区版添加第三方小工具的能力)。

    如果能了解如何真正使用DBeaver来导入CSV文件就更好了。无论如何,这可能会有帮助。 dbeaver.com/docs/wiki/Data-transfer
    Peter建议我把这个问题移到评论区。 "身为Java开发者的DBeaver高级用户能否提供一些关于创建分析小工具的步骤的见解,以便添加到DBeaver的社区版中?" 我想知道分析插件是否也是开源的,以及如何创建它们。
    Dewa Manandhar
    Dewa Manandhar
    发布于 2021-12-01
    0 人赞同

    你有3个选择来导入CSV文件到PostgreSQL。 首先,通过命令行使用COPY命令。

    第二,使用pgAdmin工具的导入/导出。

    第三,使用像Skyvia这样的云解决方案,它从一个在线位置(如FTP源或像Google Drive这样的云存储)获取CSV文件。

    你可以查看解释所有这些的文章,从 here .

    请审查 为什么不在提出问题时上传代码/错误的图片? (e.g., "图像应该只用于说明以下问题 别无他法 , 例如,提供用户界面的截图。 )并采取适当的 行动 (它也包括答案)。提前感谢。
    它至少适用于第一张图片。最后一张图片是不可读的(可能由于错误地被转换为JPEG(不适合截图)而失去了保真度)。
    suriruler
    suriruler
    发布于 2021-12-01
    0 人赞同

    创建一个表,并在CSV文件中拥有用于创建表的必要列。

  • Open postgres 并右击你想加载的目标表。选择导入并更新以下步骤 file options section

  • 现在浏览你的文件,寻找文件名

  • Select CSV in 格式

  • 编码为ISO_8859_5

    Now go to Misc. options . Check 页眉 并点击 import .

  • 0 人赞同

    如果你需要一个简单的机制来从文本/解析多行CSV内容中导入,你可以使用。

    CREATE TABLE t   -- OR INSERT INTO tab(col_names)
    SELECT
       t.f[1] AS col1
      ,t.f[2]::int AS col2
      ,t.f[3]::date AS col3
      ,t.f[4] AS col4
    FROM (
      SELECT regexp_split_to_array(l, ',') AS f
      FROM regexp_split_to_table(
    $$a,1,2016-01-01,bbb
    c,2,2018-01-01,ddd
    e,3,2019-01-01,eee$$, '\n') AS l) t;
    

    DBFiddle Demo

    Sandy
    Sandy
    发布于 2021-12-01
    0 人赞同

    通过使用任何客户端,我使用了 数据采集器 -我创建了一个新的数据库,然后在数据库的默认模式(公共)内,右键单击数据库,然后做 从文件中导入数据 .

    从位置上选择CSV文件,然后选择 Import File 格式为TSV → 确保数据CSV文件的每一列名称都有助于表的列名。

    Eduardo Pereira
    Eduardo Pereira
    发布于 2021-12-01
    0 人赞同

    我创建了一个小工具,可以非常容易地将 csv 文件导入PostgreSQL。这只是一个命令,它将创建和填充表,但不幸的是,目前,所有自动创建的字段都使用TEXT类型。

    csv2pg users.csv -d ";" -H 192.168.99.100 -U postgres -B mydatabase
    

    该工具可以在以下网站找到https://github.com/eduardonunesp/csv2pg

    你为相当于 psql -h 192.168.99.100 -U postgres mydatabase -c "COPY users FROM 'users.csv' DELIMITER ';' CSV" 的工具单独做了一个?我想它创建表格的部分很好,但由于每个字段都是文本,所以它不是超级有用。
    Ops,谢谢你的提醒。是的,我做到了,好在只花了几个小时,我学到了Go和pq以及Go中的数据库API等很酷的东西。
    Raos
    Raos
    发布于 2021-12-01
    0 人赞同

    我的想法是将你的CSV文件转换成SQL查询。

  • Open tool Convert CSV to Insert SQL Online
  • Paste or upload your CSV file in the Data Source pane
  • Scroll to the Table Generator panel
  • Click Copy to clipboard or Download
  • id,name
    1,Roberta
    2,Oliver
    

    The output of SQL queries:

    CREATE TABLE tableName
        id    varchar(300),
        name  varchar(300)