【问题标题】:How do I get textual contents from BLOB in Oracle SQL如何从 Oracle SQL 中的 BLOB 获取文本内容
【发布时间】:2010-10-24 03:22:03
【问题描述】:

我试图从 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 的内容,而不是在代码中使用它。

【问题讨论】:

    标签: sql oracle blob


    【解决方案1】:

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

    【讨论】:

    • 不幸的是,我不控制数据库架构 - 我只需要窥视 blob...不过还是谢谢。
    • 感谢 Mac,这很好 --- 但是那个“dbms_lob.substr”的目的是什么? --- 仅使用“select utl_raw.cast_to_varchar2(BLOB_FIELD) ...”似乎给了我相同的结果...?
    • cast_to_varchar2 在输入中采用 RAW (docs.oracle.com/cd/E11882_01/appdev.112/e25788/…),其长度限制为 32767 字节 (docs.oracle.com/cd/E11882_01/appdev.112/e10472/…)。 BLOB 的大小没有限制,因此 substr 会在必要时将其截断为正确的大小 (docs.oracle.com/cd/E11882_01/appdev.112/e25788/…)。
    • 对我不起作用 - 我得到“ORA-06502: PL/SQL: numeric or value error: raw variable length too long”。我可以在 BLOB_FIELD 之后放置“2000,1”以获得最多 2000 个字符,但除此之外没有。
    • 如果值超过 4000 会抛出错误,因为这是 sql 中字符串的最大值。您需要添加 substr(BLOB_FIELD, 4000, 1)。如果您需要更长的现场支持,请使用 PL/SQL(我相信最多 32000)
    【解决方案2】:

    SQL Developer 也提供了这个功能:

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

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

    就是这样!

    【讨论】:

    • @nullPointer 你真是太棒了!感谢您的提示。
    【解决方案3】:

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

    SELECT DBMS_LOB.SUBSTR(BLOB_FIELD_NAME) FROM TABLE_NAME;
    

    【讨论】:

    • 我有 BLOB 列,并且 XML 数据被压缩并存储在表中,当我读取数据时,它只显示一些数字而不是实际的 xml 文本,我应该怎么做才能读取 XML表格中的文本数据。
    • 这不起作用,原始变量长度太长错误
    【解决方案4】:

    如果您想在文本中搜索,而不是查看它,这可行:

    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 是什么?
    • 这对我不起作用,我有 BLOB 列,并且 XML 数据被压缩并存储在表中,当我读取数据时,它只显示一些数字而不是实际的 xml 文本,什么我应该从表中读取 XML 文本数据吗?
    【解决方案5】:

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

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

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

    【讨论】:

      【解决方案6】:

      Barn 的回答通过修改对我有用,因为我的列没有被压缩。快速而肮脏的解决方案:

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

      【讨论】:

        【解决方案7】:

        我为此苦苦挣扎了一段时间,并实施了 PL/SQL 解决方案,但后来意识到在 Toad 中,您只需双击结果网格单元格,它就会打开一个包含文本内容的编辑器。 (我在 Toad v11 上)

        【讨论】:

          【解决方案8】:

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

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

          这在 Oracle 19c 中适用于我,其 BLOB 字段大于 VARCHAR 限制。我得到了可读的文本(来自一个持有 JSON 的 BLOB)

          【讨论】:

            【解决方案9】:

            你可以试试这个:

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

            但是,它会被限制为 4000 字节

            【讨论】:

              【解决方案10】:

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

              希望这会对某人有所帮助。

              【讨论】:

                【解决方案11】:

                为我工作,

                选择 lcase((插入( 插入( 插入( 插入(十六进制(BLOB_FIELD),9,0,'-'), 14,0,'-'), 19,0,'-'), 24,0,'-'))) 作为 FIELD_ID 来自 TABLE_WITH_BLOB 其中 ID = '行 id';

                【讨论】:

                • 如果这对你有用,那么你没有使用 Oracle,OP 就是这样,这就是为什么答案需要是有效的 Oracle 语法。
                【解决方案12】:

                使用TO_CHAR 函数。

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

                NCHARNVARCHAR2CLOBNCLOB 数据转换为数据库字符集。返回的值始终为VARCHAR2

                【讨论】:

                • 从 TABLE_WITH_BLOB 中选择 DBMS_LOB.SUBSTR(BLOB_FIELD);
                猜你喜欢
                • 2016-05-19
                • 1970-01-01
                • 1970-01-01
                • 2018-12-24
                • 2021-06-19
                • 1970-01-01
                • 2021-01-02
                • 2015-02-08
                • 1970-01-01
                相关资源
                最近更新 更多