Как вставить (файл) данные в столбец PostgreSQL Bytea?
-
16-10-2019 - |
Вопрос
Этот вопрос не о 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 внешние таблицы.