【发布时间】:2011-02-27 04:09:12
【问题描述】:
是否可以使用 sql 语句搜索 blob 文本? 如果 f1 是 varchar,我可以从 $table where f1 like '%foo%' 中选择 *,那么 f1 是一个 blob 怎么样?有什么对应的部分吗?
【问题讨论】:
是否可以使用 sql 语句搜索 blob 文本? 如果 f1 是 varchar,我可以从 $table where f1 like '%foo%' 中选择 *,那么 f1 是一个 blob 怎么样?有什么对应的部分吗?
【问题讨论】:
这很可能而且很容易做到。
只需将 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
;
【讨论】:
如果是 Word 或 PDF 文档,请查看 Oracle Text。
【讨论】:
如果您存储纯文本,它应该是 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
【讨论】:
下面的代码是使用UTL_RAW.CAST_TO_VARCHAR2 function将blob中的详细信息显示为文本,然后我们使用substr function将文本从预期数据的开头剪切到结尾。但是,如果您知道要查找的数据的位置,则可以使用 instr function、LENGTH 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%';
【讨论】:
从 TABLE_NAME 中选择 * 和 dbms_lob.instr("BLOB_VARIABLE_NAME", utl_raw.cast_to_raw('search_text'), 1, 1) > 0
【讨论】: