Jak uzyskać zawartość tekstową z BLOBa w Oracle SQL

112

Próbuję zobaczyć z konsoli SQL, co jest wewnątrz Oracle BLOB.

Wiem, że zawiera dość duży tekst i chcę tylko zobaczyć tekst, ale poniższe zapytanie wskazuje tylko, że w tym polu znajduje się BLOB:

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

wynik, który otrzymuję, nie jest taki, jakiego się spodziewałem:

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

Więc jakie magiczne zaklęcia mogę zrobić, aby zmienić BLOB w jego tekstową reprezentację?

PS: Po prostu próbuję spojrzeć na zawartość BLOBa z konsoli SQL (Eclipse Data Tools), a nie używać go w kodzie.

Roland Tepp
źródło

Odpowiedzi:

141

Przede wszystkim możesz chcieć przechowywać tekst w kolumnach CLOB / NCLOB zamiast BLOB, który jest przeznaczony dla danych binarnych (nawiasem mówiąc, twoje zapytanie działałoby z CLOB).

Następujące zapytanie pozwoli zobaczyć pierwsze 32767 znaków (najwyżej) tekstu wewnątrz obiektu blob, pod warunkiem, że wszystkie zestawy znaków są zgodne (oryginalny CS tekstu przechowywanego w BLOB, CS bazy danych używanej dla VARCHAR2):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
Prochowiec
źródło
3
Niestety nie kontroluję schematu bazy danych - wystarczy zajrzeć do bloba ... Ale i tak dziękuję.
Roland Tepp
Dzięki Mac, to działa dobrze --- Ale jaki jest cel tego "dbms_lob.substr"? --- Tylko użycie „select utl_raw.cast_to_varchar2 (BLOB_FIELD)…” wydaje się dawać ten sam wynik ...?
Rop
4
cast_to_varchar2 pobiera RAW na wejściu ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), którego długość jest ograniczona do 32767 bajtów ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Obiekt BLOB nie ma ograniczeń co do rozmiaru, więc w razie potrzeby substr skraca go do odpowiedniego rozmiaru ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/ ... ).
Mac,
34
U mnie nie działa - wyświetla się komunikat „ORA-06502: PL / SQL: błąd numeryczny lub wartości: zbyt długa długość zmiennej surowej”. Mogę wstawić „2000,1” po BLOB_FIELD, aby uzyskać do 2000 znaków, ale nic poza tym.
Mark
2
jeśli wartość jest większa niż 4000, będzie generować błędy, ponieważ jest to maksymalna wartość dla łańcuchów w sql. musisz dodać substr (BLOB_FIELD, 4000, 1). Jeśli potrzebujesz dłuższego wsparcia w terenie, użyj PL / SQL (do 32000, jak sądzę)
Sonic Soul
14

Możesz użyć poniższego kodu SQL, aby odczytać pola BLOB z tabeli.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Imran Patel
źródło
Mam kolumnę BLOB i gdzie dane XML są skompresowane i przechowywane w tabeli, kiedy czytam dane, pokazuje tylko niektóre liczby, a nie rzeczywisty tekst xml, co powinienem zrobić, aby odczytać dane tekstowe XML z tabeli.
BHUVANESH MOHANKUMAR
14

SQL Developer udostępnia również tę funkcjonalność:

Kliknij dwukrotnie komórkę siatki wyników i kliknij edytuj:

wprowadź opis obrazu tutaj

Następnie w prawej górnej części wyskakującego okienka „Wyświetl jako tekst” (możesz nawet zobaczyć obrazy ...)

wprowadź opis obrazu tutaj

I to wszystko!

wprowadź opis obrazu tutaj

nullPointer
źródło
To świetna wskazówka - dzięki!
Ed Graham
7

Jeśli chcesz przeszukiwać tekst, zamiast go wyświetlać, działa to:

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;
Stodoła
źródło
co to jest my_id tutaj?
anjanb
U mnie to nie działa, mam kolumnę BLOB i gdzie dane XML są skompresowane i przechowywane w tabeli, gdy czytam dane, pokazuje tylko niektóre liczby a nie rzeczywisty tekst xml, co mam zrobić, aby przeczytać tekst XML dane z tabeli.
BHUVANESH MOHANKUMAR
3

Odpowiedź Barna zadziałała dla mnie z modyfikacją, ponieważ moja kolumna nie jest skompresowana. Szybkie i brudne rozwiązanie:

select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
Pecos Bill
źródło
3

Przez jakiś czas walczyłem z tym i zaimplementowałem rozwiązanie PL / SQL, ale później zdałem sobie sprawę, że w Toad możesz po prostu dwukrotnie kliknąć komórkę siatki wyników, a pojawi się edytor z zawartością w tekście. (Jestem na Toad v11)

wprowadź opis obrazu tutaj

Sonic Soul
źródło
1

W przypadku, gdy twój tekst jest skompresowany wewnątrz bloba za pomocą algorytmu DEFLATE i jest dość duży, możesz użyć tej funkcji, aby go przeczytać

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

Następnie uruchom wybierz, aby uzyskać tekst

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

Mam nadzieję, że to komuś pomoże.

Arsen Salamakha
źródło
1

Użyj tego kodu SQL, aby uzyskać pierwsze 2000 znaków z BLOBa.

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

Uwaga: Dzieje się tak, ponieważ Oracle nie będzie w stanie obsłużyć konwersji BLOB o długości większej niż 2000.

Swapnil Ingle
źródło
0

Możesz spróbować tego:

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

Jednak byłoby ograniczone do 4000 bajtów

Reza Rahimi
źródło
-2

Pracował dla mnie

select lcase ((insert (insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) jako FIELD_ID z TABLE_WITH_BLOB, gdzie ID =' id wiersza ';

Narendra Kalekar
źródło
Jeśli to zadziałało, oznacza to, że nie używasz Oracle, którym jest OP i dlatego odpowiedzi muszą być poprawną składnią Oracle.
APC
-4

Użyj TO_CHARfunkcji.

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

Nawróceni NCHAR, NVARCHAR2, CLOB, lub NCLOBdane do zestawu znaków bazy danych. Zwracana wartość to zawsze VARCHAR2.

Alex
źródło
SELECT DBMS_LOB.SUBSTR (BLOB_FIELD) FROM TABLE_WITH_BLOB;
Sambhav