Come ottengo contenuti testuali da BLOB in Oracle SQL


112

Sto cercando di vedere da una console SQL cosa c'è all'interno di un Oracle BLOB.

So che contiene un corpo di testo piuttosto grande e voglio solo vedere il testo, ma la seguente query indica solo che c'è un BLOB in quel campo:

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

il risultato che sto ottenendo non è proprio quello che mi aspettavo:

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

Quindi che tipo di incantesimi magici posso fare per trasformare il BLOB nella sua rappresentazione testuale?

PS: Sto solo cercando di guardare il contenuto del BLOB da una console SQL (Eclipse Data Tools), non di usarlo nel codice.

Risposte:


141

Prima di tutto, potresti voler memorizzare il testo nelle colonne CLOB / NCLOB invece di BLOB, che è progettato per dati binari (la tua query funzionerebbe con un CLOB, tra l'altro).

La seguente query ti permetterà di vedere i primi 32767 caratteri (al massimo) del testo all'interno del blob, a condizione che tutti i set di caratteri siano compatibili (CS originale del testo memorizzato nel BLOB, CS del database usato per VARCHAR2):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';

3
Sfortunatamente, non controllo lo schema del database - ho solo bisogno di sbirciare nel blob ... Ma grazie comunque.
Roland Tepp

Grazie Mac, funziona bene --- Ma qual è lo scopo di "dbms_lob.substr"? --- Solo usando "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." sembra che mi dia lo stesso risultato ...?
Rop

4
cast_to_varchar2 accetta un RAW in input ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), che è limitato a 32767 byte di lunghezza ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Un BLOB non ha limiti di dimensione, quindi substr lo tronca a una dimensione corretta ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) se necessario.
Mac

34
Non funziona per me - ottengo "ORA-06502: PL / SQL: errore numerico o di valore: lunghezza variabile non elaborata troppo lunga". Posso mettere "2000,1" dopo BLOB_FIELD per ottenere fino a 2000 caratteri, ma nient'altro.
Marco

2
se il valore è più lungo di 4000, genererà errori poiché è il valore massimo per le stringhe in sql. è necessario aggiungere substr (BLOB_FIELD, 4000, 1). Se hai bisogno di un supporto sul campo più lungo usa PL / SQL (fino a 32000 credo)
Sonic Soul

14

È possibile utilizzare l'SQL di seguito per leggere i campi BLOB dalla tabella.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

Ho una colonna BLOB e dove i dati XML sono compressi e memorizzati nella tabella, quando leggo i dati, mostra solo alcuni numeri e non il testo xml effettivo, cosa devo fare per leggere i dati di testo XML dalla tabella.
BHUVANESH MOHANKUMAR

14

SQL Developer fornisce anche questa funzionalità:

Fare doppio clic sulla cella della griglia dei risultati e fare clic su Modifica:

inserisci qui la descrizione dell'immagine

Quindi nella parte in alto a destra del popup, "Visualizza come testo" (puoi anche vedere le immagini ..)

inserisci qui la descrizione dell'immagine

E questo è tutto!

inserisci qui la descrizione dell'immagine


È un ottimo suggerimento, grazie!
Ed Graham

7

Se vuoi cercare all'interno del testo, invece di visualizzarlo, funziona:

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;

cos'è my_id qui?
anjanb

Questo non funziona per me, ho una colonna BLOB e dove i dati XML sono compressi e memorizzati nella tabella, quando leggo i dati, mostra solo alcuni numeri e non il testo xml effettivo, cosa devo fare per leggere il testo XML dati dalla tabella.
BHUVANESH MOHANKUMAR

3

La risposta di Barn ha funzionato per me con la modifica perché la mia colonna non è compressa. La soluzione rapida e sporca:

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

3

Ho lottato con questo per un po 'e ho implementato la soluzione PL / SQL, ma in seguito ho capito che in Toad puoi semplicemente fare doppio clic sulla cella della griglia dei risultati e viene visualizzato un editor con contenuti in testo. (sono su Toad v11)

inserisci qui la descrizione dell'immagine


1

Nel caso in cui il tuo testo sia compresso all'interno del blob usando l'algoritmo DEFLATE ed è abbastanza grande, puoi usare questa funzione per leggerlo

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;
/

Quindi esegui select per ottenere il testo

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

Spero che questo possa aiutare qualcuno.


1

Usa questo SQL per ottenere i primi 2000 caratteri del BLOB.

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

Nota: questo perché Oracle non sarà in grado di gestire la conversione di BLOB di lunghezza superiore a 2000.


0

Puoi provare questo:

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

Tuttavia, sarebbe limitato a 4000 byte


-2

Ha funzionato per me

seleziona lcase ((insert (insert (insert (insert (hex (BLOB_FIELD)), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) come FIELD_ID da TABLE_WITH_BLOB dove ID =' id riga ';


Se questo ha funzionato per te, allora non stai usando Oracle, che è l'OP ed è per questo che le risposte devono essere una sintassi Oracle valida.
APC

-4

Usa la TO_CHARfunzione.

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

Converte NCHAR, NVARCHAR2, CLOB, o NCLOBdati sul set di caratteri database. Il valore restituito è sempre VARCHAR2.


SELEZIONA DBMS_LOB.SUBSTR (BLOB_FIELD) DA TABLE_WITH_BLOB;
Sambhav
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.