web-dev-qa-db-fra.com

Comment obtenir du contenu textuel de BLOB dans Oracle SQL

J'essaie de voir à partir d'une console SQL ce qu'il y a dans un BLOB Oracle.

Je sais qu'il contient un corps de texte assez volumineux et je souhaite simplement voir le texte, mais la requête suivante indique uniquement qu'il existe un BLOB dans ce champ:

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

le résultat obtenu n'est pas tout à fait ce à quoi je m'attendais:

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

Alors, quel genre d'incantations magiques puis-je faire pour transformer le BLOB en sa représentation textuelle?

PS: J'essaie simplement de regarder le contenu du BLOB à partir d'une console SQL (Eclipse Data Tools) et de ne pas l'utiliser dans le code.

93
Roland Tepp

Tout d’abord, vous souhaiterez peut-être stocker du texte dans des colonnes CLOB/NCLOB au lieu de BLOB, conçu pour les données binaires (votre requête fonctionnerait avec un CLOB, en passant).

La requête suivante vous permettra de voir les 32 767 premiers caractères (au plus) du texte à l'intérieur du blob, à condition que tous les jeux de caractères soient compatibles (le CS d'origine du texte stocké dans le BLOB, le CS de la base de données utilisée pour VARCHAR2):

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

Vous pouvez utiliser le code SQL ci-dessous pour lire les champs BLOB de la table.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
12
Imran Patel

Si vous voulez chercher dans le texte plutôt que de le voir, ceci fonctionne:

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;
5
Barn

J'ai eu du mal avec cela pendant un moment et j'ai implémenté la solution PL/SQL, mais plus tard, j'ai réalisé que dans Toad, vous pouvez simplement cliquer deux fois sur la cellule de la grille de résultats pour afficher un éditeur avec un contenu texte. (je suis sur crapaud v11)

enter image description here

3
Sonic Soul

SQL Developer fournit également cette fonctionnalité:

Double-cliquez sur la cellule de la grille de résultats, puis cliquez sur modifier:

 enter image description here

Puis, dans la partie supérieure droite de la fenêtre contextuelle, "Afficher en texte" (vous pouvez même voir des images ..)

 enter image description here

Et c'est tout!

 enter image description here

3
funkyjelly

La réponse de Barn a fonctionné pour moi avec modification car ma colonne n'est pas compressée. La solution rapide et sale:

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

Si votre texte est compressé à l'intérieur du blob avec l'algorithme DEFLATE et qu'il est assez volumineux, vous pouvez utiliser cette fonction pour le lire

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

Puis lancez select pour obtenir du texte

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

J'espère que cela aidera quelqu'un.

0
Arsen Salamakha

Vous pouvez essayer ceci:

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

Cependant, il serait limité à 4000 octets 

0
Reza Rahimi

Travaillé pour moi, 

sélectionnez lcase ((insertion ( insertion ( insertion ( insertion (hexadécimal)))).,. 19,0, '-'), 24,0, '-'))) en tant que FIELD_ID de TABLE_WITH_BLOB où ID = 'ID de ligne';

0
Narendra Kalekar