terça-feira, 6 de agosto de 2013

Lidando com campo BLOB

Olá Amigos(a), tudo bem?

Ocorreu uma situação onde precisei imprimir um campo BLOB que mantinha um XML de nota fiscal eletrônica.

O sistema que uso aqui na empresa não me permite trabalhar com um campo BLOB por se tratar de um campo de armazenamento de binários, levando em consideração o fato de que eu “SEI” que neste campos nosso sistema só armazena texto, então precisei converter o campo para CLOB.

Para isto precisei fazer uso dos pacotes DBMS que trabalha com os LOBS.

Criei uma função onde eu passo um BLOB e que me retorna um CLOB.
Também passo mais dois parâmetros, são eles: v_amount e v_offset.
Uso “v_amount” para dizer qual o tamanho em bites que pretendo extrair a partir de v_offset.
Não posso deixar passar um campo de uma vez, pois corro o risco do XML ser maior que a buffer disponível na constante “dbms_lob.lobmaxsize” (que carrega o valor do parâmetro DB_BLOC_SIZE do banco no caso o meu é 8192).

Até pensei em mudar o parâmetro, mais por um simples detalhe, entendi que não poderia. Isto porque este valor é definido na criação do banco de dados. Como o Oracle trabalha com blocos, então o banco aqui foi definido com 8192 de blocagem.

Agora segue a função:

create or replace function CONVERT_BLOB_TO_CLOB(v_blob_in in blob, v_amount in integer, v_offset in integer)
return clob is

v_file_clob clob;
v_blob blob;
v_file_size integer := dbms_lob.lobmaxsize; – Aqui eu pego o valor maximo (DB_BLOC_SIZE).
v_dest_offset integer := 1;
v_src_offset integer := 1;
v_blob_csid number := dbms_lob.default_csid;
v_lang_context number := dbms_lob.default_lang_ctx;
v_warning integer;
v_length integer;
v_off integer := v_offset;

BEGIN

– OBTER O TAMANHO TOTAL DO CAMPO
v_length := dbms_lob.getlength(v_blob_in);

– VERIFICAR SE O OQUE ESTA SENDO PEDIDO DE FATO EXISTE.
IF(v_length < v_off ) THEN
v_off := v_length;
End If;

– PEGAR SOMENTE UM PEDAÇO DO VALOR
v_blob := dbms_lob.substr(v_blob_in,v_amount, v_off);

– RESERVA UMA AREA TEMPORÁRIA PARA CONVERTER OS DADOS.
dbms_lob.createtemporary(v_file_clob, true);

– CONVERTE OS DADOS
dbms_lob.converttoclob(v_file_clob,
v_blob,
v_file_size,
v_dest_offset,
v_src_offset,
v_blob_csid,
v_lang_context,
v_warning);

Return v_file_clob;

END;

– USANDO FUNCTION NO SQL, PERCEBA QUE PASSO O MESMO CAMPO PELOMENOS UMAS TRES VEZES.
– O TIPO VARCHAR2 SÓ ENTENDE ATÉ 4000 CARACTERS, E NO MEU CASO, MEU SISTEMA TAMBÉM NÃO NÃO LÊ CLOB, ENTÃO DEPOIS DA FUNCTION PRECISEI FAZER CAST DO CLOB PRA VARCHAR2.

Select
cast(CONVERT_BLOB_TO_CLOB(XML, 4000, 1) as varchar2(4000)) as MYXML1,
cast(CONVERT_BLOB_TO_CLOB(XML, 4000, 4001) as varchar2(4000)) as MYXML2,
cast(CONVERT_BLOB_TO_CLOB(XML, 4000, 8001) as varchar2(4000)) as MYXML3
From TABELAX Where TABELAX.nfe = '01 000067861';


Agora resta concatenar os campos no teu sistema e trabalhar da forma que achar melhor.

espero ter ajudado!

2 comentários:

  1. Fera, tenho uma dúvida e se puder me ajudar.
    Estou criando um campo clob em meu banco(oracle 11g) direto via PLSql e o mesmo está ficando com o tamanho restrito a 4000 caracteres. Sabe me dizer o que posso fazer para que aceite o tamanho máximo permitido pelo campo do tipo LOB ?
    Obrigado

    ResponderExcluir
  2. Parabens... nunca vi solução tao simples para extrair blob do oracle...

    ResponderExcluir