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.
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>';
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;
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;
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)
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;
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.
Vous pouvez essayer ceci:
SELECT TO_CHAR(dbms_lob.substr(BLOB_FIELD, 3900)) FROM TABLE_WITH_BLOB;
Cependant, il serait limité à 4000 octets
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';