CSV 파일에서 헤더가있는 PostgreSQL 테이블로 CSV 파일을 복사하는 방법은 무엇입니까?


93

CSV 파일을 Postgres 테이블에 복사하고 싶습니다. 이 테이블에는 약 100 개의 열이 있으므로 필요하지 않은 경우 다시 작성하고 싶지 않습니다.

\copy table from 'table.csv' delimiter ',' csv;명령을 사용하고 있지만 테이블이 생성되지 않으면 ERROR: relation "table" does not exist. 빈 테이블을 추가해도 오류가 발생하지 않지만 아무 일도 일어나지 않습니다. 이 명령을 두세 번 시도했는데 출력이나 메시지가 없었는데 PGAdmin을 통해 확인했을 때 테이블이 업데이트되지 않았습니다.

내가하려는 것처럼 헤더가 포함 된 테이블을 가져 오는 방법이 있습니까?


2
당신의 테이블 이름은 table? 매우 혼란 스럽습니다. 테이블이 존재합니까, 아니면 CSV를 기반으로 생성 하시겠습니까? (당신은 할 수 없습니다)
wildplasser

1
음, 다른 이름으로 이름을 지정했지만이 예에서는 테이블이라고합니다. 나는 그것의 존재 유무에 관계없이 나는 또한 \copy table(column1, column2, ...) from 'table.csv' delimiter ',' csv;운없이 시도했다 . 이상적으로는 CSV만으로 테이블을 만들고 해당 파일의 헤더를 사용할 수 있습니다.
Stanley Cup Phil


2
큰 csv를 postgres 테이블로 전환하려는 모든 사람에게주의를 기울이십시오. postgres는 단일 테이블에서 1600 개 열로 제한됩니다. 테이블을 1600 열 크기의 테이블로 청크 한 다음 나중에 조인 할 수 없습니다. db를 재 설계해야합니다.
Achekroud

파이썬을 사용할 수 있다면 d6tstack 을 사용할 수 있습니다 . 스키마 변경도 처리합니다.
citynorman

답변:


135

이것은 효과가 있었다. 첫 번째 행에는 열 이름이 있습니다.

COPY wheat FROM 'wheat_crop_data.csv' DELIMITER ';' CSV HEADER

5
이 명령의 문제점은 DB 수퍼 유저가되어야한다는 것입니다. \ copy는 일반 사용자로도 작동합니다
Exocom 2014

29
COPY테이블을 만들거나 열을 추가하지 않고 기존 열이있는 기존 테이블에 행을 추가합니다. 아마도 질문자는 ~ 100 개의 열 생성을 자동화하기를 원 COPY하며 최소한 PG 9.3부터이 기능이 없습니다.
Daniel Vérité 2014

2
@Exocom 좋은 캐치. 내가 사용하는 postgres 시스템의 DB에 대한 관리자 또는 수퍼 유저가 아니기 때문에 (pgadmin은 내가 사용하는 데이터베이스의 소유자를 만들고 제한된 권한 / 역할을 부여합니다)`\ COPY '를 사용해야합니다. 건배
G. CITO

2
@Daniel 나는 사용자의 테이블이 이미 존재하고 필요한 모든 열이 있고 단순히 데이터 를 원한다는 것을 이해 했습니다ADD .
G. CITO

있어 syntax error at or near "HEADER" LINE 2: delimiter ',' CSV HEADERAWS의 적색 편이에.
Mithril

24

Python 라이브러리 pandas를 사용하면 열 이름을 쉽게 만들고 csv 파일에서 데이터 유형을 추론 할 수 있습니다.

from sqlalchemy import create_engine
import pandas as pd

engine = create_engine('postgresql://user:pass@localhost/db_name')
df = pd.read_csv('/path/to/csv_file')
df.to_sql('pandas_db', engine)

if_exists매개 변수, 예를 바꾸거나 기존 테이블에 추가하도록 설정할 수 있습니다 df.to_sql('pandas_db', engine, if_exists='replace'). 이것은 추가 입력 파일 유형, 여기여기 문서에서도 작동합니다 .


1
나는 pd.DataFrame.from_csv가 나에게 덜 문제를 준다는 것을 알지만이 대답은 이것을하는 가장 쉬운 방법 인 IMO입니다.
brock

사실, pd.read_excel대신을 입력 한 이유를 모르겠습니다 pd.read_csv. 답변을 업데이트했습니다.
joelostblom 2015 년

1
이것은 큰 CSV를 저장할 테이블을 미리 만들고 싶지 않을 때 환상적인 솔루션입니다. 참고로 Postgres는 테이블에서 1600 개의 열만 사용할 수 있습니다. 분명히 다른 DB 엔진은 더 많은 것을 허용합니다. 이 합의가 아직 역학으로 필터링되지는 않았지만 이렇게 많은 열을 갖는 것은 SQL 형식이 좋지 않은 것 같습니다.
Achekroud

1
기본적 df.to_sql()으로 매우 느리므로 속도를 높이려면 d6tstack 을 사용할 수 있습니다 . 스키마 변경도 처리합니다.
citynorman

13

허가없이 터미널에 의한 대안

NOTES의에서 페이지 문서

경로는 클라이언트의 작업 디렉토리가 아니라 서버 프로세스의 작업 디렉토리 (일반적으로 클러스터의 데이터 디렉토리)에 상대적으로 해석됩니다.

따라서 전체적으로 psql또는 다른 클라이언트를 사용 하거나 로컬 서버에서도 문제가 있습니다 ... 그리고 다른 사용자를 위해 COPY 명령을 표현하는 경우 예를 들어. Github README에서 독자는 문제가 있습니다 ...

클라이언트 권한으로 상대 경로 를 표현하는 유일한 방법 은 STDIN을 사용하는 것 입니다 .

STDIN 또는 STDOUT을 지정하면 클라이언트와 서버 간의 연결을 통해 데이터가 전송됩니다.

여기에 기억 된 대로 :

psql -h remotehost -d remote_mydb -U myuser -c \
   "copy mytable (column1, column2) from STDIN with delimiter as ','" \
   < ./relative_path/file.csv

3

나는이 기능을 문제없이 한동안 사용하고있다. csv 파일에있는 숫자 열만 제공하면 첫 번째 행에서 헤더 이름을 가져 와서 테이블을 만듭니다.

create or replace function data.load_csv_file
    (
        target_table  text, -- name of the table that will be created
        csv_file_path text,
        col_count     integer
    )

    returns void

as $$

declare
    iter      integer; -- dummy integer to iterate columns with
    col       text; -- to keep column names in each iteration
    col_first text; -- first column name, e.g., top left corner on a csv file or spreadsheet

begin
    set schema 'data';

    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_file_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 // using quote_ident or %I does not work here!?
    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;

set schema 'data';어떤 경우 든 변경 하는 것을 잊지 마십시오
mehmet

0

기본 DB 가져 오기 명령을 사용하기 때문에 테이블을 생성하고 pd.to_sql ()보다 빠른 d6tstack 을 사용할 수 있습니다 . Postgres와 MYSQL 및 MS SQL을 지원합니다.

import pandas as pd
df = pd.read_csv('table.csv')
uri_psql = 'postgresql+psycopg2://usr:pwd@localhost/db'
d6tstack.utils.pd_to_psql(df, uri_psql, 'table')

또한 여러 CSV 가져 오기, 데이터 스키마 변경 해결 및 / 또는 db에 쓰기 전에 팬더 (예 : 날짜)로 전처리하는 데 유용합니다. 자세한 내용은 예제 노트북을 참조하십시오.

d6tstack.combine_csv.CombinerCSV(glob.glob('*.csv'), 
    apply_after_read=apply_fun).to_psql_combine(uri_psql, 'table')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.