Bei dieser Frage geht es nicht um Bytea v. Oid v. Blobs v. Große Objekte usw.
Ich habe eine Tabelle, die ein Primärschlüsselfeld integer
und ein Feld bytea
enthält. Ich möchte Daten in das Feld bytea
eingeben. Dies kann vermutlich in einer der Sprachen PL/
Durchgeführt werden, und ich werde dies möglicherweise in Zukunft mit PL/Python
Ausführen.
Während ich noch teste und experimentiere, möchte ich einfach Daten aus einer Datei (auf dem Server) mit "Standard" -SQL-Anweisungen einfügen. Mir ist bekannt, dass nur Administratoren mit Schreibberechtigung auf dem Server Daten so einfügen können, wie ich es möchte. Darüber bin ich derzeit nicht besorgt, da Benutzer derzeit keine bytea
-Daten einfügen würden. Ich habe die verschiedenen StackExchange-Sites, das PostgreSQL-Archiv und das Internet im Allgemeinen durchsucht, konnte jedoch keine Antwort finden.
Bearbeiten: Dies Diskussion aus dem Jahr 2008 impliziert, dass das, was ich tun möchte, nicht möglich ist. Wie werden dann bytea
Felder verwendet?
Edit: This ähnliche Frage aus dem Jahr 2005 bleibt unbeantwortet.
Gelöst: Die auf der Website psycopg
angegebenen Details hier bildeten die Grundlage für eine von mir geschriebene Lösung in Python. Es kann auch möglich sein, Binärdaten mit PL/Python
In eine bytea
- Spalte einzufügen. Ich weiß nicht, ob dies mit "reinem" SQL möglich ist.
als Superuser:
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
wurde in 9.4 eingeführt, sodass Sie für ältere Versionen Folgendes benötigen würden:
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;$$;
dann:
insert into my_table(bytea_data) select bytea_import('/my/file.name');
Verwenden Sie pg_read_file('location_of file')::bytea
.
Zum Beispiel,
create table test(id int, image bytea);
insert into test values (1, pg_read_file('/home/xyz')::bytea);
Diese Lösung ist in Bezug auf die Laufzeit nicht gerade effizient, aber im Vergleich zum Erstellen eigener Header für COPY BINARY
Trivial einfach. Außerdem sind keine Bibliotheken oder Skriptsprachen außerhalb von Bash erforderlich.
Konvertieren Sie zunächst die Datei in einen Hexdump und verdoppeln Sie die Größe der Datei. xxd -p
Bringt uns ziemlich nahe, aber es wirft einige nervige Zeilenumbrüche auf, um die wir uns kümmern müssen:
xxd -p /path/file.bin | tr -d '\n' > /path/file.hex
Importieren Sie als Nächstes die Daten in PostgreSQL als sehr großes text
Feld. Dieser Typ fasst bis zu 1 GB pro Feldwert, daher sollten wir für die meisten Zwecke in Ordnung sein:
CREATE TABLE hexdump (hex text); COPY hexdump FROM '/path/file.hex';
Jetzt, da unsere Daten eine unbegründet große Hex-Zeichenfolge sind, verwenden wir PostgresQLs decode
, um sie in einen bytea
Typ zu bringen:
CREATE TABLE bindump AS SELECT decode(hex, 'hex') FROM hexdump;
Das Antwort mit xxd ist schön und für kleine Dateien sehr schnell. Unten ist ein Beispielskript, das ich verwende.
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
Verwenden Sie die Funktion Postgres COPY BINARY . Dies entspricht weitgehend Oracle externe Tabellen .
Hier erfahren Sie, wie Sie dies ohne Superuser-Berechtigungen tun können (z. B. bei Heroku).
\lo_import '/cygdrive/c/Users/Chloe/Downloads/Contract.pdf'
update contracts set contract = lo_get(:LASTOID) where id = 77;
Sie können \lo_list
Verwenden, um die großen Objekte anzuzeigen, und \lo_unlink
, Um sie zu löschen. Das Feld contract
in meinem Beispiel ist bytea
.
Column | Type |
contract | bytea |