【问题标题】:oracle blob text searchoracle blob 文本搜索
【发布时间】:2011-02-27 04:09:12
【问题描述】:

是否可以使用 sql 语句搜索 blob 文本? 如果 f1 是 varchar,我可以从 $table where f1 like '%foo%' 中选择 *,那么 f1 是一个 blob 怎么样?有什么对应的部分吗?

【问题讨论】:

    标签: oracle search blob


    【解决方案1】:

    这很可能而且很容易做到。

    只需将 dbms_lob.instr 与 utl_raw.cast_to_raw 结合使用

    因此,在您的情况下,如果 t1 是 BLOB,则选择如下所示:

    select *
      from table1
     where dbms_lob.instr (t1, -- the blob
                       utl_raw.cast_to_raw ('foo'), -- the search string cast to raw
                       1, -- where to start. i.e. offset
                       1 -- Which occurrance i.e. 1=first
                        ) > 0 -- location of occurrence. Here I don't care.  Just find any
    ;
    

    【讨论】:

    • ++ 当数据库不是您的数据库时,说架构错误并无济于事。非常感谢您复活并回答问题!
    • 这确实应该是公认的答案——问题显然是关于 BLOB 而不是关于 CLOB!
    • 这是正确答案。标记为正确答案的答案是另一个问题的好答案:“存储大量文本时应该使用哪种数据类型?”。
    • 我必须搜索一个 Unicode 字符,所以我调整了这个解决方案如下: select * from table1 where dbms_lob.instr (f1, utl_raw.cast_to_raw (unistr('\D83D') ), 1, 1) > 0;
    • 谢谢。这有效!
    【解决方案2】:

    如果是 Word 或 PDF 文档,请查看 Oracle Text

    【讨论】:

      【解决方案3】:

      如果您存储纯文本,它应该是 CLOB,而不是 BLOB,然后您仍然可以使用 LIKE 进行查询。 BLOB 包含 Oracle 不知道其结构的二进制数据,因此无法通过这种方式进行搜索。

      这适用于任何长度的 CLOB(至少在 Oracle 12C 上):

      SQL> create table t1 (c clob);
      
      Table created.
      
      SQL> declare
        2     x clob;
        3  begin
        4     for i in 1..100 loop
        5        x := x || rpad('x', 32767, 'x');
        6     end loop;
        7     x := x || 'z';
        8     for i in 1..100 loop
        9        x := x || rpad('x', 32767, 'x');
       10     end loop;
       11     insert into t1 values (x);
       12  end;
       13  /
      
      PL/SQL procedure successfully completed.
      
      SQL> select dbms_Lob.getlength(c) from t1 where c like '%z%';
      
      DBMS_LOB.GETLENGTH(C)
      ---------------------
                    6553401
      

      请注意,在 6,554,401 字节的 CLOB 中只有一个“z” - 就在它的中间:

      SQL> select instr(c, 'z') from t1;
      
      INSTR(C,'Z')
      ------------
           3276701
      

      【讨论】:

      • @Olafur 在下面有一个很好的有用答案:stackoverflow.com/a/16301995/510711
      • 这也是错误的。它仅适用于
      • @Olafur:你的批评是错误的,因为我已经更新了我的答案。
      • 立场更正,它曾经是(早期版本)喜欢和 instr where varchar2. 11g 和 12c 已经用 clob 版本重载了它
      【解决方案4】:

      下面的代码是使用UTL_RAW.CAST_TO_VARCHAR2 function将blob中的详细信息显示为文本,然后我们使用substr function将文本从预期数据的开头剪切到结尾。但是,如果您知道要查找的数据的位置,则可以使用 instr functionLENGTH function

      select NVL(SUBSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), 
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '<ns:xml_element>') + LENGTH('<ns:xml_element>'),
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '</ns:xml_element>') - (
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '<ns:xml_element>') + LENGTH('<ns:xml_element>'))),
          utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(blob_body))
          ) blob_body
      from dual 
      where SUBSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), 
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '<ns:xml_element>') + LENGTH('<ns:xml_element>'),
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '</ns:xml_element>') - (
      INSTR(UTL_RAW.CAST_TO_VARCHAR2(blob_body), '<ns:xml_element>') + LENGTH('<ns:xml_element>'))) like '%foo%';
      

      【讨论】:

        【解决方案5】:

        从 TABLE_NAME 中选择 * 和 dbms_lob.instr("BLOB_VARIABLE_NAME", utl_raw.cast_to_raw('search_text'), 1, 1) > 0

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-04
          • 1970-01-01
          相关资源
          最近更新 更多