Tuesday, October 20, 2009

Cuidado: O trim de vazio nao é vazio

Bem, pelo menos no caso do Oracle trim de vazio nao é vazio mas sim Nulo. Ok, comecei pela conclusao, entao vamos para a historia completa.

Estava eu depurando uma procedure no oracle e cheguei a conclusao que um dos sub-selects nao retornava nada e a partir dai a proc começava a perder o rumo das coisas. O select era algo bem simples:

Select campoA, campoB from Tabela where trim(campoC) = trim(parametro);

Como esse sistema veio de uma base legada temos varios campos cujo valor é ' ', ou seja, espaços em branco, por isso a proc precisa desse trim. O que estava acontecendo é que o select citado acima nao estava retornando valor nenhum. Verifiquei o valor do parametro passado e descobrir que era vazio ou ''. Lembre-se que vazio é diferente de nulo e diferente de zero. Como sabia que a tabela possui valores vazios no campo pesquisado, comecei a investigar. Eis os passos até a conclusão que decora o titulo desse post.

Primeiro eu rodei a seguinte query:

select 1 as result from dual --> retorna 1

select 1 as result from dual where trim('abc') = trim('abc')--> retorna 1

select 1 as result from dual where trim('abc') = trim('def')--> nao retorna nada

select 1 as result from dual where trim('') = trim('') --> nao retorna nada, ou seja, o where é falso

select 1 as result from dual where trim(' ') = trim(' ') --> nao retorna nada tambem, ou seja, o where é falso também. O que é estranho pois temos a mesma expressão dos dois lados do =.

Depois de pensar um pouco fiz o seguinte teste (depois de analisar algumas queries com length):

select 1 as result from dual where trim('') is null--> retorna 1

Aeeee entao descobri que o trim de vazio nao é vazio mas sim nulo! Entao o problema é quando o parametro passado é um valor vazio. Para valores nao vazios a query funciona mas quando quero comparar vazios, o select nao vai encontrar.

Para resolver esse problema acabei fazendo a query da seguinte forma, usando a funcao nvl:

select 1 as result from dual where nvl(trim(campo), ' ') = nvl(trim(parametro), ' ')

Explicacao: nvl é uma funcao que verifica se o primeiro parametro é nulo , se for a funcao retorna o segundo parametro. No meu caso eu verifico o trim do campo, se for nulo ele retorna um 1 espaco em branco. O mesmo é feito do outro lado do =, se ele vier vazio , o trim do vazio é nulo entao o nvl substitui por ' '. Se os dois forem espaco em branco, entao ' ' = ' ' , e o valor é retornado na query. Se os valores do campo e parametro forem diferentes de vazio, a query se comporta da mesma como se não tivesse o nvl.

Eis minha dica de hoje, que pode poupar algumas horas de debug na sua query. Talvez possa até haver uma maneira melhor de resolver esse problema, se houver , postem um comentário.

Have fun!

No comments: