내 첫 게시물이기 때문에 나와 함께하시기 바랍니다.
PostgreSQL-9.2에서 COPY 명령을 실행하여 .txt 파일의 탭 구분 테이블을 PostgreSQL 데이터베이스에 추가하려고합니다.
COPY raw_data FROM '/home/Projects/TestData/raw_data.txt' WITH (DELIMITER ' ');
SQL 명령을 사용하여 데이터베이스에 "raw_data"라는 빈 테이블을 이미 만들었습니다.
CREATE TABLE raw_data ();
COPY
명령을 실행하려고하면 다음과 같은 오류 메시지가 계속 표시됩니다.
ERROR: extra data after last expected column
CONTEXT: COPY raw_data, line 1: " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ..."
(여기에있는 숫자는 열 머리글이라고 가정합니다)
DB 테이블을 만들 때 테이블 열을 지정하지 않았으므로 수동으로 800 또는 열을 입력하지 않아도되는지 잘 모르겠습니다.
이 문제를 해결하는 방법에 대한 제안 사항이 있으십니까?
다음은 .txt 파일의 예입니다.
1 2 3 4 5 6 7 8 9
binary1 1 1 0 1 1 1 1 1 1
binary2 1 0 0 1 0 1 1 0 0
binary3 1 0 1 1 1 0 0 1 0
binary4 1 1 1 1 0 1 0 1 0
빈 테이블은하지 않습니다. 입력 데이터의 구조와 일치하는 테이블이 필요합니다. 다음과 같은 것 :
CREATE TABLE raw_data (
col1 int
, col2 int
...
);
기본값이므로 tab
을 DELIMITER
로 선언 할 필요가 없습니다.
COPY raw_data FROM '/home/Projects/TestData/raw_data.txt';
당신이 말하는 열 800? 많은 열은 일반적으로 디자인에 문제가 있음을 나타냅니다. 어쨌든 CREATE TABLE
스크립트를 반 자동화하는 방법이 있습니다.
단순화 된 원시 데이터 가정
1 2 3 4 -- first row contains "column names"
1 1 0 1 -- tab separated
1 0 0 1
1 0 1 1
다른 DELIMITER
(가져 오기 데이터에서 전혀 발생하지 않는)를 정의하고 단일 text
열이있는 임시 스테이징 테이블로 가져 오십시오.
CREATE TEMP TABLE tmp_data (raw text);
COPY tmp_data FROM '/home/Projects/TestData/raw_data.txt' WITH (DELIMITER '§');
이 쿼리는 CREATE TABLE
스크립트를 만듭니다.
SELECT 'CREATE TABLE tbl (col' || replace (raw, E'\t', ' bool, col') || ' bool)'
FROM (SELECT raw FROM tmp_data LIMIT 1) t;
보다 일반적이고 안전한 쿼리 :
SELECT 'CREATE TABLE tbl('
|| string_agg(quote_ident('col' || col), ' bool, ' ORDER BY ord)
|| ' bool);'
FROM (SELECT raw FROM tmp_data LIMIT 1) t
, unnest(string_to_array(t.raw, E'\t')) WITH ORDINALITY c(col, ord);
보고:
CREATE TABLE tbl (col1 bool, col2 bool, col3 bool, col4 bool);
유효성을 확인한 후 실행하거나 결과를 신뢰할 수있는 경우 동적으로 실행하십시오.
DO
$$BEGIN
EXECUTE (
SELECT 'CREATE TABLE tbl (col' || replace(raw, ' ', ' bool, col') || ' bool)'
FROM (SELECT raw FROM tmp_data LIMIT 1) t
);
END$$;
그런 다음이 쿼리로 데이터를 INSERT
하십시오.
INSERT INTO tbl
SELECT (('(' || replace(replace(replace(
raw
, '1', 't')
, '0', 'f')
, E'\t', ',')
|| ')')::tbl).*
FROM (SELECT raw FROM tmp_data OFFSET 1) t;
또는 translate()
더 간단합니다.
INSERT INTO tbl
SELECT (('(' || translate(raw, E'10\t', 'tf,') || ')')::tbl).*
FROM (SELECT raw FROM tmp_data OFFSET 1) t;
문자열은 행 리터럴로 변환되어 새로 작성된 테이블 행 유형으로 캐스트되고 (row).*
분해됩니다.
다 했어요
이 모든 것을 plpgsql 함수에 넣을 수는 있지만 SQL 삽입을 방지해야합니다. (SO에는 여러 가지 관련 솔루션이 있습니다. 검색해보십시오.
db <> 바이올린 여기
오래된 SQL 바이올린
복사 명령에서 테이블을 직접 작성할 수 있습니다. COPY FROM '/path/to/csv/SourceCSVFile.csv'DELIMITERS ','CSV HEADER '와 같이 COPY의 HEADER 옵션을 직접 확인하십시오.