web-dev-qa-db-fra.com

recherche de texte blob oracle

Est-il possible de rechercher dans le texte blob à l'aide de l'instruction sql? Je peux faire sélectionner * dans $ table où f1 comme '% foo%' si le f1 est varchar, que diriez-vous que f1 est un blob? Une contrepartie pour ça?

19
Skay

C'est tout à fait possible et facile à faire.

Utilisez simplement dbms_lob.instr en conjonction avec utl_raw.cast_to_raw

Donc, dans votre cas, si t1 est un BLOB, la sélection ressemblerait à:

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
;
61
Olafur Tryggvason

S'il s'agit d'un document Word ou PDF document, consultez Oracle Text .

4
Gary Myers

Si vous stockez du texte brut, il doit s'agir d'un CLOB, et non d'un BLOB, et vous pouvez toujours interroger à l'aide de LIKE. Un BLOB contient des données binaires dont Oracle ne connaît pas la structure, il ne peut donc pas les rechercher de cette manière.

Cela fonctionne pour les CLOB de n'importe laquelle longueur (au moins sur 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

Notez qu'il n'y a qu'un seul "z" dans ce CLOB de 6 554 401 octets - en plein milieu:

SQL> select instr(c, 'z') from t1;

INSTR(C,'Z')
------------
     3276701
4
Tony Andrews

le code ci-dessous est d'afficher les détails de blob sous forme de texte en utilisant fonction UTL_RAW.CAST_TO_VARCHAR2 puis nous utilisons fonction substr pour couper le texte du début des données attendues jusqu'à la fin. cependant, vous pouvez utiliser fonction instr , fonction LENGTH , si vous connaissez l'emplacement des données que vous recherchez

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%';
0
NoOoNY