[英]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 從表中讀取 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>'
將NCHAR
、 NVARCHAR2
、 CLOB
或NCLOB
數據轉換為數據庫字符集。 返回的值始終為VARCHAR2
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.