Oracle SQL'de BLOB'dan metin içeriğini nasıl alırım


112

Bir SQL konsolundan bir Oracle BLOB'un içinde ne olduğunu görmeye çalışıyorum.

Biraz büyük bir metin gövdesi içerdiğini biliyorum ve sadece metni görmek istiyorum, ancak aşağıdaki sorgu yalnızca bu alanda bir BLOB olduğunu gösterir:

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

elde ettiğim sonuç beklediğim gibi değil:

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

Öyleyse, BLOB'u metinsel temsiline dönüştürmek için ne tür sihirli büyüler yapabilirim?

Not: BLOB içeriğine bir SQL konsolundan (Eclipse Data Tools) bakmaya çalışıyorum, onu kodda kullanmıyorum.

Yanıtlar:


141

Her şeyden önce, metni ikili veriler için tasarlanmış BLOB yerine CLOB / NCLOB sütunlarında saklamak isteyebilirsiniz (bu arada sorgunuz bir CLOB ile çalışır).

Aşağıdaki sorgu, tüm karakter kümelerinin uyumlu olması koşuluyla blob içindeki metnin ilk 32767 karakterini (en fazla) görmenizi sağlar (BLOB'da depolanan metnin orijinal CS'si, VARCHAR2 için kullanılan veritabanının CS'si):

select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';

3
Ne yazık ki, veritabanı şemasını kontrol etmiyorum - sadece blob'a bakmam gerekiyor ... Ama yine de teşekkürler.
Roland Tepp

Teşekkürler Mac, bu iyi çalışıyor --- Ama bu "dbms_lob.substr" ın amacı nedir? --- Sadece "select utl_raw.cast_to_varchar2 (BLOB_FIELD) ..." kullanılması bana aynı sonucu veriyor gibi görünüyor ...?
Rop

4
cast_to_varchar2, 32767 bayt uzunluğunda ( docs.oracle.com/cd/E11882_01/appdev.112/e10472 ) girdi olarak bir RAW alır ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) /… ). Bir BLOB'un boyut sınırlaması yoktur, bu nedenle, gerekirse alt boyutu doğru bir boyuta ( docs.oracle.com/cd/E11882_01/appdev.112/e25788/… ) kısaltır .
Mac

34
Benim için çalışmıyor - "ORA-06502: PL / SQL: sayısal veya değer hatası: ham değişken uzunluğu çok uzun" alıyorum. 2000 karaktere kadar BLOB_FIELD'in arkasına "2000,1" koyabilirim, ama bunun ötesinde bir şey yok.
Mark

2
eğer değer 4000'den uzunsa, sql'deki dizeler için maksimum değer bu olduğundan, hata verir. substr (BLOB_FIELD, 4000, 1) eklemeniz gerekir. Daha uzun alan desteğine ihtiyacınız varsa PL / SQL kullanın (sanırım 32000'e kadar)
Sonic Soul

14

BLOB Alanlarını tablodan okumak için aşağıdaki SQL'i kullanabilirsiniz.

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

BLOB sütunum var ve XML verilerinin sıkıştırıldığı ve tabloda depolandığı yerde, verileri okuduğumda, yalnızca bazı sayıları gösteriyor ve gerçek xml metnini göstermiyor, XML metin verilerini tablodan okumak için ne yapmalıyım.
BHUVANESH MOHANKUMAR

14

SQL Developer da bu işlevi sağlar:

Sonuçlar ızgara hücresine çift tıklayın ve düzenle'ye tıklayın:

görüntü açıklamasını buraya girin

Ardından açılır pencerenin sağ üst kısmında "Metin Olarak Görüntüle" (Resimleri bile görebilirsiniz ..)

görüntü açıklamasını buraya girin

Ve bu kadar!

görüntü açıklamasını buraya girin


Bu harika bir ipucu - teşekkürler!
Ed Graham

7

Metni görüntülemek yerine içinde aramak istiyorsanız, bu işe yarar:

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 burada nedir?
anjanb

Bu benim için çalışmıyor, BLOB sütunum var ve XML verilerinin tabloda sıkıştırıldığı ve saklandığı yerde, verileri okuduğumda yalnızca bazı sayılar gösteriyor ve gerçek xml metni gösterilmiyor, XML metnini okumak için ne yapmalıyım tablodaki veriler.
BHUVANESH MOHANKUMAR

3

Barn'ın cevabı, sütunum sıkıştırılmadığı için değişiklik yaparak benim için çalıştı. Hızlı ve kirli çözüm:

select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;

3

Bununla bir süre uğraştım ve PL / SQL çözümünü uyguladım, ancak daha sonra Toad'da sonuçlar ızgara hücresine çift tıklayabileceğinizi ve metinde içeriği olan bir düzenleyici getirdiğini fark ettim. (Toad v11'deyim)

görüntü açıklamasını buraya girin


1

Metninizin DEFLATE algoritması kullanılarak blob içinde sıkıştırılması ve oldukça büyük olması durumunda, okumak için bu işlevi kullanabilirsiniz.

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

Ardından metni almak için seç'i çalıştırın

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

Umarım bu birine yardımcı olur.


1

BLOB'un ilk 2000 karakterini almak için bu SQL'i kullanın.

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

Not: Bunun nedeni, Oracle'ın 2000'den uzun BLOB'un dönüştürülmesini işleyemeyecek olmasıdır.


0

Bunu deneyebilirsiniz:

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

Ancak 4000 bayt ile sınırlı olacaktır


-2

Benim için çalıştı

lcase seçin ((insert (insert (insert (hex (BLOB_FIELD), 9,0, '-'), 14,0, '-'), 19,0, '-'), 24,0, '- '))) TABLE_WITH_BLOB'dan FIELD_ID olarak burada ID =' satır kimliği ';


Bu sizin için işe yaradıysa, Oracle'ı kullanmıyorsunuzdur, ki bu OP'dir ve bu nedenle yanıtların geçerli Oracle sözdizimi olması gerekir.
APC

-4

TO_CHARİşlevi kullanın .

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

Dönüştürür NCHAR, NVARCHAR2, CLOB, veya NCLOBveritabanı karakter kümesine verileri. Döndürülen değer her zaman olur VARCHAR2.


TABLE_WITH_BLOB'DAN DBMS_LOB.SUBSTR (BLOB_FIELD) SEÇİN;
Sambhav
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.