2012-04-13 3 views
2

Ich versuche, eine bytea-Spalte zu ändern, um den Typ oid zu haben, und behalte immer noch die Werte bei.Wandle eine Bytea-Spalte in OID um, während Werte beibehalten werden

Ich habe mit Anfragen wie versucht:

ALTER TABLE mytable ADD COLUMN mycol_tmp oid; 
UPDATE mytable SET mycol_tmp = CAST(mycol as oid); 
ALTER TABLE mytable DROP COLUMN mycol; 
ALTER TABLE mytable RENAME mycol_tmp TO mycol; 

Aber das gibt mir nur die Fehlermeldung:

ERROR: cannot cast type bytea to oid 

Gibt es eine Möglichkeit zu erreichen, was ich will?

+0

haben Related: http://stackoverflow.com/questions/29433041/understanding-cast-from-bytea-to-oid –

Antwort

4

Eine Spalte vom Typ Oid ist nur eine Referenz auf die binären Inhalte, die tatsächlich in der Tabelle pg_largeobject des Systems gespeichert sind. In Bezug auf die Speicherung, ein Oid eine 4-Byte-Integer. Auf der anderen Seite ist eine Spalte vom Typ Bytea der eigentliche Inhalt.

Um ein Bytea in ein großes Objekt zu übertragen, sollte ein neues großes Objekt mit der dateiähnlichen API großer Objekte erstellt werden: lo_create() um eine neue OID zu erhalten, dann lo_open() im Schreibmodus, dann schreibt mit lo_write() oder lowrite() und dann lo_close().

Dies kann nicht vernünftig mit nur einem Guss getan werden.

Grundsätzlich müssten Sie ein ~ 10 Zeilen Stück Code in der Sprache Ihrer Wahl (mindestens eine, die die API für große Objekte einschließlich plpgsql unterstützt) schreiben, um diese Konvertierung durchzuführen.

+0

Danke für Deine Antwort! Ich weiß, dass eine OID sich sehr von einer Bytea unterscheidet, aber ich vermutete, dass es eine Abfrage gab, mit der man den Inhalt der Bytea in eine OID-Referenz schreiben konnte. Es wird kein großes Problem sein, eine andere Sprache dafür zu verwenden. Danke noch einmal! – Petter

+0

Ich war falsch über das Fehlen einer serverseitigen Schreibfunktion zum Schreiben der Daten in das große Objekt, ich habe die Antwort entsprechend bearbeitet. Es stellt sich heraus, dass es LowRite heißt (nicht Lo_Write) und es wird nicht in den Dokumenten erwähnt, aber es könnte sicherlich für den Kopierschritt verwendet werden. –

0

Um das Problem zu lösen, habe ich erfolgreich Blob_Write-Verfahren aus Grace Batumbyas Blog: http://gbatumbya.wordpress.com/2011/06/.

+2

Bitte erläutern Sie mindestens die wichtigsten Bits. Link rot passiert. –

4

Ich denke, die beste Antwort kann bei Grace Batumbya's Blog, in verbis finden:

The algorithm is pretty simple, get the binary data, if it is null, return null. Else create a large object and in the lowrite function, pass it the binary value, instead of a path to a file.

The code for the procedure is below. Note that the lo_manage package should be installed for this to work.

create or replace function blob_write(lbytea bytea) 
    returns oid 
    volatile 
    language plpgsql as 
$f$ 
    declare 
     loid oid; 
     lfd integer; 
     lsize integer; 
begin 
    if(lbytea is null) then 
     return null; 
    end if; 

    loid := lo_create(0); 
    lfd := lo_open(loid,131072); 
    lsize := lowrite(lfd,lbytea); 
    perform lo_close(lfd); 
    return loid; 
end; 
$f$; 
CREATE CAST (bytea AS oid) WITH FUNCTION blob_write(bytea) AS ASSIGNMENT; 

So now the following code works: CREATE TABLE bytea_to_lo ( lo largeObj );

INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex')); 

ich es versucht habe und wie ein Zauber funktioniert.

2

Postgres 9.4 fügt eine built-in function dafür:

lo_from_bytea(loid oid, string bytea) 

Vom release notes:

  • Add SQL functions to allow [large object reads/writes][12] at arbitrary offsets (Pavel Stehule)

Für ältere Versionen, diese effizienter ist als das, was has been posted before:

CREATE OR REPLACE FUNCTION blob_write(bytea) 
    RETURNS oid AS 
$func$ 
DECLARE 
    loid oid := lo_create(0); 
    lfd int := lo_open(loid, 131072); -- = 2^17 = x2000 
    -- symbolic constant defined in the header file libpq/libpq-fs.h 
    -- #define INV_WRITE 0x00020000 
BEGIN 
    PERFORM lowrite(lfd, $1); 
    PERFORM lo_close(lfd); 
    RETURN loid; 
END 
$func$ LANGUAGE plpgsql VOLATILE STRICT; 

Der Modifikator STRICT ist intelligenter als die manuelle Verarbeitung von NULL.

SQL Fiddle.

Mehr in dieser verwandten Antwort:

0

Ich bin seine spät sicher, aber für irgendjemand in Zukunft mit dem gleichen Problem.

Ich konfrontiert auch ein ähnliches Problem, wo ich alte Daten in den Spalten des Textes direkt in den Spalten nicht als OIDs hatte. Und als ich versuchte, diese Daten mit aktualisierten Anwendung zu verwenden, bekam ich auch

Ich benutzte das Wissen dieses Threads, um dieses Problem zu lösen. Ich fühle stark, dass, wer stolpert über diese Frage würde sicherlich gerne einen Blick auf diese here

Verwandte Themen