如何在Oracle SQL中从BLOB获取文本内容


112

我正在尝试从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数据工具)查看BLOB的内容,而不是在代码中使用它。

Answers:


141

首先,您可能希望将文本存储在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>';

3
不幸的是,我不控制数据库模式-我只需要浏览一下Blob ...但是无论如何,谢谢。
罗兰·特普

感谢Mac,它可以正常工作---但是“ dbms_lob.substr”的目的是什么?---仅使用“ select utl_raw.cast_to_varchar2(BLOB_FIELD)...”似乎能给我相同的结果...?
罗普

4
cast_to_varchar2在输入中输入RAW(docs.oracle.com/cd/E11882_01/appdev.112/e25788/…),其长度限制为32767字节(docs.oracle.com/cd/E11882_01/appdev.112/e10472 /…)。BLOB的大小没有限制,因此如有必要,将其截短为正确的大小(docs.oracle.com/cd/E11882_01/appdev.112/e25788/…)。
Mac

34
对我不起作用-我收到“ ORA-06502:PL / SQL:数字或值错误:原始变量长度过长”。我可以在BLOB_FIELD之后加上“ 2000,1”,以获取最多2000个字符,但是除此之外。
2013年

2
如果该值大于4000,则会抛出错误,因为这是sql中字符串的最大值。您需要添加substr(BLOB_FIELD,4000,1)。如果您需要更长的现场支持,请使用PL / SQL(我相信最多32000)
Sonic Soul

14

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

SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;

我有BLOB列,并且XML数据被压缩并存储在表中,当我读取数据时,它仅显示一些数字而不是实际的xml文本,我应该怎么做才能从表中读取XML文本数据。
BHUVANESH MOHANKUMAR

14

SQL Developer也提供此功能:

双击结果网格单元格,然后单击编辑:

在此处输入图片说明

然后在弹出窗口的右上部分,“以文本查看”(您甚至可以看到图像。)

在此处输入图片说明

就是这样!

在此处输入图片说明


这是一个很好的提示-谢谢!
Ed Graham

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文本表中的数据。
BHUVANESH MOHANKUMAR

3

谷仓的答案对我来说很有效,因为我的列未压缩。快速而肮脏的解决方案:

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上)

在此处输入图片说明


1

如果您使用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;

希望这会帮助某人。


1

使用此SQL可以获取BLOB的前2000个字符。

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

注意:这是因为,Oracle将无法处理长度超过2000的BLOB转换。



-2

为我工作

选择lcase((insert(insert(insert(insert(insert(hex(BLOB_FIELD),9,0,'-')),14,0,'-'),19,0,'-')),24,0,'- ')))为TABLE_WITH_BLOB中的FIELD_ID,其中ID ='行ID';


如果这对您有用,那么您不是使用OP,而是使用Oracle,这就是为什么答案必须是有效的Oracle语法的原因。
APC

-4

使用TO_CHAR功能。

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

皈依NCHARNVARCHAR2CLOB,或NCLOB数据到数据库中的字符集。返回的值始终为VARCHAR2


从TABLE_WITH_BLOB中选择DBMS_LOB.SUBSTR(BLOB_FIELD);
Sambhav 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.