Como obtenho conteúdo textual de BLOB no Oracle SQL

112

Estou tentando ver em um console SQL o que está dentro de um Oracle BLOB.

Eu sei que ele contém um corpo de texto um tanto grande e quero apenas ver o texto, mas a consulta a seguir indica apenas que há um BLOB nesse campo:

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

o resultado que estou obtendo não é exatamente o que esperava:

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

Então, que tipo de encantamentos mágicos posso fazer para transformar o BLOB em sua representação textual?

PS: Estou apenas tentando olhar o conteúdo do BLOB de um console SQL (Eclipse Data Tools), não usá-lo no código.

Roland Tepp
fonte

Respostas:

141

Em primeiro lugar, você pode querer armazenar texto em colunas CLOB / NCLOB em vez de BLOB, que é projetado para dados binários (sua consulta funcionaria com um CLOB, a propósito).

A consulta a seguir permitirá que você veja os primeiros 32.767 caracteres (no máximo) do texto dentro do blob, desde que todos os conjuntos de caracteres sejam compatíveis (CS original do texto armazenado no BLOB, CS do banco de dados usado para VARCHAR2):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
Mac
fonte
3
Infelizmente, eu não controlo o esquema do banco de dados - só preciso dar uma olhada no blob ... Mas obrigado mesmo assim.
Roland Tepp
Obrigado Mac, isso funciona bem --- Mas qual é o propósito desse "dbms_lob.substr"? --- Apenas o uso de "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." parece me dar o mesmo resultado ...?
Rop
4
cast_to_varchar2 usa um RAW na entrada ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), que é limitado a 32767 bytes de comprimento ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Um BLOB não tem limitação de tamanho, então substr o trunca para um tamanho correto ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) se necessário.
Mac
34
Não funciona para mim - recebo "ORA-06502: PL / SQL: erro numérico ou de valor: comprimento da variável bruta muito longo". Posso colocar "2.000,1" após BLOB_FIELD para obter até 2.000 caracteres, mas nada além disso.
Marcos
2
se o valor for maior que 4000, haverá erros, pois esse é o valor máximo para strings em sql. você precisa adicionar substr (BLOB_FIELD, 4000, 1). Se você precisar de suporte de campo mais longo, use PL / SQL (até 32.000, eu acredito)
Sonic Soul
14

Você pode usar o SQL abaixo para ler os campos BLOB da tabela.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Imran Patel
fonte
Tenho coluna BLOB e onde os dados XML são compactados e armazenados na tabela, quando leio os dados, mostra apenas alguns números e não o texto xml real, o que devo fazer para ler os dados de texto XML da tabela.
BHUVANESH MOHANKUMAR
14

O SQL Developer também oferece esta funcionalidade:

Clique duas vezes na célula da grade de resultados e clique em editar:

insira a descrição da imagem aqui

Em seguida, na parte superior direita do pop-up, "Exibir como texto" (você pode até ver as imagens ..)

insira a descrição da imagem aqui

E é isso!

insira a descrição da imagem aqui

Ponteiro nulo
fonte
Essa é uma ótima dica - obrigado!
Ed Graham
7

Se você deseja pesquisar dentro do texto, em vez de visualizá-lo, isso 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;
Celeiro
fonte
qual é my_id aqui?
anjanb
Isso não está funcionando para mim, eu tenho a coluna BLOB e onde os dados XML são compactados e armazenados na tabela, quando eu leio os dados, mostra apenas alguns números e não o texto xml real, o que devo fazer para ler o texto XML dados da tabela.
BHUVANESH MOHANKUMAR
3

A resposta de Barn funcionou para mim com modificações porque minha coluna não está compactada. A solução rápida e suja:

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

Lutei com isso por um tempo e implementei a solução PL / SQL, mas depois percebi que no Toad você pode simplesmente clicar duas vezes na célula da grade de resultados, e ele abre um editor com conteúdo em texto. (estou no Toad v11)

insira a descrição da imagem aqui

Sonic Soul
fonte
1

Caso seu texto esteja compactado dentro do blob usando o algoritmo DEFLATE e seja muito grande, você pode usar esta função para lê-lo

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

Em seguida, execute select para obter o texto

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

Espero que isso ajude alguém.

Arsen Salamakha
fonte
1

Use este SQL para obter os primeiros 2.000 caracteres do BLOB.

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

Nota: Isso ocorre porque o Oracle não será capaz de lidar com a conversão de BLOB com mais de 2.000.

Swapnil Ingle
fonte
0

Você pode tentar isto:

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

No entanto, seria limitado a 4000 bytes

Reza Rahimi
fonte
-2

Funcionou para mim,

selecione lcase ((inserir (inserir (inserir (inserir (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) como FIELD_ID de TABLE_WITH_BLOB onde ID =' id de linha ';

Narendra Kalekar
fonte
Se isso funcionou para você, então você não está usando o Oracle, que é o OP e é por isso que as respostas precisam ter sintaxe válida do Oracle.
APC de
-4

Use a TO_CHARfunção.

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

Convertidos NCHAR, NVARCHAR2, CLOB, ou NCLOBdados para o conjunto de caracteres de banco de dados. O valor retornado é sempre VARCHAR2.

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