CSV dosya verilerini PostgreSQL tablosuna nasıl aktarabilirim?


601

CSV dosyasından veri alan ve tabloyu dolduran saklı bir yordamı nasıl yazabilirim?


18
Neden saklı yordam? KOPYA hile yapar
Frank Heikens

1
Ben csv dosyasını yükleyen bir kullanıcı arayüzü var, bu bağlamak için aslında cvs dosyasından veri kopyalar saklı yordamı gerekir
vardhan

3
KOPYALAMA'nın nasıl kullanılacağını açıklayabilir misiniz?
vardhan

17
Bozhidar Batsov zaten bir örneğe bağlantı verdi, iyi kılavuz da yardımcı olabilir: postgresql.org/docs/8.4/interactive/sql-copy.html
Frank Heikens

Yanıtlar:


774

Bu kısa makaleye bir göz atın .


Burada açıklanan çözüm:

Masanızı oluşturun:

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

CSV dosyanızdan tabloya veri kopyalayın:

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

46
süper kullanıcı erişimine sahip değilseniz aslında \ copy aynı numarayı yapar; root olmayan bir hesapla COPY kullanırken Fedora 16'mdan şikayet ediyor.
asksw0rder

81
İPUCU: zip_codes (col1, col2, col3) kullanarak CSV'de hangi sütunlara sahip olduğunuzu belirtebilirsiniz. Sütunlar, dosyada göründükleri sırayla listelenmelidir.
David Pelaez

6
@ asksw0rder \ copy aynı sözdizimine sahip mi? bcoz \ copy
JhovaniC

6
Üstbilgi satırını eklemeli miyim?
bernie2436

116
Başlık satırını kolayca ekleyebilirsiniz - seçeneklere HEADER eklemeniz yeterlidir: COPY zip_codes FROM '/path/to/csv/ZIP_CODES.txt' DELIMITER ',' CSV HEADER; postgresql.org/docs/9.1/static/sql-copy.html
Barrett Clark

221

COPY(Db sunucusunda çalışan) kullanma izniniz yoksa \copy(db istemcisinde çalışan) bunun yerine kullanabilirsiniz . Bozhidar Batsov ile aynı örneği kullanarak:

Masanızı oluşturun:

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

CSV dosyanızdan tabloya veri kopyalayın:

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

Ayrıca, okunacak sütunları da belirleyebilirsiniz:

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

KOPYA belgelerine bakın :

COPY'yi psql yönergesi \ copy ile karıştırmayın. \ copy STDIN'den COPY veya STDOUT'a COPY'yi çağırır ve ardından verileri psql istemcisinin erişebileceği bir dosyaya getirir / depolar. Bu nedenle, \ copy kullanıldığında dosya erişilebilirliği ve erişim hakları sunucuya değil istemciye bağlıdır.

ve not:

Kimlik sütunları için, FROM FROM komutu her zaman giriş verilerinde sağlanan sütun değerlerini, örneğin INSERT OVERRIDING SYSTEM VALUE gibi yazar.


\ '/Users/files/Downloads/WOOD.TXT' DELIMITER ',' CSV HEADER 'dan seçmenleri (ZIP, CITY) kopyala; Hata ... "
JZ.

@JZ. Benzer bir hatayla karşılaştım. Çünkü fazladan boş sütunlarım vardı. CSV'nizi kontrol edin ve boş sütunlarınız varsa, nedeni bu olabilir.
alex bennett

5
Bu biraz yanıltıcı: izinler arasındaki fark COPYve \copyizinlerden çok daha fazlası ve sihirli bir şekilde çalışması için bir `` ekleyemezsiniz. Açıklamaya (ihracat bağlamında) bakın: stackoverflow.com/a/1517692/157957
IMSoP

@IMSoP: haklısın, açıklığa kavuşturmak için sunucu ve istemciden bahsetmiştim
bjelli

@bjelli \ copy kopyadan yavaş mı? RDS üzerinde 1.5MB dosya ve db.m4.large örneği var ve bu kopyalama komutunun çalıştığı saatler oldu (en az 3).
Sebastian

79

Bunu yapmanın hızlı bir yolu Python pandas kütüphanesidir (sürüm 0.15 veya üstü en iyi sonucu verir). Bu, sizin için sütunlar oluşturmayı işleyecektir - açıkçası veri türleri için yaptığı seçimler istediğiniz gibi olmayabilir. İstediğinizi tam olarak yapmazsa, her zaman şablon olarak oluşturulan 'tablo oluştur' kodunu kullanabilirsiniz.

İşte basit bir örnek:

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)

İşte size çeşitli seçenekleri nasıl ayarlayacağınızı gösteren bazı kodlar:

# 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
Ek olarak, if_existsparametre mevcut bir tabloyu değiştirmek veya eklemek için ayarlanabilir, örn.df.to_sql("fhrs", engine, if_exists='replace')
joelostblom

1
kullanıcı adı ve şifre: Giriş oluşturmalı ve kullanıcıya DB atamalıdır. PgAdmin kullanıyorsa, GUI kullanarak "Giriş / Grup rolü" oluşturun
Somnath Kadam

9
Pandalar sql (csv dosyaları vs) yüklemek için süper yavaş bir yoludur. Daha yavaş büyüklük siparişleri olabilir.
user48956

Bu, veri yazmanın bir yolu olabilir, ancak toplu iş ve iyi bilgi işlem gücü ile bile süper yavaştır. CSV'leri kullanmak bunu başarmanın iyi bir yoludur.
Ankit Singh

df.to_sql()gerçekten yavaş, sen kullanabilirsiniz d6tstack.utils.pd_to_psql()gelen d6tstack bkz performans karşılaştırması
citynorman

30

İçe aktarma işlemini yapmak için bir GUI sunan pgAdmin'i de kullanabilirsiniz. Bu SO iş parçacığında gösterilir . PgAdmin kullanmanın avantajı, uzak veritabanlarında da çalışmasıdır.

Önceki çözümlere çok benzer şekilde, tablonuzun veritabanında zaten olması gerekir. Her kişinin kendi çözümü vardır, ancak genellikle yaptığım şey CSV'yi Excel'de açmak, üstbilgileri kopyalamak, farklı bir çalışma sayfasına aktarma ile özel yapıştırmak, karşılık gelen veri türünü bir sonraki sütuna yerleştirip kopyalayıp bir metin düzenleyicisine yapıştırmaktır. birlikte uygun SQL tablo oluşturma sorgusu ile birlikte:

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

1
pls yapıştırılan verilerinizin birkaç örnek
satırını gösterir

29

Buradaki diğer çözümlerin çoğu, tabloyu önceden / manuel olarak oluşturmanızı gerektirir. Bu, bazı durumlarda pratik olmayabilir (örneğin, hedef tabloda çok sayıda sütun varsa). Dolayısıyla, aşağıdaki yaklaşım kullanışlı olabilir.

Csv dosyanızın yolunu ve sütun sayısını sağlayarak, tablonuzu şu şekilde adlandırılacak bir geçici tabloya yüklemek için aşağıdaki işlevi kullanabilirsiniz target_table :

En üst satırın sütun adlarına sahip olduğu varsayılır.

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
Merhaba Mehmet, gönderdiğin cevap için teşekkürler ama kodunu çalıştırdığımda aşağıdaki hata mesajını alıyorum: HATA: şema "veri" mevcut değil
user2867432

user2867432 buna göre kullandığınız şema adını değiştirmeniz gerekir (örn. public)
mehmet

Merhaba Mehmet, Çözüm için teşekkürler, mükemmel ama Bu sadece postgres DB kullanıcı süper kullanıcı ise çalışır, süper kullanıcı olmadan çalışması için herhangi bir yolu var mı?
Geeme

Geeme: Burada "güvenlik tanımlayıcısı" nı okudum , ama kendim kullanmadım.
mehmet

Güzel cevap! Ben diğerleri için okunabilirlik için kodumda olsa çok genel gitmiyorum.
Manohar Reddy Poreddy

19

Paul'un belirttiği gibi, ithalat, pgAdmin'de çalışır:

masaya sağ tıklayın -> içe aktar

yerel dosya, biçim ve kodlama seç

İşte bir alman pgAdmin GUI ekran görüntüsü:

pgAdmin içe aktarma GUI'si

DbVisualizer ile yapabileceğiniz benzer bir şey (Lisansım var, ücretsiz sürümden emin değilim)

bir tabloya sağ tıklayın -> Tablo Verilerini İçe Aktar ...

DbVisualizer içe aktarma GUI'si


2
DBVisualizer üç alanlı 1400 satır almak için 50 saniye sürdü - ve her şeyi bir String'den olması gereken her şeye geri dökmek zorunda kaldım.
Noumenon

19
COPY table_name FROM 'path/to/data.csv' DELIMITER ',' CSV HEADER;

10
  1. önce tablo oluştur

  2. Ardından tablo ayrıntılarını kopyalamak için copy komutunu kullanın:

Kopyalama tablo_adı (C1, C2, C3 ....)
dan sınırlayıcı '' CSV başlığı 'yol CSV dosyası';

Teşekkürler


3
Bu kabul edilen cevap nasıl değil? Veritabanı zaten bunu yapmak için bir komut aldığında neden bir python komut dosyası yazayım?
Wes


8

PostgreSQL ile kişisel deneyim, hala daha hızlı bir yol bekliyor.

1. Dosya yerel olarak depolanıyorsa önce tablo iskeletini oluşturun:

    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. \ path \ xxx.csv sunucudayken, postgreSQL'in sunucuya erişim izni yoktur, .csv dosyasını yerleşik pgAdmin işlevselliği aracılığıyla içe aktarmanız gerekir.

İçe aktarma işlemini seçmek için tablo adına sağ tıklayın.

resim açıklamasını buraya girin

Hâlâ sorun yaşıyorsanız, lütfen bu eğiticiye bakın. http://www.postgresqltutorial.com/import-csv-file-into-posgresql-table/


6

CSV dosya verilerini PostgreSQL tablosuna nasıl aktarabilirim?

adımlar:

  1. Terminalde postgresql veritabanını bağlamanız gerekiyor

    psql -U postgres -h localhost
  2. Veritabanı oluşturmanız gerekiyor

    create database mydb;
  3. Kullanıcı oluşturmanız gerekiyor

    create user siva with password 'mypass';
  4. Veritabanına bağlanın

    \c mydb;
  5. Şema oluşturmanız gerekiyor

    create schema trip;
  6. Tablo oluşturmanız gerekiyor

    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. Csv dosya verilerini postgresql dosyasına aktar

    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. Verilen tablo verilerini bulma

    select * from trip.test;

5

IMHO, en uygun yol "takip etmektir postgresql içine CSV verileri, konforlu yolu ;-) kullanarak," csvsql gelen csvkit pip üzerinden bir piton paketi yüklenebilir olduğunu.


3
Link çürüklüğü obur! Bağlantı verdiğiniz makale artık çalışmıyor, bu beni rahatsız ediyor :(
chbrown

onun py olduğunu belirtmek isteyebilirsiniz.
dağ tırmanışı

1
Benim için büyük bir CSV içe aktarmaya çalışıyorsa bir MemoryError alıyorum.
DavidC

@DavidC İlginç. Dosyanız ne kadar büyük? Ne kadar hafızanız var? Göründüğü gibi akış yapmazsa, yerleştirmeden önce verileri toparlamanızı öneririm
sal

1
Dosya 5GB boyutundaydı ve 2GB belleğim var. Ben vazgeçti ve sonunda CREATE TABLE ve COPY komutları oluşturmak için bir komut dosyası kullanın.
DavidC

3

Python'da bu kodu, sütun adlarıyla otomatik PostgreSQL tablosu oluşturmak için kullanabilirsiniz:

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)

Ayrıca nispeten hızlı, yaklaşık 4 dakika içinde 3,3 milyondan fazla satır içe aktarabilirim.


2

Ayrıca pgfutter veya daha da iyisi pgcsv kullanabilirsiniz .

pgfutter oldukça buggy, pgcsv şu.

Pgcsv ile nasıl yapılacağı aşağıda açıklanmıştır:

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

1

Metin / ayrıştırmalı çok satırlı CSV'den içe aktarmak için basit bir mekanizmaya ihtiyacınız varsa şunları kullanabilirsiniz:

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 Demosu


1

DBeaver Community Edition (dbeaver.io) bir veritabanına bağlanmayı ve ardından PostgreSQL veritabanına yüklemek için bir CSV dosyasını içe aktarmayı önemsiz kılar. Ayrıca CSV, JSON, SQL veya diğer yaygın veri formatlarına sorgu vermeyi, veri almayı ve sonuç kümelerini indirmeyi de kolaylaştırır.

Tüm popüler veritabanlarını destekleyen SQL programcıları, DBA'lar ve analistler için bir FOSS çok platformlu veritabanı aracıdır: MySQL, PostgreSQL, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, vb. Postgres için TOAD, SQL Server için TOAD veya Oracle için Toad için uygun bir FOSS rakibi.

DBeaver ile hiçbir bağlantım yok. Fiyat (ÜCRETSİZ!) Ve tam işlevselliği seviyorum, ancak keşke bu DBeaver / Eclipse uygulamasını daha fazla açacak ve kullanıcıların 199 $ yıllık abonelik için ödeme yapmasını istemek yerine DBeaver / Eclipse'a analitik widget'ları eklemeyi kolaylaştıracaklar doğrudan uygulama içinde grafikler ve grafikler oluşturmak için. Java kodlama becerilerim paslı ve Eclipse widget'larının nasıl oluşturulacağını öğrenmek için haftalar sürmekten hoşlanmıyorum (sadece DBeaver'ın DBeaver Topluluk Sürümü'ne üçüncü taraf widget'ları ekleme yeteneğini devre dışı bıraktığını bulmak için.)

Java geliştiricileri olan DBeaver yetkili kullanıcıları, DBeaver'ın Topluluk Sürümü'ne eklemek üzere analitik widget'ları oluşturma adımları hakkında bilgi verebilir mi?


Bir CSV dosyasını içe aktarmak için DBeaver'ın gerçekte nasıl kullanılacağını anlamak güzel olurdu. Her neyse, bu yardımcı olabilir: dbeaver.com/docs/wiki/Data-transfer
umbe1987

0

Tablo oluşturun ve csv dosyasında tablo oluşturmak için kullanılan gerekli sütunlara sahip olun.

  1. Postgres'i açın ve yüklemek istediğiniz hedef tabloya sağ tıklayın ve içe aktarmayı seçin ve dosya seçenekleri bölümünde aşağıdaki adımları güncelleyin

  2. Şimdi dosya adınıza dosyaya göz atın

  3. Biçimde csv seçin

  4. ISO_8859_5 olarak kodlama

Şimdi Misc. seçeneklerini işaretleyin ve başlığı kontrol edin ve içe aktar'ı tıklayın.


0

Ben csvsadece bir komut PostgreSQL süper kolay, dosya ithal küçük bir araç yarattı ve tabloları oluşturmak ve doldurmak ne yazık ki, şu anda otomatik olarak oluşturulan tüm alanlar TEXT türünü kullanır

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

Araç https://github.com/eduardonunesp/csv2pg adresinde bulunabilir


Eşdeğeri için ayrı bir araç yaptınız psql -h 192.168.99.100 -U postgres mydatabase -c "COPY users FROM 'users.csv' DELIMITER ';' CSV"mı? Tabloyu oluşturduğu bölüm güzel, ama her alan metin olduğu için çok kullanışlı değil
GammaGames

1
Ops, kafalar için teşekkürler. Evet, yaptım, sadece birkaç saat sürdü ve Go'da harika şeyler öğrendim ve Go'da pq ve veritabanı API'sı öğrendim.
Eduardo Pereira
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.