如何编写从CSV文件导入数据并填充表的存储过程?
看看这篇短文吧。
解决方案如下:
创建你的表:
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);
您还可以使用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
)
一种快速的方法是使用Python Pandas库(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
这里的大多数其他解决方案都要求您提前/手动创建表。这在某些情况下可能不实用(例如,如果目标表中有很多列)。因此,下面的方法可能会派上用场。
提供你的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
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;
$$ language plpgsql;
如果你没有权限使用COPY(在db服务器上工作),你可以使用\ COPY(在db客户端上工作)。以Bozhidar 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
参见COPY的文档:
不要将COPY与psql指令\ COPY混淆。\copy调用copy FROM STDIN或copy TO STDOUT,然后在psql客户端可访问的文件中获取/存储数据。因此,当使用\copy时,文件的可访问性和访问权限取决于客户端而不是服务器。
并注意:
对于标识列,COPY FROM命令将始终写入输入数据中提供的列值,就像INSERT选项覆盖SYSTEM VALUE一样。
正如Paul提到的,导入在pgAdmin中起作用:
右键单击表→导入
选择一个本地文件,格式和编码。
这是一个德文pgAdmin GUI截图:
使用DbVisualizer也可以做类似的事情(我有许可证,但不确定是否有免费版本)。
右键单击表→导入表数据…
使用下面的SQL代码:
copy table_name(atribute1,attribute2,attribute3...)
from 'E:\test.csv' delimiter ',' csv header
header关键字让DBMS知道CSV文件有一个带有属性的头。
欲了解更多信息,请访问导入CSV文件到PostgreSQL表。
创建一个表,并拥有用于在CSV文件中创建表所需的列。
打开postgres,右键单击要加载的目标表。在文件选项部分中选择导入和更新以下步骤 现在浏览文件查找文件名 选择CSV格式 编码为ISO_8859_5
现在去Misc。选项。检查标题并单击导入。
这是我个人使用PostgreSQL的经验,我还在等待更快的方法。
Create a table skeleton first if the file is stored locally: 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 ); COPY ur_table(id, log_id, proc_code, date, qty, name, price) FROM '\path\xxx.csv' DELIMITER ',' CSV HEADER; When the \path\xxx.csv file is on the server, PostgreSQL doesn't have the permission to access the server. You will have to import the .csv file through the pgAdmin built in functionality. Right click the table name and choose import.
如果您仍然有问题,请参考本教程:导入CSV文件到PostgreSQL表
首先创建一个表 然后使用copy命令复制表的详细信息: 复制table_name (C1,C2,C3....) 从'路径到您的CSV文件'分隔符,' CSV头;
注意:
列和顺序由C1,C2,C3..在SQL 标题选项只是从输入中跳过一行,而不是根据列的名称。
如果你需要一个简单的机制来导入文本/解析多行CSV内容,你可以使用:
CREATE TABLE t -- OR INSERT INTO tab(col_names)
AS
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演示
在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多万行。
如何将CSV文件数据导入PostgreSQL表
步骤:
Need to connect a PostgreSQL database in the terminal psql -U postgres -h localhost Need to create a database create database mydb; Need to create a user create user siva with password 'mypass'; Connect with the database \c mydb; Need to create a schema create schema trip; Need to create a table 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 ); Import csv file data to 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; Find the given table data select * from trip.test;
我创建了一个小工具,可以超级简单地将csv文件导入PostgreSQL。它只是一个命令,它将创建和填充表,但不幸的是,目前自动创建的所有字段都使用TEXT类型:
csv2pg users.csv -d ";" -H 192.168.99.100 -U postgres -B mydatabase
该工具可以在https://github.com/eduardonunesp/csv2pg上找到
您还可以使用pgfutter,或者更好的pgcsv。
这些工具根据CSV标题为您创建表列。
pgfutter有很多bug,我推荐pgcsv。
下面是如何使用pgcsv:
sudo pip install pgcsv
pgcsv --db 'postgresql://localhost/postgres?user=postgres&password=...' my_table my_file.csv
DBeaver社区版(DBeaver .io)使得连接到数据库,然后导入CSV文件上传到PostgreSQL数据库变得很简单。它还可以方便地发出查询、检索数据以及将结果集下载为CSV、JSON、SQL或其他常见数据格式。
它是一个面向SQL程序员、dba和分析师的自由/开源多平台数据库工具,支持所有流行的数据库:MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL Server、Sybase、MS Access、Teradata、Firebird、Hive、Presto等。对于Postgres的TOAD, SQL Server的TOAD,或者Oracle的TOAD,它是一个可行的自由/开源软件竞争对手。
I have no affiliation with DBeaver. I love the price (FREE!) and full functionality, but I wish they would open up this DBeaver/Eclipse application more and make it easy to add analytics widgets to DBeaver / Eclipse, rather than requiring users to pay for the $199 annual subscription just to create graphs and charts directly within the application. My Java coding skills are rusty and I don't feel like taking weeks to relearn how to build Eclipse widgets, (only to find that DBeaver has probably disabled the ability to add third-party widgets to the DBeaver Community Edition.)
您可以创建一个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)
然后运行这个脚本。
如果文件不是很大,可以使用Pandas库。
在Pandas数据框架上使用iter时要小心。我这样做是为了证明这种可能性。当从数据帧复制到SQL表时,也可以考虑使用pd.Dataframe.to_sql()函数。
假设你已经创建了你想要的表,你可以:
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.')
你有3个选项来导入CSV文件到PostgreSQL: 首先,通过命令行使用COPY命令。
其次,使用pgAdmin工具的导入/导出。
第三,使用像Skyvia这样的云解决方案,从在线位置(如FTP源)或云存储(如谷歌驱动器)获取CSV文件。
你可以从这里查看解释所有这些的文章。
这些都是很好的答案,但对我来说太复杂了。我只需要在postgreSQL中加载一个CSV文件,而不需要先创建一个表。
这是我的方法:
库
import pandas as pd
import os
import psycopg2 as pg
from sqlalchemy import create_engine
使用环境变量获取密码
password = os.environ.get('PSW')
创建引擎
engine = create_engine(f"postgresql+psycopg2://postgres:{password}@localhost:5432/postgres")
发动机需求分解:
Engine = create_engine(dialect+驱动程序://用户名:password@host:端口/数据库)
分解
Postgresql +psycopg2 =方言+驱动程序 Postgres =用户名 Password =来自环境变量的密码。如果需要,可以输入密码,但不建议输入 Localhost = host 5432 = port Postgres =数据库
获取您的CSV文件路径,我不得不使用编码方面。原因可以在这里找到
data = pd.read_csv(r"path, encoding= 'unicode_escape')
发送数据到Postgress SQL:
data.to_sql('test', engine, if_exists='replace')
分解
Test =你想要的表名 引擎=上面创建的引擎。也就是我们的联系 if_exists =将替换旧表。请谨慎使用。
在一起:
import pandas as pd
import os
import psycopg2 as pg
from sqlalchemy import create_engine
password = os.environ.get('PSW')
engine = create_engine(f"postgresql+psycopg2://postgres:{password}@localhost:5432/postgres")
data = pd.read_csv(r"path, encoding= 'unicode_escape')
data.to_sql('test', engine, if_exists='replace')
推荐文章
- django test app error -在创建测试数据库时出现错误:创建数据库的权限被拒绝
- Postgres唯一约束与索引
- 使用电子邮件地址为主键?
- 选择postgres中字段的数据类型
- 如何在PostgreSQL中查看视图的CREATE VIEW代码?
- 错误:没有唯一的约束匹配给定的键引用表"bar"
- 如何使用新的PostgreSQL JSON数据类型中的字段进行查询?
- 如何彻底清除和重新安装postgresql在ubuntu?
- 分组限制在PostgreSQL:显示每组的前N行?
- IN与PostgreSQL中的ANY运算符
- PSQLException:当前事务被中止,命令被忽略,直到事务块结束
- 添加布尔列到表集默认
- 库未加载:/usr/local/opt/readline/lib/libreadline.6.2.dylib
- 如何将这个字典列表转换为csv文件?
- Python导入csv到列表