Problema formatação de valor

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: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Colegas,

Estou com um problema que na verdade é um paradoxo.

Eu estou analisando uma pkg que tem uma função que busca dados em uma tabela e retorna uma coluna de datatype de VARCHAR2(80) e atribui o mesmo a um TYPE OBJECT de datatype NUMBER(17,2). Eu consigo tratar essa conversão no banco, porém como eu estou na parte de análise dos dados e não tenho acesso a aplicação que recebe os valores deste TYPE eu não sei qual é o valor ou formato esperado, por dedução acredito que este TYPE tenha sido criado com NUMBER(17,2) para compatibilizar com a aplicação.

Acontece que quando eu debugo em minha máquina os testes são concluidos com sucesso, mas quando eu subo para homologação e os testes são efetuados através da aplicação dá erro de convesão de tipo. Aparentemente pela descrição é o problema não está na pkg. No entanto quando solicitei para que os meus teste fossem feitos na máquina de configuração diferente de um colega, começou a dar erro de conversão também. Notem que as configurações regionais da máquina dele estão em inglês enquanto que na minha está em português.

Ai começa a novela, pois teoricamente na aplicação deveria estar pegando a configuração do servidor. E o que está acontecendo, o formato da moeda muda, ou seja, os separadores são invertidos causando o erro. Para tentar solucionar o caso, eu tentei aplicar uma máscara no valor, no entanto não deu certo. Depois em uma medida mais drastica eu criei um procedure com transação autonoma dentro da minha pkg para conseguir executar um comando DDL para forçar a alteração para sessão do usuário para um formato de moeda específico. Neste caso o que está acontecendo é o seguinte, a primeira vez que a pkg é executada passa sem erro já na segunda dá erro. E fica alternando entre uma certa e outra errada, é como se a sessão ficasse presa com o formato definido, depois fechasse e abre novamente com o formato anterior e da próxima dá certo novamente.

Eu sei que explicando assim parece meio complicado, mas na verdade o problema todo é que a tabela e coluna do valor de origem é um campo aberto, portanto o usuário pode digitar o que ele bem entender, ou seja, ele sabe que tem que ser um valor numérico mas pra ele isso é transparente então pode variar valores com vírgula, ponto, os dois, ou nenhum! E o para ajudar o TYPE e de outro datatype. Para mim, a solução mais razoável seria alterar o TYPE para o mesmo datatype da tabela e fazer essa validação na aplicação, no entanto não há viabilidade de fazer isso.

Por isso, gostaria a ajuda dos senhores para uma solução alternativa para este caso.

Caso puderem me ajudar, fico no aguardo.

Agradecido.

Att.,
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

Tinho,

Creio que este seria um caso de configuração regional que é adotada pela sessão onde você está executando.

Tente executar esta querie no servidor e na sua estação de trabalho:

Selecionar tudo

SELECT * FROM NLS_SESSION_PARAMETERS
Acredito que os valores das duas sessões apresentem resultados diferentes.

Como você poderia para tentar resolver este problema?

Você poderia alterar a sua package para alterar as configurações da sessão SQL onde a package está sendo executada, para deixar a sessão da package igual às configurações do servidor de banco, onde nenhum problema ocorre.

Por exemplo:

Selecionar tudo

BEGIN
  EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS= ''.,'' ';
  ...
Se você alterar as configurações de sessão durante a execução da package, creio que tanto faz onde você executará sua querie (sua máquina, servidor de banco ou máquina do colega).

Bem .. mas só me preocupa o fato do usuário poder digitar qualquer valor no campo (com virgula, ponto ou nada). Talvez você precise fazer alguma espécie de consistência na aplicação para forçar o usuário a somente usar vírgula ou ponto.

Talvez uma explicação melhor sobre formato de números e sessões oracle possa ser obtida no link abaixo:

http://stackoverflow.com/questions/1113 ... s-not-work

Não sei se consegui responder adequadamente a sua pergunta.

Abraços,

Sergio Coutinho
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Sérgio bom dia,

Agradeço as informações mas quando me referi que estou executando um comando DDL dentro de uma transação autonoma eu estou exatamente executando o script:

Selecionar tudo

  EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS= ''.,'' ';

Eu já havia rodado o script:

Selecionar tudo

  SELECT * FROM NLS_SESSION_PARAMETERS

E de fato as configurações estão diferentes.

Porque eu resolvi criar uma transação autonoma, porque dentro da sessão principal da package o Oracle está restringindo a execuçao de um comdando DDL após um DML na mesma sessão. Acontece que está solução, funciona na primeira execução e na segunda retorna o erro, em seguida, na próxima execução funciona novamente e depois volta a dar erro e assim vai seguindo sucessivamente. Eu cheguei até a comitar após a instrução do script DDL pensando que pudesse deixar alguma sessão presa.

Quanto ao problema do campo ser aberto, eu sei que é critico, mas como nossa equipe é responsável pelo banco de dados nos temos limitações de acesso a aplicação e não há muito o que possamos fazer além de tentar consistir os valores que recebemos. Esses dados geralmente vem de uma outra aplicação e de outra equipe que realiza a carga em nossas tabelas e depois de todo esse fluxo existe uma outra aplicação que consulta esses dados, que onde está dando o erro.

Por isso que eu disse, acredito que tenha havido um erro de definição, pois a validação deveria estar na aplicação, mas como a package faz com se fosse um intermédio entre os dados recebidos e aplicação que consulta esses valores, existem ainda a incompatibilidade de datypes, mas até então eu consigo tratar a conversão no banco mesmo. O problema é na consuta dessa outra aplicação, que eu não conheço e não tenho acesso aos fontes.

está difícil! Por isso eu disse se tratar de um paradoxo pois nos encontramos de mãos atadas, mas precisamos dar uma solução.

Att.,
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Pelo que entendi o campo origem é texto aberto, porém deve conter apenas números e colocar a informação num campo destino tipo number(17,2), resumidamente.
Quando você faz os testes em sua máquina, ela está apontando para mesmos dados, mesma base de homologação???
Se for diferente acredito que seja problema nos dados mesmos. Aí teria que analisar os dados problemáticos e fazer ajustes, se for possível.
Se possuem outro caractere diferente(ex ' '), se possui mais de 1 virgula ou mais de um ponto, ou ponto e virgula ao mesmo tempo.
Se for mais simples, apenas números as vezes com ponto as vezes com virgula, e na conversão de um ou outra pontuação ele falha, precisaria fazer uma substituição de um pelo outro que é o reconhecido pelo ambiente.

Enfim, se não tiver nenhuma validação nesse campo na aplicação, para que registre apenas números, mesmo sendo em um campo tipo CHAR, suas informações estão bastante comprometidas.
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Sim, além das informações correrem esse risco de comprometimento e consistência é quase impossível prever o que o usuário irá digitar em um campo aberto, mesmo que este seja orientado a digitar apenas números e seus separadores. No entanto o problema não é esse até o momento, pois não apareceu nenhum caso. Por isso, estou conseguindo tratar o CAST no banco, ou seja, trato a conversão do VARCHAR2 para o OBJECT de datatype NUMBER(17,2). Dai quando esse valor vai ser recebido após uma consulta na aplicação é gerado o erro. Eu já havia feito os testes na minha máquina, considerando a configuração da mesma e tinha dado certo, estava praticamente resolvido, fiz teste simulandos várias possibilidades de digitação e passou tranquilo. Quano eu subi a alteração para homologação para efetuar os testes a partir da aplicação começou a estourar os erros, voltei a versão anterior e retomei os teste, foi quando eu tiver a "brilhante" idéia de fazer os testes na máquina de configuração americana de um colega, dai o erro ficou perceptível a configuração onde a aplicação está sendo executada está diferente. Ai começa a saga, pois tentei forçar uma mascara para valor numérico, o que não deu certo, tentei forçar a alteração da configuração através do comando DDL e como explicado anteriormente na primeira execução dá depois na proxima da erro e assim segue sucessivamente, com uma certa e outra errada.

Não estou sabendo mais o que fazer. Eu sei que o correto seria fazer validações na aplicação que inputa os valores no banco, e no banco trabalhar com datatypes compatíveis e na aplicação que recebe esses valores fazer o tratamento de exibição de valores. Mas eu não tenho acesso a aplicação e não posso solicitar ao cliente que faça essa validações no front-end. Tenho que dar um jeito por aqui, mas não sei mais como.

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

Você tem como postar o código do erro (ORA-XXXX), e o trecho de código que causa ele, com uma estrutura BEEEEM (mas bastante mesmo) simplificada fazendo só a conversão que você precisa, para reproduzirmos o comportamento da aplicação e o erro em nossas máquinas?

Se puder facilitará muito o diagnóstico e a solução. Não gosto de dar palpite sem saber o que está acontecendo, mas parece que uma conversão explícita usando NLS_NUMERIC_CHARACTERS definido no comando, em vez de tentar setar a sessão ou o servidor ficando independente de qualquer configuração que esteja definida no ambiente.
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

Reli os posts e estou com dificuldade para entender... a conversão do VARCHAR2 para o OBJECT de datatype NUMBER(17,2) é feita na tal package? É aí que dá o erro? E você pode ou não alterá-la?
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Então, o problema não está na package pois na package eu consigo tratar a conversão e/ou formato dos valores. O problema é que no momento que é feito a consulta do valor pela aplicação dá o erro e é a tal a aplicação que eu não tenho acesso e não posso alterá-la.

Grato.
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Se o dado já foi inserido num campo NUMBER... muito estranho dar problema num campo NUMBER.
Você poderia fazer um teste eliminando os decimais( ou multiplicar por 100 os valores),para ao menos tentar eliminar os decimais das lista de provaveis motivadores do problema.
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Pois é, por isso quando fiz os testes na minha máquina deu certo e quando testei na máquina do colega, cuja a qual possuia configurações diferentes deu erro. Isso eu percebi que ocorre por causa da configuração regional, que vai inverter os separadores de acordo com a configuração. Mas como vou tratar o que eu não sei o que vai o valor que virá?!

Eu tentei montar um script prevendo todas as possibilidades, mas eu não estou com tempo para desenvolvê-lo e testá-lo, por isso tive que parar e atender a solicitação do usuário que reclama exatamente do separador de decimais, por isso, fiz o que nem você descreveu, mas eu retiro a vírgula ou o ponto do separador de decimais e divido por 100 e ele aplica o separador conforme as configurações locais.

Segue abaixo:

Selecionar tudo


DECLARE
 vVALOR VARCHAR2(19) := '156.56';
 vRESULT NUMBER(17,2);
BEGIN
  SELECT TRIM( DECODE( SUBSTR(vVALOR, INSTR(vVALOR,','),1),',', REPLACE(vVALOR, SUBSTR(vVALOR, INSTR(vVALOR,','),1),'' ), 
                                                                REPLACE(vVALOR, SUBSTR(vVALOR, INSTR(vVALOR,'.'),1),'' ) 
                     ) ) / 100
    INTO vRESULT
  FROM DUAL;
  
  DBMS_OUTPUT.PUT_LINE(vRESULT);
END;

Mas sabe como é que é né. Apesar do usuário ser orientado pela área de negócio e operações que o campo é para valores monetários, pode vir qualquer coisa! Então não é uma solução completa, uma hora ou outra quando vir separador de milhar ou caracteres especiais ou letras vai dar erro.

Segue o esboço da solução que estava tentando desenvolver para tentar prever todas as possibilidades:

Selecionar tudo


DECLARE
  vVALOR     VARCHAR2(19); 
  vCONVERSAO VARCHAR2(19);
  vTYPE      NUMBER(17,2);
  --
  vCARACTER1 CHAR(1);
  vCARACTER2 CHAR(1);  
  --
  vPOSICAO1  NUMBER;
  vPOSICAO2  NUMBER;
  --
  vBUSCA     NUMBER; 
BEGIN

  /* AMBIENTE PARA TESTE PARA VALIDACAO E FORMTACAO DO VALOR */
  /* ESSE BLOCO ANONIMO SERÁ CONVERTIDO EM UMA FUNÇÃO        */  

  vBUSCA := 0;
  
  BEGIN
    -- BUSCA O VALOR DO DADO VARIAVEL A SER UTILIZADO NO TESTE
    IF vBUSCA = 0 THEN
      SELECT X.VAL_CAMPO
        INTO vVALOR
        FROM XXXXXXX X
       WHERE X.COD_CIA     = 1
         AND X.COD_RAMO    = 215
         AND X.NUM_SPTO    = 0
         AND X.MCA_VIGENTE = 'S'
         AND X.COD_CAMPO   = 'DADO_VARIVAVEL';
         
       DBMS_OUTPUT.PUT_LINE('VALOR (DV): ' || vVALOR);
    ELSE
      -- ATRIBUI VALOR FIXO AO QUAL SE PRETENDE TESTAR NA VARIÁVEL;
      --  vVALOR := '999999999108075'; /* SEM PONTUAÇÃO */
      --  vVALOR := '1080,75';  /* COM VIRGULA          */
      --  vVALOR := '1080.75';  /* COM PONTO            */
      --  vVALOR := '1.08075';  /* COM PONTO            */
      --  vVALOR := '1,08075';  /* COM VIRGULA          */
      --  vVALOR := '1.080,75'; /* COM PONTO E VIRGULA  */
      vVALOR := '1,080.75';     /* COM VIRGULA E PONTO  */
      DBMS_OUTPUT.PUT_LINE('VALOR (DV): ' || vVALOR);        
    END IF;
  END;

  --
  
  BEGIN
    -- PEGA POSIÇÃO DOS CARACTERES
    SELECT  instr(vVALOR,'.')
           ,instr(vVALOR,',')
      INTO  vPOSICAO1
           ,vPOSICAO2
      FROM DUAL;   
          
    -- DEVOLVE OS CARACTERES EM CADA POSIÇÃO          
    SELECT  SUBSTR(vVALOR,vPOSICAO1,1)
           ,SUBSTR(vVALOR,vPOSICAO2,1) 
      INTO  vCARACTER1
           ,vCARACTER2
      FROM DUAL;     
      
    -- EXIBE CADA CARACTER REFERENTE A SUA POSIÇÃO
    DBMS_OUTPUT.PUT_LINE('POSICAO: ' || vPOSICAO1 || ' SEPARADOR: ' || vCARACTER1);    
    DBMS_OUTPUT.PUT_LINE('POSICAO: ' || vPOSICAO2 || ' SEPARADOR: ' || vCARACTER2);
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      vPOSICAO1  := 0;
      vPOSICAO2  := 0;
      vCARACTER1 := 0;
      vCARACTER2 := 0;           
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('CODIGO: ' || SQLCODE || ' - ' || 'ERRO: ' || SQLERRM);
  END;  

  --
  
  BEGIN
    -- TRATAMENTO DO VALOR
    IF (    vCARACTER1  = '.' OR vCARACTER1  = ',' 
         OR vCARACTER2  = '.' OR vCARACTER2  = ','
         OR vPOSICAO1  <> 0   OR vPOSICAO2  <> 0 ) THEN
      
      -- TESTA PONTO (".")
      IF ( vPOSICAO1 > vPOSICAO2 AND vCARACTER1 = '.' ) THEN
        DBMS_OUTPUT.put_line('SEPARADOR DE DECIMAL IGUAL A: ' || vCARACTER1); -- XXX.XX
  	    DBMS_OUTPUT.put_line(vCARACTER2||vCARACTER1);
        
        --
	    ELSE IF ( vPOSICAO1 < vPOSICAO2 AND vCARACTER1 = '.' ) THEN
        DBMS_OUTPUT.put_line('SEPARADOR DE MILHAR IGUAL A: ' || vCARACTER1);	-- X.XXXXX
  	    DBMS_OUTPUT.put_line(vCARACTER1||vCARACTER2);
        --

      -- TESTA VÍRGULA (",")         
      ELSE IF ( vPOSICAO2 > vPOSICAO1 AND vCARACTER2 = ',') THEN
	      DBMS_OUTPUT.put_line('SEPARADOR DE DECIMAL IGUAL A: ' || vCARACTER2); -- XXX,XX
	      DBMS_OUTPUT.put_line(vCARACTER1||vCARACTER2);
        --
      ELSE IF ( vPOSICAO2 < vPOSICAO1 AND vCARACTER2 = ',') THEN
	      DBMS_OUTPUT.put_line('SEPARADOR DE MILHAR IGUAL A: ' || vCARACTER2);	-- X,XXXXX
	      DBMS_OUTPUT.put_line(vCARACTER2||vCARACTER1);
        --        

      -- TESTA PONTO E VÍRGULA (".,")
      ELSE IF     (    vPOSICAO1 > vPOSICAO2 AND vCARACTER1 = '.'  -- XXX.XX OU XXX,XX
                    OR vPOSICAO2 > vPOSICAO1 AND vCARACTER2 = ',' ) 
              AND (    vPOSICAO1 < vPOSICAO2 AND vCARACTER1 = '.'  -- X.XXX,XX OU X,XXX.XX / X.XXX.XX OU X,XXX,XX
                    OR vPOSICAO2 < vPOSICAO1 AND vCARACTER2 = ',' )  THEN
	      DBMS_OUTPUT.put_line(vCARACTER1);
	      DBMS_OUTPUT.put_line(vCARACTER2);
        --
      END IF;
      END IF;
    	END IF;
	    END IF;
      END IF;
  
    ELSE
      DBMS_OUTPUT.PUT_LINE('não POSSUI PONTUACAO');
    END IF;
    
    -- ATRIBUIÇÃO DO VALOR TRATADO A VARIAVEL vTYPE CUJO DATATPE É DIFERENTE
    -- 
    
  EXCEPTION          
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('CODIGO: ' || SQLCODE || ' - ' || 'ERRO: ' || SQLERRM);        
  END;
  
END;

Camaradas obrigado pela força. Por enquanto, problema temporariamente resolvido.

Att.,
DanielNN
Moderador
Moderador
Mensagens: 641
Registrado em: Seg, 03 Set 2007 3:26 pm
Localização: Fortaleza - CE
att,

Daniel N.N.

Para "conversões", fiz um select aqui para te ajudar nas conversões independente de ponto, virgula ou da quantidade deles.Vê a ultima pontuação e conta as casas. Além disso a função translate() ajuda a tirar as pontuações:

Selecionar tudo

select &teste                 ORIGINAL
     , Translate(&teste,' ,.',' ') LIMPO
     , length(&teste)         TAMANHO
     , instr(&teste,'.',-1)   ULTIMO_PONTO
     , instr(&teste,',',-1)   ULTIMA_VIRGULA
     , DECODE(SIGN(instr(&teste,'.',-1)-instr(&teste,',',-1)),1,instr(&teste,'.',-1),instr(&teste,',',-1)) MAX_P
     , length(&teste) - DECODE(SIGN(instr(&teste,'.',-1)-instr(&teste,',',-1)),1,instr(&teste,'.',-1),instr(&teste,',',-1)) NUM_CASAS
     , POWER(10,length(&teste) - DECODE(SIGN(instr(&teste,'.',-1)-instr(&teste,',',-1)),1,instr(&teste,'.',-1),instr(&teste,',',-1))) MULTIPLICADOR
  from dual
Mas é bom dar uma aprofundada nos parâmetros de configuração como o Sérgio falou.
Dá uma olhada no parâmetro NLS_NUMERIC_CHARACTERS:
http://docs.oracle.com/cd/B28359_01/ola ... ons072.htm
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Agradeço mais uma vez a ajuda. Assim que der vou analisar com calma a query que você fez.

Eu tentei executar um script DDL na package principal, no entanto o oracle estava restringindo a execução de um comando DDL na mesma sessão de um comando DML não terminado, ou em aberto. O problema é que existem diversas packages aninhadas e que executam funções e procedures com scritps de insert, update, delete. A solução encontrada foi criar um procedure implicita com assinatura de transação autonoma dentro da package para criar uma sessão paralela para poder executar o instrução DDL, a instrução DDL é a seguinte:

Selecionar tudo


-- onde eu verificava se o separador decimal era ponto ou vírgula e de acordo com a condição alterava o parametro NLS_NUMERIC_CHARACTERS

EXECUTE IMMEDIATE('ALTER SESSION SET NLS_NUMERIC_CHARACTERS='',.''');

Dai como eu relatei, essa execução "forçada" da instrução DDL parecia ter funcionado, porque a principio não estava dando erro. Mas durante os testes foi identificado que na primeira execução a package é executada com sucesso, já segunda vez, já dá erro e assim sucessivamente, ou seja, uma execução correta outra errada. É um comportamento estranho, não sei bem o que pode estar acontecendo! É como se a cada execução ficasse uma sessão presa e como são duas sessões distintas, eu acredito aconteça mais ou menos isso:

* sessão principal: package;
- com a configuração regional "original" da maquina onde está sendo realizado a consulta pela aplicação;
- executa sub-rotinas;

* aberta a sessão paralela;

* continua a execução da package;
- executa a função que busca o valor e atribui ao OBJECT;

* continua a execução da package;
- executa sub-rotinas;

O que eu estou tentando retratar é que as intervenções que eu fiz estão no meio do processo e com duas sessões simultâneas. Então a questão é, quando a sessão principal é encerrada a sessão paralela continua em aberto? As alterações DDL vão consistir apenas enquanto a sessão estiver aberta. O que acontece na proxima execução caso a sessão fique aberta? E se estiverem vários usuários acessando simultâneamente a mesma package, existiram diversas outras sessões abertas. E se em algum outro ponto da aplicação algum usuário estiver acessando uma outra funcionalidade que execute um DDL fazendo o inverso do que eu estou fazendo?

Sei lá, são tudo hipóteses que devem ser consideradas. Por isso, acho que forçar a execução de um comando DDL em uma sessão paralela seja uma medidad muito drástica e arriscada.

Att.,
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Além disso, pode existir calculos que dependam do formato local para ser executado, ou seja, eu estou alterando a formatação do valor. E se na mesma sessão que o usuário estiver fazendo a consulta ele também conseguir efetuar cálculos, gerar relatórios? Qual vai ser o efeito e impacto disso?

Por isso, neste caso, reforço que eu acho arriscado utilizar o recurso de execução em uma sessão paralela dentro de outra.
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

Tinho,

Estava pensando no seu problema e talvez você possa resolver o mesmo com alguns procedimentos.

Para padronizar o NLS_NUMERIC_CHARACTERS da sessão - independente de que local se conecte - você pode criar uma TRIGGER de LOGON para acertar este parâmetro de sessão. Se por exemplo você (e sua aplicação) se loga com o usuário XPTO, você deve criar uma trigger de logon associada a este usuário que configure automaticamente a sessão (ALTER SESSION SET NLS_NUMERIC_CHARACTERS).

Para forçar o usuário a informar corretamente um número válido para este campo VARCHAR2, você poderia adotar a "horrorosa gambiarra" de criar uma coluna adicional NUMBER nesta tabela. O próximo passo seria o de criar uma trigger que faria com que esta coluna NUMBER fosse atualizada com qualquer valor que fosse inserido na coluna VARCHAR2 (usando as funções DECODE,TRANSLATE,TO_NUMBER, etc). Se a conversão não for possível, deve aparecer um erro para o usuário.

É lógico que tudo isso exige um teste completo do seu sistema.

Mas eu desconfio que não seja possível você encontrar uma solução 100% adequada para o seu problema, uma vez que você se depara com uma pequena caixa preta (o sistema que você não tem como avaliar o que faz).

Abraços e boa sorte,

Sergio Coutinho
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 317
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Coutinho,

Obrigado. De fato seria uma solução. O problema é que para qualquer implementação nova no sistema, isso depende de uma demanda que justifique essa intervenção e posteriormente deve ser aprovada pela equipe de projetos e seguir todos os tramites burocráticos até a efetivação da ação. E você deve saber como essas coisas são demoradas. Eu estou alocado neste projeto, e como o mesmo é dividido por módulos e camadas eu não tenho acesso direto ao sistema e não conheço com detalhes o seu mecanismo de funcionamento e nem mesmo o fluxo operacional do mesmo.

Por isso, quando postei a minha dúvida precisa achar uma solução rápida para solucionar um problema de forma paleativa através do banco alterando o objeto com problema, que se tratava de uma função de uma package.

No entanto, foi atendido a solicitação do usuário que era tratar o separador de decimais. Mas pelo problema do campo ser aberto à digitação foi alertado e ressaltado que poderá voltar a dar problema caso seja recebido um valor não tratado.

De qualquer maneira, mais uma vez agradeço.

Att.,
Responder
  • Informação