簡體   English   中英

如何從 Oracle SQL 中的 BLOB 獲取文本內容

[英]How do I get textual contents from BLOB in Oracle SQL

我試圖從 SQL 控制台查看 Oracle BLOB 中的內容。

我知道它包含一個有點大的文本體,我只想查看文本,但以下查詢僅表明該字段中有一個 BLOB:

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

我得到的結果並不完全符合我的預期:

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

那么我可以做什么樣的魔法咒語來將 BLOB 變成它的文本表示呢?

PS:我只是想從 SQL 控制台(Eclipse Data Tools)查看 BLOB 的內容,而不是在代碼中使用它。

首先,您可能希望將文本存儲在 CLOB/NCLOB 列中,而不是 BLOB,后者專為二進制數據而設計(順便說一下,您的查詢將使用 CLOB)。

以下查詢將讓您看到 blob 中文本的前 32767 個字符(最多),前提是所有字符集都兼容(存儲在 BLOB 中的文本的原始 CS,用於 VARCHAR2 的數據庫的 CS):

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

SQL Developer 也提供此功能:

雙擊結果網格單元格,然后單擊編輯:

在此處輸入圖片說明

然后在彈出窗口的右上角,“以文本形式查看”(您甚至可以看到圖像..)

在此處輸入圖片說明

就是這樣!

在此處輸入圖片說明

您可以使用下面的 SQL 從表中讀取 BLOB 字段。

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

如果你想在文本中搜索,而不是查看它,這有效:

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;

Barn 的答案經過修改對我有用,因為我的專欄沒有被壓縮。 快速而骯臟的解決方案:

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

我為此苦苦掙扎了一段時間並實施了 PL/SQL 解決方案,但后來意識到在 Toad 中您只需雙擊結果網格單元格,它就會顯示一個包含文本內容的編輯器。 (我在 Toad v11 上)

在此處輸入圖片說明

使用此 SQL 獲取 BLOB 的前 2000 個字符。

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

注意:這是因為,Oracle 將無法處理長度超過 2000 的 BLOB 的轉換。

你可以試試這個:

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

但是,它將被限制為 4000 字節

如果您的文本使用 DEFLATE 算法在 blob 中壓縮並且非常大,您可以使用此函數讀取它

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 read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;

希望這會幫助某人。

我可以使用 TO_CLOB ( docs ) 使其工作:

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

這在 Oracle 19c 中對我有用,有一個 BLOB 字段,它大於 VARCHAR 限制。 我得到可讀的文本(來自一個 JSON 持有的 BLOB)

為我工作,

選擇 lcase((插入(插入(插入(插入(插入(十六進制(BLOB_FIELD),9,0,'-'), 14,0,'-'), 19,0,'-'), 24,0,'- '))) 作為 TABLE_WITH_BLOB 中的 FIELD_ID,其中 ID = 'row id';

使用TO_CHAR函數。

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

NCHARNVARCHAR2CLOBNCLOB數據轉換為數據庫字符集。 返回的值始終為VARCHAR2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM