Làm cách nào để nhập dữ liệu tệp CSV vào bảng PostgreSQL?


601

Làm cách nào tôi có thể viết một quy trình được lưu trữ để nhập dữ liệu từ tệp CSV và điền vào bảng?


18
Tại sao một thủ tục lưu trữ? SAO CHÉP thực hiện mánh khóe
Frank Heikens

1
Tôi có giao diện người dùng tải lên tệp csv, để kết nối điều này, tôi cần thủ tục được lưu trữ thực sự sao chép dữ liệu từ tệp cvs
vardhan

3
bạn có thể giải thích cách sử dụng COPY không?
vardhan

17
Bozhidar Batsov đã cung cấp cho bạn một liên kết đến một ví dụ, hướng dẫn sử dụng tốt cũng có thể giúp: postgresql.org/docs/8.4/interactive/sql-copy.html
Frank Heikens

Câu trả lời:


775

Hãy xem bài viết ngắn này .


Giải pháp diễn giải ở đây:

Tạo bảng của bạn:

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

Sao chép dữ liệu từ tệp CSV của bạn vào bảng:

COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' WITH (FORMAT csv);

46
thực sự sử dụng \ copy sẽ thực hiện thủ thuật tương tự nếu bạn không có quyền truy cập siêu người dùng; nó phàn nàn về Fedora 16 của tôi khi sử dụng COPY với tài khoản không root.
Asksw0rder

81
MIPO: bạn có thể chỉ ra những cột nào bạn có trong CSV bằng cách sử dụng zip_codes (col1, col2, col3). Các cột phải được liệt kê theo cùng thứ tự xuất hiện trong tệp.
David Pelaez

6
@ Asksw0rder có sao chép cùng một cú pháp không? bcoz Tôi đang gặp lỗi cú pháp với \ copy
JhovaniC

6
Tôi có nên bao gồm hàng tiêu đề?
bernie2436

116
Bạn có thể dễ dàng bao gồm hàng tiêu đề - chỉ cần thêm ĐẦU TIÊN trong các tùy chọn: COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV HEADER; postgresql.org/docs/9.1/static/sql-copy.html
Barrett Clark

222

Nếu bạn không có quyền sử dụng COPY(hoạt động trên máy chủ db), bạn có thể sử dụng \copythay thế (hoạt động trong máy khách db). Sử dụng ví dụ tương tự như Bozhidar Batsov:

Tạo bảng của bạn:

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

Sao chép dữ liệu từ tệp CSV của bạn vào bảng:

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

Bạn cũng có thể chỉ định các cột để đọc:

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

Xem tài liệu về COPY :

Đừng nhầm lẫn COPY với hướng dẫn psql \ copy. \ copy gọi COPY TỪ STDIN hoặc SAO CHÉP sang STDOUT, sau đó tìm nạp / lưu trữ dữ liệu trong một tệp có thể truy cập vào máy khách psql. Do đó, quyền truy cập tệp và quyền truy cập tùy thuộc vào máy khách thay vì máy chủ khi \ copy được sử dụng.

và lưu ý:

Đối với các cột định danh, lệnh COPY TỪ sẽ luôn ghi các giá trị cột được cung cấp trong dữ liệu đầu vào, giống như tùy chọn INSERT QUÁ TRÌNH GIÁ TRỊ HỆ THỐNG.


\ sao chép cử tri (ZIP, THÀNH PHỐ) TỪ '/Users/files/Doads/WOOD.TXT' DELIMITER ',' CSV Header; LRI: dữ liệu bổ sung sau cột dự kiến ​​cuối cùng TIẾP THEO: Cử tri COPY, dòng 2: "OH0012781511,87,26953, NHÀ NHÀ, SHERRY, LEIGH ,, 11/26 / 1965,08 / 19/1988, 211 N GARFIELD ST, BLOOMD ... "
JZ.

@JZ. Tôi đã có một lỗi tương tự. Đó là bởi vì tôi có thêm cột trống. Kiểm tra csv của bạn và nếu bạn có các cột trống, đó có thể là lý do.
alex bennett

5
Điều này hơi sai lệch: sự khác biệt giữa COPY\copykhông chỉ là các quyền và bạn không thể thêm một `` để làm cho nó hoạt động một cách kỳ diệu. Xem mô tả (trong ngữ cảnh xuất khẩu) tại đây: stackoverflow.com/a/1517692/157957
IMSoP

@IMSoP: bạn nói đúng, tôi đã thêm một đề cập đến máy chủ và máy khách để làm rõ
bjelli

@bjelli là \ sao chép chậm hơn sao chép? Tôi có một tệp 1,5 MB và một cá thể db.m4.lund trên RDS và đã vài giờ lệnh sao chép này đã chạy (ít nhất là 3).
Sebastian

79

Một cách nhanh chóng để làm điều này là với thư viện gấu trúc Python (phiên bản 0.15 trở lên hoạt động tốt nhất). Điều này sẽ xử lý việc tạo các cột cho bạn - mặc dù rõ ràng các lựa chọn mà nó đưa ra cho các kiểu dữ liệu có thể không phải là điều bạn muốn. Nếu nó không hoàn toàn làm những gì bạn muốn, bạn luôn có thể sử dụng mã 'tạo bảng' được tạo làm mẫu.

Đây là một ví dụ đơn giản:

import pandas as pd
df = pd.read_csv('mypath.csv')
df.columns = [c.lower() for c in df.columns] #postgres 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)

Và đây là một số mã chỉ cho bạn cách đặt các tùy chọn khác nhau:

# 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][1]

6
Bên cạnh đó, if_existsthông số có thể được thiết lập để thay thế hoặc append vào một bảng hiện có, ví dụdf.to_sql("fhrs", engine, if_exists='replace')
joelostblom

1
tên người dùng và mật khẩu: cần tạo Đăng nhập và gán DB cho người dùng. Nếu sử dụng pgAdmin, sau đó tạo "Đăng nhập / Vai trò nhóm" bằng GUI
Somnath Kadam

9
Pandas là một cách siêu chậm để tải vào sql (so với các tệp csv). Có thể là các đơn đặt hàng cường độ chậm hơn.
dùng48956

Đây có thể là một cách để ghi dữ liệu nhưng nó siêu chậm ngay cả với hàng loạt và khả năng tính toán tốt. Sử dụng CSV là một cách tốt để thực hiện điều này.
Ankit Singh

df.to_sql()thực sự rất chậm, bạn có thể sử dụng d6tstack.utils.pd_to_psql()từ d6tstack xem so sánh hiệu suất
citynorman

30

Bạn cũng có thể sử dụng pgAdmin, cung cấp GUI để thực hiện nhập. Điều đó được thể hiện trong chủ đề SO này . Ưu điểm của việc sử dụng pgAdmin là nó cũng hoạt động cho các cơ sở dữ liệu từ xa.

Giống như các giải pháp trước đây, bạn sẽ cần phải có bảng trên cơ sở dữ liệu. Mỗi người có giải pháp riêng nhưng những gì tôi thường làm là mở CSV trong Excel, sao chép các tiêu đề, dán đặc biệt với chuyển vị trên một bảng tính khác nhau, đặt loại dữ liệu tương ứng trên cột tiếp theo, sau đó chỉ cần sao chép và dán nó vào trình soạn thảo văn bản cùng với truy vấn tạo bảng SQL thích hợp như vậy:

CREATE TABLE my_table (
    /*paste data from Excel here for example ... */
    col_1 bigint,
    col_2 bigint,
    /* ... */
    col_n bigint 
)

1
vui lòng hiển thị một vài hàng mẫu của dữ liệu đã dán của bạn
dcorking

29

Hầu hết các giải pháp khác ở đây yêu cầu bạn tạo bảng trước / thủ công. Điều này có thể không thực tế trong một số trường hợp (ví dụ: nếu bạn có nhiều cột trong bảng đích). Vì vậy, cách tiếp cận dưới đây có thể có ích.

Cung cấp đường dẫn và số cột của tệp csv của bạn, bạn có thể sử dụng hàm sau để tải bảng của mình vào bảng tạm thời sẽ được đặt tên là target_table :

Hàng trên cùng được giả sử có tên cột.

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;

1
Xin chào Mehmet, cảm ơn câu trả lời bạn đã đăng nhưng khi tôi chạy mã của mình, tôi nhận được thông báo lỗi sau: ERROR: lược đồ "dữ liệu" không tồn tại
user2867432

user2867432 bạn cần thay đổi tên lược đồ mà bạn sử dụng cho phù hợp (ví dụ public:)
mehmet

Xin chào Mehmet, Cảm ơn giải pháp, nó hoàn hảo nhưng Điều này chỉ hoạt động nếu người dùng DB postgres là siêu người dùng, có cách nào để làm cho nó hoạt động mà không cần siêu người dùng không?
Geeme

Geeme: đọc "definer security" ở đây , nhưng tôi chưa sử dụng nó.
mehmet

Câu trả lời đẹp! Tôi sẽ không quá chung chung mặc dù trong mã của tôi để dễ đọc cho người khác.
Manohar Reddy Poreddy

19

Như Paul đã đề cập, nhập hoạt động trong pgAdmin:

nhấp chuột phải vào bảng -> nhập

chọn tập tin cục bộ, định dạng và mã hóa

đây là ảnh chụp màn hình GUI pgAdmin của Đức:

GUI nhập pgAdmin

điều tương tự bạn có thể làm với DbVisualizer (tôi có giấy phép, không chắc chắn về phiên bản miễn phí)

nhấp chuột phải vào bảng -> Nhập dữ liệu bảng ...

GUI nhập DbVisualizer


2
DBVisualizer mất 50 giây để nhập 1400 hàng với ba trường - và tôi phải chuyển mọi thứ trở lại từ Chuỗi thành bất cứ thứ gì đáng lẽ phải có.
Noumenon


10
  1. tạo bảng trước

  2. Sau đó sử dụng lệnh sao chép để sao chép chi tiết bảng:

sao chép tên_bảng (C1, C2, C3 ....)
từ 'đường dẫn đến tệp csv của bạn' dấu phân cách ',' tiêu đề csv;

Cảm ơn


3
Làm thế nào đây không phải là câu trả lời được chấp nhận? Tại sao tôi lại viết một kịch bản python khi cơ sở dữ liệu đã có lệnh để làm điều này?
Wes


8

Trải nghiệm cá nhân với PostgreSQL, vẫn đang chờ một cách nhanh hơn.

1. Tạo khung xương đầu tiên nếu tệp được lưu trữ cục bộ:

    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;

2. Khi \ path \ xxx.csv ở trên máy chủ, postgreSQL không có quyền truy cập vào máy chủ, bạn sẽ phải nhập tệp .csv thông qua chức năng pgAdmin được tích hợp.

Nhấp chuột phải vào tên bảng chọn nhập.

nhập mô tả hình ảnh ở đây

Nếu bạn vẫn có vấn đề, xin vui lòng tham khảo hướng dẫn này. http://www.postgresqltutorial.com/import-csv-file-into-posegresql-table/


6

Làm cách nào để nhập dữ liệu tệp CSV vào bảng PostgreSQL?

các bước:

  1. Cần kết nối cơ sở dữ liệu postgresql trong terminal

    psql -U postgres -h localhost
  2. Cần tạo cơ sở dữ liệu

    create database mydb;
  3. Cần tạo người dùng

    create user siva with password 'mypass';
  4. Kết nối với cơ sở dữ liệu

    \c mydb;
  5. Cần tạo lược đồ

    create schema trip;
  6. Cần tạo bảng

    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
    );
  7. Nhập dữ liệu tệp csv vào 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;
  8. Tìm dữ liệu bảng đã cho

    select * from trip.test;

5

IMHO, cách thuận tiện nhất là theo dõi " Nhập dữ liệu CSV vào postgresql, cách thoải mái ;-) ", sử dụng csvsql từ csvkit , đây là gói python có thể cài đặt qua pip.


3
Liên kết thối là phàm ăn! Bài viết bạn liên kết không còn hoạt động, điều này khiến tôi không thoải mái :(
chbrown

bạn có thể muốn đề cập rằng anh ấy là py.
Mountainclimber

1
Đối với tôi, tôi nhận được MemoryError nếu cố gắng nhập một CSV lớn để có vẻ như nó không phát trực tuyến.
DavidC

@DavidC Thú vị. Làm thế nào lớn là tập tin của bạn? Bạn có bao nhiêu kỷ niệm? Nếu nó không phát trực tuyến khi nó xuất hiện, tôi khuyên bạn nên kiểm tra dữ liệu trước khi chèn
sal

1
Tệp có kích thước 5 GB và tôi có bộ nhớ 2 GB. Tôi đã từ bỏ nó và sử dụng một tập lệnh để tạo các lệnh CREATE TABLE và COPY cuối cùng.
DavidC

3

Trong Python, bạn có thể sử dụng mã này để tạo bảng PostgreSQL tự động với tên cột:

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)

Nó cũng tương đối nhanh, tôi có thể nhập hơn 3,3 triệu hàng trong khoảng 4 phút.


2

Bạn cũng có thể sử dụng pgfutter , hoặc, thậm chí tốt hơn, pgcsv .

pgfutter khá lỗi, tôi muốn giới thiệu pgcsv.

Đây là cách thực hiện với pgcsv:

sudo pip install pgcsv
pgcsv --db 'postgresql://localhost/postgres?user=postgres&password=...' my_table my_file.csv

1

Nếu bạn cần cơ chế đơn giản để nhập từ CSV đa văn bản / phân tích cú pháp, bạn có thể sử dụng:

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;

Trình diễn DBFiddle


1

DBeaver Community Edition (dbeaver.io) khiến việc kết nối với cơ sở dữ liệu trở nên tầm thường, sau đó nhập tệp CSV để tải lên cơ sở dữ liệu PostgreQuery. Nó cũng giúp bạn dễ dàng đưa ra các truy vấn, truy xuất dữ liệu và tải xuống các tập kết quả thành CSV, JSON, SQL hoặc các định dạng dữ liệu phổ biến khác.

Nó là một công cụ cơ sở dữ liệu đa nền tảng FOSS dành cho các lập trình viên SQL, DBA và nhà phân tích hỗ trợ tất cả các cơ sở dữ liệu phổ biến: MySQL, PostgreQuery, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, v.v. Đây là đối thủ cạnh tranh FOSS khả thi với TOAD cho Postgres, TOAD cho SQL Server hoặc Toad cho Oracle.

Tôi không có liên kết với DBeaver. Tôi yêu giá (MIỄN PHÍ!) Và đầy đủ chức năng, nhưng tôi ước họ sẽ mở ứng dụng DBeaver / Eclipse này nhiều hơn và giúp dễ dàng thêm các tiện ích phân tích vào DBeaver / Eclipse, thay vì chỉ yêu cầu người dùng trả tiền cho đăng ký hàng năm $ 199 để tạo đồ thị và biểu đồ trực tiếp trong ứng dụng. Các kỹ năng mã hóa Java của tôi rất yếu và tôi không cảm thấy mất nhiều tuần để học cách xây dựng các widget Eclipse, (chỉ để thấy rằng DBeaver có thể đã vô hiệu hóa khả năng thêm các widget của bên thứ ba vào DBeaver Community Edition.)

Người dùng DBeaver có thể cung cấp năng lượng cho các nhà phát triển Java có thể cung cấp một số thông tin chi tiết về các bước để tạo các tiện ích phân tích để thêm vào Phiên bản Cộng đồng của DBeaver không?


Thật tuyệt khi hiểu cách sử dụng DBeaver để nhập tệp CSV. Dù sao, điều này có thể giúp: dbeaver.com/docs/wiki/Data-transfer
umbe1987

0

Tạo bảng và có các cột bắt buộc được sử dụng để tạo bảng trong tệp csv.

  1. Mở postgres và nhấp chuột phải vào bảng đích mà bạn muốn tải và chọn nhập và Cập nhật các bước sau trong phần tùy chọn tệp

  2. Bây giờ duyệt tập tin của bạn trong tên tệp

  3. Chọn csv ở định dạng

  4. Mã hóa thành ISO_8859_5

Bây giờ goto Misc. tùy chọn và kiểm tra tiêu đề và nhấp vào nhập khẩu.


0

Tôi đã tạo một công cụ nhỏ để nhập csvtệp vào PostgreSQL siêu dễ dàng, chỉ cần một lệnh và nó sẽ tạo và điền vào các bảng, thật không may, tại thời điểm tất cả các trường được tạo tự động sử dụng kiểu văn bản

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

Công cụ này có thể được tìm thấy trên https://github.com/eduardonunesp/csv2pg


Bạn đã tạo một công cụ riêng cho tương đương psql -h 192.168.99.100 -U postgres mydatabase -c "COPY users FROM 'users.csv' DELIMITER ';' CSV"? Tôi đoán phần mà nó tạo ra bảng là tốt, nhưng vì mọi trường đều là văn bản nên nó không siêu hữu ích
GammaGames

1
Ops, cảm ơn cho những người đứng đầu. Vâng, tôi đã làm điều đó, chỉ mất vài giờ và tôi đã học được những thứ hay ho trong Go và pq và API cơ sở dữ liệu trong Go.
Eduardo Pereira
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.