Вопрос

Этот вопрос не о Bytea v. Oid v. Blobs v. Большие объекты и т. Д.

У меня есть таблица, содержащая первичный ключ integer поле и bytea поле. Я хотел бы ввести данные в bytea поле. Это может быть сделано одним из PL/ языки, и я могу сделать это с PL/Python в будущем.

Поскольку я все еще тестирую и экспериментирую, я просто хотел бы вставить данные из файла (на сервере), используя «стандартные» операторы SQL. Я знаю, что только администраторы с разрешения на запись на сервере смогут вставить данные так, как я хотел бы. Я не обеспокоен этим на этом этапе, так как пользователи не будут вставлять bytea Данные в настоящее время. Я искал различные сайты StackexChange, Archives PostgreSQL и Интернет, но не смог найти ответ.

Редактировать: Этот Обсуждение с 2008 года подразумевает, что то, что я хочу сделать, невозможно. Как bytea Поля использовались тогда?

Редактировать: Этот Аналогичный вопрос с 2005 года остается без ответа.

Решено: Предоставленные детали здесь на psycopg Веб -сайт предоставил основу для решения, которое я написал в Python. Также может быть возможно вставить бинарные данные в bytea столбец с использованием PL/Python. Анкет Я не знаю, возможно ли это с использованием «чистого» SQL.

Это было полезно?

Решение

как суперпользователь:

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');

Другие советы

Использовать pg_read_file('location_of file')::bytea.

Например,

create table test(id int, image bytea);
insert into test values (1, pg_read_file('/home/xyz')::bytea);

Руководство

Это решение не совсем эффективно с точки зрения времени выполнения, но это тривиально легко по сравнению с созданием собственных заголовков для COPY BINARY. Анкет Кроме того, это не требует никаких библиотек или языков сценариев за пределами Bash.

Во -первых, преобразовать файл в шестнадцатеричный размер, удваивая размер файла. xxd -p Подключите нас к довольно близко, но он добавляет некоторые раздражающие новшество, о которых мы должны позаботиться:

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

Далее импортируйте данные в PostgreSQL как очень большой text поле. Этот тип содержит до одного Великобритании за поле, поэтому мы должны быть в порядке для большинства целей:

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

Теперь, когда наши данные - это беспристрастно большая шестнадцатеричная строка, мы используем PostgreSQL decode Чтобы получить это в bytea тип:

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

А Ответьте 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

Используйте Postgres Копировать бинарный функция Это в целом эквивалентно Oracle внешние таблицы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top