¿Cómo obtengo contenido textual de BLOB en Oracle SQL?

112

Estoy tratando de ver desde una consola SQL lo que hay dentro de un BLOB de Oracle.

Sé que contiene un cuerpo de texto algo grande y solo quiero ver el texto, pero la siguiente consulta solo indica que hay un BLOB en ese campo:

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

el resultado que obtengo no es exactamente el que esperaba:

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

Entonces, ¿qué tipo de encantamientos mágicos puedo hacer para convertir el BLOB en su representación textual?

PD: Solo estoy tratando de ver el contenido del BLOB desde una consola SQL (Eclipse Data Tools), no usarlo en el código.

Roland Tepp
fuente

Respuestas:

141

En primer lugar, es posible que desee almacenar texto en columnas CLOB / NCLOB en lugar de BLOB, que está diseñado para datos binarios (por cierto, su consulta funcionaría con un CLOB).

La siguiente consulta le permitirá ver los primeros 32767 caracteres (como máximo) del texto dentro del blob, siempre que todos los conjuntos de caracteres sean compatibles (CS original del texto almacenado en el BLOB, CS de la base de datos utilizada para VARCHAR2):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
Mac
fuente
3
Desafortunadamente, no controlo el esquema de la base de datos, solo necesito echar un vistazo al blob ... Pero gracias de todos modos.
Roland Tepp
Gracias Mac, eso funciona bien --- ¿Pero cuál es el propósito de ese "dbms_lob.substr"? --- ¿Sólo el uso de "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." parece darme el mismo resultado ...?
Rop
4
cast_to_varchar2 toma una entrada RAW ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), que está limitada a 32767 bytes de longitud ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Un BLOB no tiene limitación de tamaño, por lo que substr lo trunca a un tamaño correcto ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) si es necesario.
Mac
34
No funciona para mí - obtengo "ORA-06502: PL / SQL: error numérico o de valor: longitud de la variable sin procesar demasiado larga". Puedo poner "2000,1" después de BLOB_FIELD para obtener hasta 2000 caracteres, pero nada más allá de eso.
Mark
2
si el valor es mayor que 4000 arrojará errores, ya que ese es el valor máximo para cadenas en sql. necesita agregar substr (BLOB_FIELD, 4000, 1). Si necesita soporte de campo más largo, use PL / SQL (hasta 32000, creo)
Sonic Soul
14

Puede utilizar el SQL siguiente para leer los campos BLOB de la tabla.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Imran Patel
fuente
Tengo una columna BLOB y donde los datos XML están comprimidos y almacenados en la tabla, cuando leo los datos, solo muestra algunos números y no el texto xml real, ¿qué debo hacer para leer los datos de texto XML de la tabla?
BHUVANESH MOHANKUMAR
14

SQL Developer también proporciona esta funcionalidad:

Haga doble clic en la celda de la cuadrícula de resultados y haga clic en editar:

ingrese la descripción de la imagen aquí

Luego, en la parte superior derecha de la ventana emergente, "Ver como texto" (incluso puede ver imágenes ..)

ingrese la descripción de la imagen aquí

¡Y eso es!

ingrese la descripción de la imagen aquí

puntero nulo
fuente
Ese es un gran consejo, ¡gracias!
Ed Graham
7

Si desea buscar dentro del texto, en lugar de verlo, esto funciona:

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;
Granero
fuente
¿Qué es my_id aquí?
anjanb
Esto no me funciona, tengo una columna BLOB y donde los datos XML están comprimidos y almacenados en la tabla, cuando leo los datos, solo muestra algunos números y no el texto xml real, ¿qué debo hacer para leer el texto XML? datos de la tabla.
BHUVANESH MOHANKUMAR
3

La respuesta de Barn funcionó para mí con modificaciones porque mi columna no está comprimida. La solución rápida y sucia:

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

Luché con esto por un tiempo e implementé la solución PL / SQL, pero luego me di cuenta de que en Toad puedes simplemente hacer doble clic en la celda de la cuadrícula de resultados y aparece un editor con contenido en texto. (estoy en Toad v11)

ingrese la descripción de la imagen aquí

Sonic Soul
fuente
1

En caso de que su texto esté comprimido dentro del blob usando el algoritmo DEFLATE y sea bastante grande, puede usar esta función para leerlo

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

Luego ejecuta seleccionar para obtener texto

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

Espero que esto ayude a alguien.

Arsen Salamakha
fuente
1

Utilice este SQL para obtener los primeros 2000 caracteres del BLOB.

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

Nota: Esto se debe a que Oracle no podrá manejar la conversión de BLOB con una longitud superior a 2000.

Swapnil Ingle
fuente
0

Puedes probar esto:

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

Sin embargo, estaría limitado a 4000 bytes

Reza Rahimi
fuente
-2

Trabajó para mi,

seleccione lcase ((insert (insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) como FIELD_ID de TABLE_WITH_BLOB donde ID =' ID de fila ';

Narendra Kalekar
fuente
Si esto funcionó para usted, entonces no está utilizando Oracle, que es el OP y es por eso que las respuestas deben ser una sintaxis válida de Oracle.
APC
-4

TO_CHARFunción de uso .

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

Conversos NCHAR, NVARCHAR2, CLOB, o NCLOBlos datos al conjunto de caracteres base de datos. El valor devuelto es siempre VARCHAR2.

Alex
fuente
SELECCIONE DBMS_LOB.SUBSTR (BLOB_FIELD) FROM TABLE_WITH_BLOB;
Sambhav