Como funciona a conversão implicita do Oracle

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Boa tarde amigos,

Eu sei que o Oracle faz a conversão implicita de tipos, mas tem algumas situações que isto me deixa confuso. Como o caso que eu vi recentemente. Estava analisando uma package que possui uma procedure que utiliza uma condição de um IF/ELSE com um NOT IN onde é comparado um parametro VARCHAR da propria procedure com um RETURN do tipo CHAR da function, exemplo:

Selecionar tudo


Trecho da Procedure

l_num_new := trim(nvl(f_cod_new(digito => l_num_ci_dv  codcia => g_cod_cia),'#'));
l_num_ant := trim(nvl(f_cod_ant(digito => l_num_ci_dv, codcia => g_cod_cia),'#'));

...
ELSE IF (    l_num_seg     <> l_cod_cia
          OR l_num     NOT IN l_num_new,l_num_ant ) THEN

-- Ou seja, caso o l_num não contiver um dos valores do retorno da função ele entra na condição do ELSE.

Apesar desse critério não estar sendo satisfeito ele entrava na condição exibindo uma mensagem de erro ao usuário. Mas ao analisar a função percebi que o retorno da fucntion apesar de ser um CHAR no meio do seu processo é feito um cálculo que retorna um inteiro.

Ai entra a dúvida, quem criou a function declarou o retorno da function como CHAR mas no meio do processo ao fazer o cálculo esse valor passar a ser um NUMBER, nessa hora, automaticamente o Oracle faz a conversão implicita? Por que senão deveria dar erro de tipos inválidos, correto? Mas como ele não estava dando erro em tempo de execução ele retornava para a procedure o valor numérico calculado na function, mas ao comparar um NUMBER com um VARCHAR apesar dos valores serem aparentementes iguais a condição não o reconhecia como tal. Exemplo 8 = "8" = FALSE. Por isso, ele estava entrando na condição do ELSE, porque ao comparar um numérico com um alfa ele retornava false por ser diferente mas por ter um NOT ele inverte o valor lógico satisfazendo a condição. A solução neste caso foi colocar um TO_CHAR na variavel do RETURN da function para comparar os valores com o mesmo tipo e resolveu o problema.

Att.,
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

É isso mesmo que você postou... a questão é que em conversão implícita os problemas acontecem 99% das vezes porque essas conversões são totalmente dependentes das configurações de NLS vigentes no servidor no momento que o código executou (que podem ser manipuladas por alter session, etc para complicar mais).

Ou seja, o formato para o qual um número será convertido para caractere depende de diversos parâmetros no servidor. Num ambiente de desenvolvimento eles podem estar com um valor para os parâmetros... em produção podem ser outros. Um usuário pode ter um... outro usuário pode ter outro. O idioma pode ser outro, a região, o separador de milhar e decimais... enfim.

Nada deve ser deixado para ser feito por conversão explícita: todas as conversões em comparações devem ser feitas explicitamente pelo desenvolvedor, sob risco de estar implementando um bug no sistema que vai ser uma bomba relógio sem data nem hora para estourar.
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

fsitja escreveu:Nada deve ser deixado para ser feito por conversão explícita:
Corrigindo:
Nada deve ser deixado para ser feito por conversão IMPLÍCITA
:-o
Avatar do usuário
fsitja
Rank: OraSauro
Rank: OraSauro
Mensagens: 611
Registrado em: Seg, 19 Jan 2009 4:29 pm
Localização: Gaúcho no Rio de Janeiro - RJ
"The scars exist to remind us that the past was real"
Campanha: Como fazer uma pergunta e obter uma resposta.
http://tkyte.blogspot.com/2005/06/how-t ... tions.html

OCA & OCP Developer — OCE SQL Expert — OCS Data Warehousing Specialist

Para complementar... mesmo que você use o to_char(), ele deve conter sempre a máscara de formato da conversão.
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Obrigado pelos esclarecimentos amigo! No meu caso eu só coloquei o TO_CHAR sem formatação pois sempre vai retornar um inteiro. Geralmente isso gera muito problema, com datas, valores monetários entre outros. No entanto acredito que uma solução seria alinhar a configuração de todos os ambientes conforme os parâmetros do servidor.

Eu peguei casos de valores monetários (até postei aqui) que nem o "ALTER SESSION" estava me ajudando porque além de ser outra formatação (máscara) era feita uma validação sobre a máscara, além de eu achar "arriscado" a utilização do "ALTER SESSION", na verdade parece mais uma "gambi" para resolver o problema, né?

Abç.,
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 11 visitantes