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!

segunda-feira, 5 de agosto de 2013

Removendo Datafiles Perdido

Deletando um datafile perdido na pasta:

Resolvi postar esta situação porque aconteceu comigo quando estava aprendendo lidar com Oracle.

Eu exclui uma tablespace que possuía um único datafile.
E quando fui criar a tablespace novamente, o datafile já existia, então o Oracle não me deixou criar a tablespace.
Então conclui que, quando se "dropa" umaa tablespace, o oracle não apaga o arquivo do disco também, ele mantêm o cara lá.

bom, ai fui atrás de tentar excluir o datafile, mas não queria fazer isto via Sistema Operacional, eu gostaria de fazer isto através do Oracle.

Então tentei os seguintes comandos:
ALTER TABLESPACE TESTEX DROP DATAFILE '/u01/dados/mydatafile.fdb';
Não deu, porque a tablespace não existia mais..."dãããããã".

ALTER DATABASE DROP DATAFILE '/u01/dados/mydatafile.fdb';
Comando não reconhecido pelo ORACLE.

A solução foi, cria um novo tablespace com um novo datafile.

CREATE TABLESPACE TESTEY DATAFILE '/u01/dados/mynewdatafile.fdb' 1M;

Então só depois acrescentar a este tablespace o datafile perdido.

CREATE TABLESPACE TESTEY ADD DATAFILE '/u01/dados/mydatafile.fdb' 1M;

agora eu tenho dois datafiles no meu tablespace:

então agora vem um comandinho que é mágico para deletar os tablespace e os datafiles:

DROP TABLESPACE TESTEY INCLUDING CONTENTS AND DATAFILES;

Pronto, problema resolvido.


segunda-feira, 3 de setembro de 2012

Usando PL/SQL


Oi Amigos,

hoje vou falar de PL/SQL, uma linguagem desenvolvida pela ORACLE a fim de aumentar as possibilidades do SQL, muitos bancos fazem uso desta linguagem, o postgre por exemplo usa pl/pgsql com o mesmo objetivo.
Sabemos que algumas coisas são impossíveis de fazer somente com o SQL (Linguagem de consulta Estruturada), por exemplo... se você tem um mesmo código SQL para fazer uma consulta, em várias partes do seu sistema.. ou um SUB-SELECT para retornar um único valor, você pode cogitar a ideia de criar um recurso PL/SQL, uma função ao qual venha te retornar estas informações, onde a mesma pode ser aplicada em vários lugares do seu fonte.
O banco ORACLE é esperto e sabe diferenciar um código SQL e um PL/SQL em runtime, então muitas vezes você precisará utilizar um código SQL dentro do PL/SQL, mas fique tranquilo, pois o banco vai saber separar (à gasolina do álcool na hora de usar no motor!!!.. he he he, se é que você me entende!).

Então segue uma estrutura de um bloco PL/SQL, uma bloco anônimo:

-- usa-se DECLARE para iniciar o bloco e declarar
DECLARE

-- declaração das variáveis com tipo e valor inicial;
V_TESTE INTEGER := 0;

-- Inicio do bloco não se usar ";" aqui, somente no final
BEGIN

-- Select que retornar um ÚNICO registro e Coluna, e o resultado é passado para a V_TESTE
-- atráves do operador INTO.
SELECT COUNT(*) INTO V_TESTE FROM MINHA_TABELA;
-- comando para imprimir na saida DBMS.
dbms_output.put_line('Total de resgistros: '||v_teste);

END;


Espero que ajude!!!
abraço!

terça-feira, 28 de agosto de 2012

Funções NVL e NVL2 do Oracle


Olá Amigos...

Neste post eu vou falar sobre a função NVL() e NVL2()..

NVL é um função de 2 parâmetros que tem por objetivo testar o primeiro parâmetro, se o mesmo for nulo, então retornará o valor do segundo parâmetro caso contrário retorna o valor do primeiro parâmetro.

Exemplificando, se informarmos um campo de um determinado tipo no primeiro parametro do NVL e no segundo informar ZERO, então ao rodar o SQL o valor do primeiro campo for NULO o valor retornado será ZERO.

select NVL(codigo_cliente, 0) as campo from dual;

retorno

campo
-------|
0 |


O NVL2 já nos ajuda um pouco mais por se tratar de um operador "TERNÁRIO" ( não é terneiro tá, é ternário!!!!).

Sua sintaxe é a seguinte:

NVL2(teste, true, false)..

como a primeira função NVL que retorna o valor do segundo parâmetro se o primeiro parâmetro for NULO, o NVL2 retorna o segundo parâmetro se o primeiro não for nulo, ou o valor do terceiro parâmetro se for nulo.
Exemplificando:

select NVL2(codigo_cliente, 1 , 0) from dual;

se codigo_cliente for nulo, então o retorno será 0 caso contrário 1.

isto também pode ser aplicado como teste de filtro depois da clausula WHERE ao inves de testar se o campo é nulo com IS NULL ou IS NOT NULL pode se usar o NVL ou NVL2

Neste SQL eu quero somente os registros onde o código do cliente forem nulos (ONDE OS NULOS SERÃO ZERO... HE HE HE).

SELECT * FROM clientes
WHERE NVL(codigo_cliente,0) == 0;

Claro que você poderia também usar :
SELECT * FROM clientes
WHERE codigo_cliente IS NULL;

OU

SELECT * FROM clientes
WHERE COALESCE(codigo_cliente, 0) == 0 ;

Mas a minha intensão neste post é apresentá-los esta funcionalidade ORACLE.

Abraço a todos.

segunda-feira, 27 de agosto de 2012

Wellcome


Olá pessoal, depois de várias vezes pensar e criar um blog para postar minhas ideias e conhecimento, resolvi tomar um copo de coragem e por a mão na massa (ou os dedos no teclado!! rsrs).
Meu método de aprendizagem é este, eu aprendo e massifico melhor quando consigo explicar oque aprendi, e neste blog eu quero colocar e expor o conhecimento que venho adquirindo ao longo do tempo, e de certa forma também vejo como um meio de levantar debates de melhorias através do comentários postados pelo visitantes.
Espero que curtam este blog, e prometo que estarei sempre postando informações novas sobre as tecnologias que venho conhecendo para que não se torne mais um amontoado de conteúdo sem relevância, só para fazer o indexador da google trabalhar mais (he he he), abraço a todos e vamos lá.