PostgreSQL bytea 열에 데이터를 삽입하는 방법은 무엇입니까?


37

이 질문은 bytea v. oid v. blobs v. large objects 등에 관한 것이 아닙니다.

기본 키 integer필드와 필드가 포함 된 테이블 이 bytea있습니다. bytea필드에 데이터를 입력하고 싶습니다 . 아마도 이것은 PL/언어 중 하나에 의해 수행 될 수 있으며, 앞으로이 작업을 수행 할 수 PL/Python있습니다.

여전히 테스트하고 실험하면서 "표준"SQL 문을 사용하여 파일 (서버의)에서 데이터를 삽입하고 싶습니다. 서버에 대한 쓰기 권한이있는 관리자 만 원하는 방식으로 데이터를 삽입 할 수 있다는 것을 알고 있습니다. 사용자가 bytea현재 데이터를 삽입하지 않기 때문에이 단계에서 걱정하지 않습니다 . 다양한 StackExchange 사이트, PostgreSQL Archives 및 인터넷을 일반적으로 검색했지만 답변을 찾지 못했습니다.

편집 : 2008 년 토론은 내가하고 싶은 일이 불가능하다는 것을 암시합니다. 그러면 bytea필드 는 어떻게 사용됩니까?

편집 : 2005 년부터 비슷한 질문은 답이 남아있다.

해결 : 제공된 자세한 여기psycopg웹 사이트는 내가 파이썬으로 작성한 솔루션의 기초를 제공했다. 를 bytea사용하여 이진 데이터를 열에 삽입 할 수도 있습니다 PL/Python. "순수한"SQL을 사용하여 이것이 가능한지 모르겠습니다.


1
psycopg 문서에 대한 링크가 끊어지고 편집이 거부 된 것 같습니다 (!?). 현재 위치는 다음과 같습니다 .
Aryeh Leib Taurog

@AryehLeibTaurog : 감사합니다. 변경된 텍스트가 하이퍼 링크인지 명확하지 않기 때문에 편집을 거부했습니다. 다시 수정하고 싶으면 승인하겠습니다.
SabreWolfy

@Andriy_M 왜 "이 수정은 게시물의 원래 의도와 다릅니다." (편집 informatik01에 의해 수행?)
기적 173

@ miracle173 : 제안 된 태그 중 일부가 관련이 없다는 인상을 받았기 때문에 (실제로 하나만 blob). 그게 실수라면 진심으로 사과드립니다.
Andriy M

@Andriy_M : 매뉴얼은 "typea"에 대해 말합니다. "SQL 표준은 BLOB 또는 BINARY LARGE OBJECT라고하는 다른 이진 문자열 유형을 정의합니다. 입력 형식은 bytea와 다르지만 제공된 함수와 연산자는 거의 동일합니다." 그래서 blob괜찮다고 생각 datafile합니다. 어쩌면 관련이 없습니다.
miracle173

답변:


26

수퍼 유저로서 :

create or replace function bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
begin
  select lo_import(p_path) into l_oid;
  select lo_get(l_oid) INTO p_result;
  perform lo_unlink(l_oid);
end;$$;

lo_get 9.4에 도입되었으므로 이전 버전의 경우 다음이 필요합니다.

create or replace function bytea_import(p_path text, p_result out bytea) 
                   language plpgsql as $$
declare
  l_oid oid;
  r record;
begin
  p_result := '';
  select lo_import(p_path) into l_oid;
  for r in ( select data 
             from pg_largeobject 
             where loid = l_oid 
             order by pageno ) loop
    p_result = p_result || r.data;
  end loop;
  perform lo_unlink(l_oid);
end;$$;

그때:

insert into my_table(bytea_data) select bytea_import('/my/file.name');

반대 과정을 위해, 나는 이것을 시도하지 않았지만 그것이 작동한다면 lo_export 가 당신이 필요한 전부입니다
Jack Douglas


15

이 솔루션은 런타임 측면에서 정확히 효율적이지는 않지만에 대한 자체 헤더를 만드는 것보다 쉽습니다 COPY BINARY. 또한 bash 외부의 라이브러리 또는 스크립팅 언어가 필요하지 않습니다.

먼저 파일을 16 진수 덤프로 변환하여 파일 크기를 두 배로 늘립니다. xxd -p우리를 꽤 가깝게 만들지 만, 우리가 처리해야 할 성가신 개행을 던졌습니다.

xxd -p /path/file.bin | tr -d '\n' > /path/file.hex

그런 다음 PostgreSQL의 데이터를 매우 큰 text필드 로 가져옵니다 . 이 유형은 필드 값당 최대 1GB를 보유하므로 대부분의 경우 괜찮습니다.

CREATE TABLE hexdump (hex text); COPY hexdump FROM '/path/file.hex';

이제 데이터는 크기가 큰 16 진 문자열이므로 PostgresQL을 사용 decode하여 bytea형식 으로 가져옵니다 .

CREATE TABLE bindump AS SELECT decode(hex, 'hex') FROM hexdump;

이 솔루션을 사용하면 파일에서 \ n 문자가 제거됩니다.
SabreWolfy

2
SabreWolfy : 아닙니다. 는 tr -d '\n'ASCII 16 진수 문자 (0-9 및 AF)로 입력되는 이진 콘텐츠를 인코딩 xxd의 출력에서 동작한다. xxd는 또한 출력을 사람이 읽을 수 있도록 정기적으로 라인 피드를 출력하지만이 경우에는 출력을 제거하기를 원합니다. 원본 데이터의 줄 바꿈은 16 진 형식이며 영향을받지 않습니다.
goodside

5

xxd대답 은 훌륭하고 작은 파일의 경우 매우 빠릅니다. 아래는 내가 사용하는 예제 스크립트입니다.

xxd  -p /home/user/myimage.png | tr -d '\n' > /tmp/image.hex
echo "
    -- CREATE TABLE hexdump (hex text);
    DELETE FROM hexdump;
    COPY hexdump FROM '/tmp/image.hex';

    -- CREATE TABLE bindump (binarydump bytea);
    DELETE FROM bindump;

    INSERT INTO bindump (binarydump)  
    (SELECT decode(hex, 'hex') FROM hexdump limit 1);

    UPDATE users 
    SET image= 
    (
        SELECT decode(hex, 'hex') 
        FROM hexdump LIMIT 1
    )  
    WHERE id=15489 ;
    " | psql mydatabase

1

Postgres COPY BINARY 기능을 사용하십시오 . 이것은 Oracle의 외부 테이블 과 대체로 동일합니다 .


감사. 제공 한 링크는 데이터가 ASCII 또는 PostgreSQL의 이진 테이블 형식이어야 함을 나타냅니다. 페이지 아래로 이진 테이블 형식이 먼저 COPY TO 명령으로 작성된다는 언급이 있습니다. 이러한 방법 중 하나를 사용하여 이진 파일 (PDF, 문서, 스프레드 시트)을 bytea열에 삽입 할 수 있습니까?
SabreWolfy

COPY BINARY에 대한 PostgreSQL 설명서 ( postgresql.org/docs/8.4/interactive/sql-copy.html )는 이진 데이터를 삽입 할 때 특수 파일 헤더가 필요함을 나타냅니다. 이 헤더를 빌드하고 바이너리 데이터에 추가해야합니까? 단순히 이진 데이터 문자열을 저장하기에는 다소 복잡해 보입니다.
SabreWolfy

흠, 이제 당신은 그것을 확신하지 못합니다. 나는 명령을 기억하고 그렇게 할 것이라고 생각했습니다. 아마도 PL / 그것을하는 유일한 방법 일 것입니다.
Gaius
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.