2011-06-14 3 views
3

COPY를 사용하여 테이블의 필드를 파일로 복사하고 있습니다. 이 필드는 압축 된 텍스트 파일이므로 이진 복사본을 사용합니다. 파일이 만들어지면 유일한 문제는 COPY가 필요없는 파일에 헤더와 예고편 (?)을 추가한다는 것입니다. 이것이 바뀔 수 있습니까? COPY가 데이터베이스에있는 그대로 필드를 넣을 수있는 매개 변수가 있습니까?postgres 복사 명령, 이진 파일

수동으로 원하지 않는 헤더를 삭제하면 zcat 또는 gunzip으로 파일을 추출 할 수 있습니다.

psql -d some_database -c \ 
"copy (select some_column from a_table where id=900) to stdout with BINARY;" > /tmp/tmp.gz 

을 그리고 나는

gunzip /tmp/tmp.gz 

어떤 아이디어를하고 싶지 :

나는 이런 식으로 뭔가를해야만하고 있는가?

답변

1

압축 된 텍스트를 데이터베이스에 바이너리로 저장하는 가장 좋은 방법이 있습니까?

긴 문자열이 자동으로 시스템에 의해 압축되어 있으므로 디스크에 물리적 요구 사항은 작을 수 있습니다 : documentation 긴 텍스트에 따르면 암시 적/자동으로 압축됩니다. 매우 긴 값은 배경 테이블에도 저장되므로 은 더 짧은 열 값에 대한 빠른 액세스를 방해하지 않습니다. 어쨌든 이 저장 될 수있는 가장 긴 문자열은 입니다. 약 1GB입니다.

+0

나는 :-) 가장 좋은 방법은 아니지만 난 그냥에 있고, 그것을하기로 결정 사람 아닙니다 동의 그것을 밖으로 꺼내십시오 :-) – user797710

1

나는 간단한 방법을 모른다 ... COPY는 가변 길이 헤더가있는 바이너리 형식이며 "잘라 내기"가 쉽지 않다. PG는 오히려 텍스트 중심이며, BYTEA 필드의 SELECT에서 "원시"(바이너리) 출력을 강제로 생성하는 방법은 없습니다.

텍스트로 된 16 진수 출력을 얻고 작은 프로그램 (C, perl 등)을 작성하여 \x000102414243에서 이진으로 변환 할 수 있습니다. 어려운 일이 아니다,하지만 간단하지

psql -t -q -c "select binaryfield from.. where ..." mydb | myhextobin > tmp.gz 

이 BTW, 그르의 대답은 매우 관련있다 (그리고 진수 형식은 PostgreSQL을 9.0이다).

추가 : 뭔가 유용 발견 만하면, 매우 깨끗하고도 완전하지는 않습니다 ... 그것은 제안되지

/* expects a pg hexadecimal string, in "\x....." format, and converts to binary*/ 
/* warning: no checks! it just ignores chars outside [0-9a-f] */ 
#include<stdio.h> 
int main() { 
    int x, pos, v; 
    char hex[3]={0,0,0}; 
    pos = 0; 
    while((x = getchar()) >= 0) { 
     if((x >='0' && x <= '9') || (x >= 'a' && x <= 'f')) { 
      hex[pos++] = (char)x; 
      if(pos == 2) { 
       sscanf(hex, "%x", &v); 
       putchar((char)v); 
       pos = 0; 
      } 
     } 
    } 
    return pos==0 ? 0 : 1; 
} 
0

는 PostgreSQL의 바이너리 형식을 디코딩을 시도합니다. 테스트 파일을 사용한다고해서 모든 것이 작동한다는 것은 아닙니다. 예를 들어, 특정 문자 시퀀스 (테스트 파일에 나타나지 않음)가 이스케이프 처리됩니다. 당신이 그것을 좋아하지 않을 수도 있지만 작동

+0

나는 그것을 얻지 않는다. 'b '가'bytea' 필드라면 (가정했을 때), 원시 이진 내용이 아닌 16 진수 문자열을 출력합니다. (나는 downvote하지 않았다) – leonbloy

+0

@leonbloy : 예, 데이터 유형이 지정되지 않았습니다. 실제 출력 형식은 bytea_output()에 따라 다르지만 기본 형식은 모두 인코딩 형식입니다. PostgreSQL은 blob 타입의 인라인을 지원하지 않고 큰 객체에 대한 참조 만 지원합니다. –

3

하나의 가능성 :

psql -At -c "select encode(content, 'base64') from t where ..." | base64 -d 

즉 base64로 같은 내용을 인쇄하고 디코딩. 현실은 psql이 읽을 수있는 출력을 만들어 내고 원시 이진 데이터를 해독하도록 설득하는 것이 의도적으로 어렵다는 것입니다.

필자가 원하는 경우 데이터베이스에 연결하여 원시 출력을 직접 인쇄 할 수있는 몇 가지 도구 (Perl/python 스크립트)를 작성할 수 있습니다.

COPY에 대한 "WITH BINARY"옵션은 단순한 바이너리 출력을 수행하는 것이 아니라, 사용하기에 다소 모호한 인코딩을 수행합니다.

+0

그것은 작동하고, 나는 그것을 좋아한다! 감사!! – user797710

0

클라이언트 드라이버가있는 언어와 PHP, python, ruby, perl, javascript, java 등의 bytea 유형을 읽을 수있는 언어를 사용하면이 작업을 쉽게 수행 할 수 있습니다. 그 언어로 이미 존재하는 gzip 라이브러리를 작성하고 파일을 작성하십시오.

데이터베이스 내에서 절차 언어를 사용하고 저장 프로 시저를 만들 수 있습니다. 요청한 파일 이름을 저장 프로 시저에 전달합니다.

+0

또는 base64 유형의'encode()'사용에 대한 Araqnid의 대답을 좋아합니다. – justis

0

복사 명령이 작업을 수행합니다. 당신은 말할 필요가 : --no-align--tuples-only.

압축 들어, psql의 사이에 gzip을 사용하여 파일을

psql의 --tuples-only --no-align -d some_database -c \ "copy (select some_column from a_table where id=900) to stdout with BINARY;" | gzip > /tmp/tmp.gz