我试图从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中,BLOB是专为二进制数据设计的(顺便提一下,您的查询将与CLOB一起使用)。
如果所有字符集都兼容(存储在BLOB中的文本的原始CS,用于VARCHAR2的数据库的CS),以下查询将允许您查看blob内部文本的第一个32767个字符(最多):
select utl_raw.cast_to_varchar2(dbms_lob.substr(BLOB_FIELD)) from TABLE_WITH_BLOB where ID = '<row id>';
使用TO_CHAR
函数。
select TO_CHAR(BLOB_FIELD) from TABLE_WITH_BLOB where ID = '<row id>'
将NCHAR
,NVARCHAR2
,CLOB
或NCLOB
数据转换为数据库字符集。返回的值始终是VARCHAR2
。
您可以使用以下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;
我挣扎了一段时间并实现了PL / SQL解决方案,但后来意识到在Toad中你可以简单地双击结果网格单元格,它会弹出一个包含文本内容的编辑器。 (我在Toad v11上)
Barn的回答对我有用,因为我的专栏没有压缩。快速而肮脏的解决方案:
select * from my_table
where dbms_lob.instr(my_UNcompressed_blob, utl_raw.cast_to_raw('MY_SEARCH_STRING'))>0;
你可以试试这个:
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来获取文本
SELECT read_gzipped_entity_package.read_entity('entity_id') FROM DUAL;
希望这会对某人有所帮助。
为我工作,
select lcase((insert(insert(insert(hex(hex(BLOB_FIELD),9,0,' - '),14,0,' - '),19,0,' - '),24,0,' - ')))作为TABLE_WITH_BLOB的FIELD_ID,其中ID ='row id';