Come posso ottenere contenuti testuali da BLOB in Oracle SQL
Domanda
Sto cercando di vedere da una console SQL cosa c'è dentro un Oracle BLOB.
So che contiene una parte piuttosto ampia di testo e voglio solo vedere il testo, ma la seguente query indica solo che c'è un BLOB in quel campo:
select BLOB_FIELD from TABLE_WITH_BLOB where ID = '<row id>';
il risultato che sto ottenendo non è esattamente quello che mi aspettavo:
BLOB_FIELD ----------------------- oracle.sql.BLOB@1c4ada9
Quindi che tipo di incantesimi magici posso fare per trasformare BLOB nella sua rappresentazione testuale?
PS: sto solo cercando di guardare il contenuto del BLOB da una console SQL (Eclipse Data Tools), non di usarlo nel codice.
Soluzione
Prima di tutto, potresti voler archiviare il testo nelle colonne CLOB / NCLOB anziché BLOB, che è progettato per dati binari (la tua query funzionerebbe con un CLOB, comunque).
La seguente query ti consentirà di vedere i primi 32767 caratteri (al massimo) del testo all'interno del BLOB, a condizione che tutti i set di caratteri siano compatibili (CS originale del testo archiviato in BLOB, CS del database utilizzato per VARCHAR2 ):
select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
Altri suggerimenti
È possibile utilizzare SQL sotto per leggere i campi BLOB dalla tabella.
SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Se vuoi cercare all'interno del testo, piuttosto che visualizzarlo, questo funziona:
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;
Ho lottato con questo per un po 'e ho implementato la soluzione PL / SQL, ma in seguito mi sono reso conto che in Toad puoi semplicemente fare doppio clic sulla cella della griglia dei risultati e visualizza un editor con contenuti nel testo. (sono su Toad v11)
La risposta di Barn ha funzionato per me con modifiche perché la mia colonna non è compressa. La soluzione rapida e sporca:
select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
Puoi provare questo:
SELECT TO_CHAR(dbms_lob.substr(BLOB_FIELD, 3900)) FROM TABLE_WITH_BLOB;
Tuttavia, sarebbe limitato a 4000 byte
Nel caso in cui il testo sia compresso all'interno del BLOB usando l'algoritmo DEFLATE ed è piuttosto grande, è possibile utilizzare questa funzione per leggerlo
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;
/
Quindi esegui select per ottenere il testo
SELECT read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;
Spero che questo possa aiutare qualcuno.
Ha funzionato per me,
seleziona lcase ((inserisci ( inserire( inserire( inserire (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '-'))) come FIELD_ID da TABLE_WITH_BLOB dove ID = "ID riga";
Utilizza la funzione TO_CHAR
.
select TO_CHAR(BLOB_FIELD) from TABLE_WITH_BLOB where ID = '<row id>'
Converte i dati NCHAR
, NVARCHAR2
, CLOB
o NCLOB
nel set di caratteri del database. Il valore restituito è sempre VARCHAR2
.