Comment obtenir du contenu textuel à partir de BLOB dans Oracle SQL

112

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

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

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

le résultat que j'obtiens n'est pas tout à fait ce que j'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 juste de regarder le contenu du BLOB depuis une console SQL (Eclipse Data Tools), pas de l'utiliser dans le code.

Roland Tepp
la source

Réponses:

141

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

La requête suivante vous permettra de voir les 32767 premiers caractères (au plus) du texte à l'intérieur du blob, à condition que tous les jeux de caractères soient compatibles (CS original du texte stocké dans le BLOB, 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>';
Mac
la source
3
Malheureusement, je ne contrôle pas le schéma de la base de données - j'ai juste besoin de jeter un coup d'œil dans le blob ... Mais merci quand même.
Roland Tepp
Merci Mac, cela fonctionne bien --- Mais quel est le but de ce "dbms_lob.substr"? --- Uniquement en utilisant "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." semble me donner le même résultat ...?
Rop
4
cast_to_varchar2 prend un RAW en entrée ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), qui est limité à 32767 octets de longueur ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Un BLOB n'a pas de limitation de taille, donc substr le tronque à une taille correcte ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) si nécessaire.
Mac
34
Ne fonctionne pas pour moi - J'obtiens "ORA-06502: PL / SQL: erreur numérique ou de valeur: longueur de variable brute trop longue". Je peux mettre "2000,1" après BLOB_FIELD pour obtenir jusqu'à 2000 caractères, mais rien au-delà.
Mark le
2
si la valeur est plus longue que 4000, cela générera des erreurs car c'est la valeur maximale pour les chaînes en sql. vous devez ajouter substr (BLOB_FIELD, 4000, 1). Si vous avez besoin d'un support de terrain plus long, utilisez PL / SQL (jusqu'à 32000 je crois)
Sonic Soul
14

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

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Imran Patel
la source
J'ai une colonne BLOB et où les données XML sont compressées et stockées dans la table, lorsque je lis les données, elles ne montrent que quelques chiffres et non du texte xml réel, que dois-je faire pour lire les données de texte XML de la table.
BHUVANESH MOHANKUMAR
14

SQL Developer fournit également cette fonctionnalité:

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

entrez la description de l'image ici

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

entrez la description de l'image ici

Et c'est tout!

entrez la description de l'image ici

pointeur nul
la source
C'est un bon conseil - merci!
Ed Graham le
7

Si vous souhaitez rechercher dans le texte plutôt que de le visualiser, cela 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;
Grange
la source
quel est mon_id ici?
anjanb
Cela ne fonctionne pas pour moi, j'ai une colonne BLOB et où les données XML sont compressées et stockées dans la table, lorsque je lis les données, elles ne montrent que quelques chiffres et non du texte xml réel, que dois-je faire pour lire le texte XML données du tableau.
BHUVANESH MOHANKUMAR
3

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;
Bill Pecos
la source
3

J'ai eu du mal avec cela pendant un moment et j'ai implémenté la solution PL / SQL, mais je me suis rendu compte plus tard que dans Toad, vous pouvez simplement double-cliquer sur la cellule de la grille de résultats, et cela fait apparaître un éditeur avec le contenu en texte. (je suis sur Toad v11)

entrez la description de l'image ici

Sonic Soul
la source
1

Si votre texte est compressé à l'intérieur du blob à l'aide de 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;
/

Ensuite, exécutez select pour obtenir du texte

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

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

Arsen Salamakha
la source
1

Utilisez ce SQL pour obtenir les 2000 premiers caractères du BLOB.

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

Remarque: Ceci est dû au fait qu'Oracle ne pourra pas gérer la conversion de BLOB d'une longueur supérieure à 2000.

Swapnil Ingle
la source
0

Vous pouvez essayer ceci:

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

Cependant, il serait limité à 4000 octets

Reza Rahimi
la source
-2

A travaillé pour moi,

sélectionnez lcase ((insert (insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) comme FIELD_ID à partir de TABLE_WITH_BLOB où ID =' row id ';

Narendra Kalekar
la source
Si cela a fonctionné pour vous, vous n'utilisez pas Oracle, ce qui est l'OP et c'est pourquoi les réponses doivent être une syntaxe Oracle valide.
APC
-4

Utilisez la TO_CHARfonction.

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

Convertis NCHAR, NVARCHAR2, CLOBou NCLOBdonnées au jeu de caractères de base de données. La valeur renvoyée est toujours VARCHAR2.

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