Wie erhalte ich Textinhalte von BLOB in Oracle SQL?

112

Ich versuche von einer SQL-Konsole aus zu sehen, was sich in einem Oracle BLOB befindet.

Ich weiß, dass es einen etwas großen Text enthält und ich möchte nur den Text sehen, aber die folgende Abfrage zeigt nur an, dass sich in diesem Feld ein BLOB befindet:

select BLOB_FIELD from TABLE_WITH_BLOB where ID = '<row id>';

Das Ergebnis ist nicht ganz das, was ich erwartet hatte:

    BLOB_FIELD
    -----------------------
    oracle.sql.BLOB@1c4ada9

Welche magischen Beschwörungsformeln kann ich also verwenden, um das BLOB in seine Textdarstellung umzuwandeln?

PS: Ich versuche nur, den Inhalt des BLOB von einer SQL-Konsole (Eclipse Data Tools) aus zu betrachten und nicht im Code zu verwenden.

Roland Tepp
quelle

Antworten:

141

Zunächst möchten Sie möglicherweise Text in CLOB / NCLOB-Spalten anstelle von BLOB speichern, das für Binärdaten ausgelegt ist (Ihre Abfrage würde übrigens mit einem CLOB funktionieren).

Mit der folgenden Abfrage können Sie die ersten 32767 Zeichen (höchstens) des Textes im Blob sehen, sofern alle Zeichensätze kompatibel sind (Original-CS des im BLOB gespeicherten Textes, CS der für VARCHAR2 verwendeten Datenbank):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
Mac
quelle
3
Leider kontrolliere ich das Datenbankschema nicht - ich muss nur in den Blob schauen ... Aber trotzdem danke.
Roland Tepp
Danke Mac, das funktioniert gut --- Aber was ist der Zweck dieser "dbms_lob.substr"? --- Nur die Verwendung von "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." scheint mir das gleiche Ergebnis zu liefern ...?
Rop
4
cast_to_varchar2 verwendet eine RAW-Eingabe ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), die auf 32767 Byte begrenzt ist ( docs.oracle.com/cd/E11882_01/appdev.112/e10472) /… ). Ein BLOB hat keine Größenbeschränkung, daher schneidet substr es bei Bedarf auf die richtige Größe ab ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ).
Mac
34
Funktioniert bei mir nicht - ich erhalte "ORA-06502: PL / SQL: numerischer oder Wertefehler: Länge der Rohvariablen zu lang". Ich kann "2000,1" nach BLOB_FIELD setzen, um bis zu 2000 Zeichen zu erhalten, aber nichts weiter.
Mark
2
Wenn der Wert länger als 4000 ist, werden Fehler ausgegeben, da dies der maximale Wert für Zeichenfolgen in SQL ist. Sie müssen substr hinzufügen (BLOB_FIELD, 4000, 1). Wenn Sie längere Feldunterstützung benötigen, verwenden Sie PL / SQL (bis zu 32000, glaube ich)
Sonic Soul
14

Sie können unten SQL verwenden, um die BLOB-Felder aus der Tabelle zu lesen.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Imran Patel
quelle
Ich habe eine BLOB-Spalte und wo die XML-Daten komprimiert und in der Tabelle gespeichert sind. Wenn ich die Daten lese, werden nur einige Zahlen und kein tatsächlicher XML-Text angezeigt. Was soll ich tun, um die XML-Textdaten aus der Tabelle zu lesen?
BHUVANESH MOHANKUMAR
14

SQL Developer bietet auch diese Funktionalität:

Doppelklicken Sie auf die Ergebnisrasterzelle und klicken Sie auf Bearbeiten:

Geben Sie hier die Bildbeschreibung ein

Dann oben rechts im Popup "Als Text anzeigen" (Sie können sogar Bilder sehen ..)

Geben Sie hier die Bildbeschreibung ein

Und das ist es!

Geben Sie hier die Bildbeschreibung ein

Null Zeiger
quelle
Das ist ein toller Tipp - danke!
Ed Graham
7

Wenn Sie im Text suchen möchten, anstatt ihn anzuzeigen, funktioniert dies:

with unzipped_text as (
  select
    my_id
    ,utl_compress.lz_uncompress(my_compressed_blob) as my_blob
  from my_table
  where my_id='MY_ID'
)
select * from unzipped_text
where dbms_lob.instr(my_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
Scheune
quelle
Was ist my_id hier?
Anjanb
Dies funktioniert bei mir nicht. Ich habe eine BLOB-Spalte und wo die XML-Daten komprimiert und in der Tabelle gespeichert sind. Wenn ich die Daten lese, werden nur einige Zahlen und kein tatsächlicher XML-Text angezeigt. Was soll ich tun, um den XML-Text zu lesen? Daten aus Tabelle.
BHUVANESH MOHANKUMAR
3

Die Antwort von Barn hat bei mir mit Änderungen funktioniert, da meine Spalte nicht komprimiert ist. Die schnelle und schmutzige Lösung:

select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
Pecos Bill
quelle
3

Ich hatte eine Weile damit zu kämpfen und implementierte die PL / SQL-Lösung, stellte jedoch später fest, dass Sie in Toad einfach auf die Ergebnisrasterzelle doppelklicken können und ein Editor mit Inhalten im Text angezeigt wird. (Ich bin auf Toad v11)

Geben Sie hier die Bildbeschreibung ein

Sonic Soul
quelle
1

Wenn Ihr Text mithilfe des DEFLATE-Algorithmus im Blob komprimiert ist und ziemlich groß ist, können Sie ihn mit dieser Funktion lesen

CREATE OR REPLACE PACKAGE read_gzipped_entity_package AS

FUNCTION read_entity(entity_id IN VARCHAR2)
  RETURN VARCHAR2;

END read_gzipped_entity_package;
/

CREATE OR REPLACE PACKAGE BODY read_gzipped_entity_package IS

FUNCTION read_entity(entity_id IN VARCHAR2) RETURN VARCHAR2
IS
    l_blob              BLOB;
    l_blob_length       NUMBER;
    l_amount            BINARY_INTEGER := 10000; -- must be <= ~32765.
    l_offset            INTEGER := 1;
    l_buffer            RAW(20000);
    l_text_buffer       VARCHAR2(32767);
BEGIN
    -- Get uncompressed BLOB
    SELECT UTL_COMPRESS.LZ_UNCOMPRESS(COMPRESSED_BLOB_COLUMN_NAME)
    INTO   l_blob
    FROM   TABLE_NAME
    WHERE  ID = entity_id;

    -- Figure out how long the BLOB is.
    l_blob_length := DBMS_LOB.GETLENGTH(l_blob);

    -- We'll loop through the BLOB as many times as necessary to
    -- get all its data.
    FOR i IN 1..CEIL(l_blob_length/l_amount) LOOP

        -- Read in the given chunk of the BLOB.
        DBMS_LOB.READ(l_blob
        ,             l_amount
        ,             l_offset
        ,             l_buffer);

        -- The DBMS_LOB.READ procedure dictates that its output be RAW.
        -- This next procedure converts that RAW data to character data.
        l_text_buffer := UTL_RAW.CAST_TO_VARCHAR2(l_buffer);

        -- For the next iteration through the BLOB, bump up your offset
        -- location (i.e., where you start reading from).
        l_offset := l_offset + l_amount;
    END LOOP;
    RETURN l_text_buffer;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('!ERROR: ' || SUBSTR(SQLERRM,1,247));
END;

END read_gzipped_entity_package;
/

Führen Sie dann select aus, um Text abzurufen

SELECT read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;

Hoffe das wird jemandem helfen.

Arsen Salamakha
quelle
1

Verwenden Sie diese SQL, um die ersten 2000 Zeichen des BLOB abzurufen.

SELECT utl_raw.cast_to_varchar2(dbms_lob.substr(<YOUR_BLOB_FIELD>,2000,1)) FROM <YOUR_TABLE>;

Hinweis: Dies liegt daran, dass Oracle die Konvertierung von BLOB mit einer Länge von mehr als 2000 nicht verarbeiten kann.

Swapnil Ingle
quelle
0

Sie können dies versuchen:

SELECT TO_CHAR(dbms_lob.substr(BLOB_FIELD, 3900)) FROM TABLE_WITH_BLOB;

Es wäre jedoch auf 4000 Byte begrenzt

Reza Rahimi
quelle
-2

Arbeitete für mich,

Wählen Sie lcase ((insert (insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) als FIELD_ID aus TABLE_WITH_BLOB wobei ID =' Zeilen-ID ';

Narendra Kalekar
quelle
Wenn dies für Sie funktioniert hat, verwenden Sie nicht Oracle, was das OP ist, und deshalb müssen die Antworten eine gültige Oracle-Syntax sein.
APC
-4

Verwenden Sie TO_CHARFunktion.

select TO_CHAR(BLOB_FIELD) from TABLE_WITH_BLOB where ID = '<row id>'

Wandelt NCHAR, NVARCHAR2, CLOB, oder NCLOBDaten in die Datenbank - Zeichensatz. Der zurückgegebene Wert ist immer VARCHAR2.

Alex
quelle
SELECT DBMS_LOB.SUBSTR (BLOB_FIELD) FROM TABLE_WITH_BLOB;
Sambhav