Как получить текстовое содержимое из BLOB в Oracle SQL

113

Я пытаюсь увидеть из консоли SQL, что находится внутри Oracle BLOB.

Я знаю, что он содержит довольно большой текст, и я хочу просто увидеть текст, но следующий запрос указывает только на то, что в этом поле есть BLOB:

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

результат, который я получаю, не совсем то, что я ожидал:

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

Итак, какие магические заклинания я могу использовать, чтобы превратить BLOB в его текстовое представление?

PS: Я просто пытаюсь посмотреть содержимое BLOB-объекта из консоли SQL (Eclipse Data Tools), а не использовать его в коде.

Роланд Тепп
источник

Ответы:

141

Прежде всего, вы можете захотеть хранить текст в столбцах CLOB / NCLOB вместо BLOB, который предназначен для двоичных данных (кстати, ваш запрос будет работать с CLOB).

Следующий запрос позволит вам увидеть первые 32767 символов (самое большее) текста внутри большого двоичного объекта при условии, что все наборы символов совместимы (исходная CS текста, хранящегося в BLOB, CS базы данных, используемой для VARCHAR2):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
макинтош
источник
3
К сожалению, я не контролирую схему базы данных - мне просто нужно заглянуть в blob ... Но все равно спасибо.
Роланд Тепп
Спасибо, Mac, все работает нормально --- Но какова цель этого "dbms_lob.substr"? --- Только использование "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ...", кажется, дает мне тот же результат ...?
Rop
4
cast_to_varchar2 принимает на вход RAW ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ), длина которого ограничена 32767 байтами ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 /… ). Большой двоичный объект не имеет ограничений по размеру, поэтому substr при необходимости обрезает его до правильного размера ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ).
Mac,
34
У меня не работает - я получаю «ORA-06502: PL / SQL: числовая ошибка или ошибка значения: необработанная длина переменной слишком велика». Я могу поставить "2000,1" после BLOB_FIELD, чтобы получить до 2000 символов, но не более того.
Марк
2
если значение больше 4000, это вызовет ошибки, поскольку это максимальное значение для строк в sql. вам нужно добавить substr (BLOB_FIELD, 4000, 1). Если вам нужна более длительная полевая поддержка, используйте PL / SQL (я полагаю, до 32000)
Sonic Soul
15

SQL Developer также предоставляет эту функциональность:

Дважды щелкните ячейку сетки результатов и нажмите кнопку изменить:

введите описание изображения здесь

Затем в правой верхней части всплывающего окна «Просмотреть как текст» (вы даже можете видеть изображения ..)

введите описание изображения здесь

И это все!

введите описание изображения здесь

NullPointer
источник
Отличный совет - спасибо!
Эд Грэм
@nullPointer, ты такой классный человек! Спасибо за чаевые.
Моисей Ндеда
14

Вы можете использовать приведенный ниже SQL для чтения полей BLOB из таблицы.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
Имран Патель
источник
У меня есть столбец BLOB, и где данные XML сжимаются и хранятся в таблице, когда я читаю данные, он показывает только некоторые числа, а не фактический текст xml, что мне делать, чтобы читать текстовые данные XML из таблицы.
БХУВАНЕШ МОХАНКУМАР
7

Если вы хотите искать внутри текста, а не просматривать его, это работает:

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;
амбар
источник
что здесь my_id?
anjanb
Это не работает для меня, у меня есть столбец BLOB, и где данные XML сжимаются и хранятся в таблице, когда я читаю данные, он показывает только некоторые числа, а не фактический текст xml, что мне делать, чтобы прочитать текст XML данные из таблицы.
БХУВАНЕШ МОХАНКУМАР
3

Ответ Barn сработал для меня с модификацией, потому что мой столбец не сжат. Быстрое и грязное решение:

select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
Пекос Билл
источник
3

Некоторое время я боролся с этим и реализовал решение PL / SQL, но позже понял, что в Toad вы можете просто дважды щелкнуть ячейку сетки результатов, и появится редактор с текстовым содержимым. (я использую Toad v11)

введите описание изображения здесь

Sonic Soul
источник
1

Если ваш текст сжат внутри большого двоичного объекта с использованием алгоритма DEFLATE, и он довольно большой, вы можете использовать эту функцию для его чтения.

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

Затем запустите select, чтобы получить текст

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

Надеюсь, это кому-то поможет.

Арсен Саламаха
источник
1

Используйте этот SQL, чтобы получить первые 2000 символов BLOB.

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

Примечание: это связано с тем, что Oracle не сможет обработать преобразование BLOB, длина которого превышает 2000.

Swapnil Ingle
источник
0

Вы можете попробовать это:

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

Однако он будет ограничен 4000 байтами

Реза Рахими
источник
-2

Работал у меня,

выберите lcase ((insert (insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) как FIELD_ID из TABLE_WITH_BLOB, где ID =' идентификатор строки ';

Нарендра Калекар
источник
Если это сработало для вас, значит, вы не используете Oracle, каковым является OP, и поэтому ответы должны быть правильным синтаксисом Oracle.
APC
-4

Используйте TO_CHARфункцию.

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

Обращенные NCHAR, NVARCHAR2, CLOB, или NCLOBданные в набор символов базы данных. Возвращаемое значение всегда VARCHAR2.

Alex
источник
ВЫБРАТЬ DBMS_LOB.SUBSTR (BLOB_FIELD) ИЗ TABLE_WITH_BLOB;
Sambhav