2013-08-30 4 views
3

나는이 같은 포스트 그레스 데이터베이스에 여러 .CSV 파일을 복사하는 SQL 스크립트를 쓰고 있어요 :.는 포스트 그레스에 여러 CSV 파일을 복사

COPY product(title, department) from 'ys.csv' CSV HEADER; 

난에 복사 할 파일을 여러 개 가지고 내가 원하지 않는 :

COPY product(title, department) from 'ys1.csv' CSV HEADER; 
COPY product(title, department) from 'ys2.csv' CSV HEADER; 
COPY product(title, department) from 'ys3.csv' CSV HEADER; 
COPY product(title, department) from 'ys4.csv' CSV HEADER; 
COPY product(title, department) from 'ys5.csv' CSV HEADER; 

여러 개의 복사 명령 대신 for 루프를 사용하고 싶습니다. 이것이 가능한가? 감사합니다

+0

아마도'do' 블록을 사용하고 있을까요? http://www.postgresql.org/docs/current/static/sql-do.html –

답변

8

리눅스 파이프에서 psql 파일 목록의 출력. copy는 표준 입력을 사용하십시오 : 다른 OS

2

에 해당하는 대한

cat /path_to/ys*.csv | psql -c 'COPY product(title, department) from stdin CSV HEADER' 

봐 나는 위의 대답을 시도했지만 두 개 이상의 파일로 작업 할 때 나는 오류가 발생했습니다. 나는 두 번째 파일에서 헤더를 잘라 내지 않았다고 생각한다.

나 FOT 일 :

# get filenames 
IMPFILES=(path/FileNamepart.csv) 

# import the files 
for i in ${IMPFILES[@]} 
    do 
     psql -U user -d database -c "\copy TABLE_NAME from '$i' DELIMITER ';' CSV HEADER" 
     # move the imported file 
     mv $i /FilePath 
    done 

를 내 경우에는 그것을 가져 Afer 즉 내가 모든 파일을 이동합니다. 오류가 발생하면 어디를 봐야하는지 알 수 있습니다. 그 위치에 새 파일이 있으면 스크립트를 다시 실행할 수 있습니다.

0

pg_ls_dir을 사용하여 파일 이름을 반복 할 수 있습니다.

DO $$ 

DECLARE file_path TEXT; -- Path where your CSV files are 
DECLARE fn_i TEXT; -- Variable to hold name of current CSV file being inserted 
DECLARE mytable TEXT; -- Variable to hold name of table to insert data into 

BEGIN 

    file_path := 'C:/Program Files/PostgreSQL/9.6/data/my_csvs/'; -- Declare the path to your CSV files. You probably need to put this in your PostgreSQL file path to avoid permission issues. 
    mytable := 'product(title,department)'; -- Declare table to insert data into. You can give columns too since it's just going into an execute statement. 

    CREATE TEMP TABLE files AS 
    SELECT file_path || pg_ls_dir AS fn -- get all of the files in the directory, prepending with file path 
    FROM pg_ls_dir(file_path); 

    LOOP  
     fn_i := (select fn from files limit 1); -- Pick the first file 
     raise notice 'fn: %', fn_i; 
     EXECUTE 'COPY ' || mytable || ' from ''' || fn_i || ''' with csv header'; 
     DELETE FROM files WHERE fn = fn_i; -- Delete the file just inserted from the queue 
     EXIT WHEN (SELECT COUNT(*) FROM files) = 0; 
    END LOOP; 

END $$; 
관련 문제