Pular para o conteúdo
  • Este tópico contém 2 respostas, 2 vozes e foi atualizado pela última vez 1 ano, 8 meses atrás por Avatar photoJosé Laurindo Chiappa.
Visualizando 3 posts - 1 até 3 (de 3 do total)
  • Autor
    Posts
  • #164768
    Airton
    Participante

      Boa tarde,

      Beleza?

      Criei uma procedure que faz a validação dos registros de uma tabela que recebe os dados de um arquivo texto. Até ai, tudo bem, a carga funciona sem problemas. Essa procedure utiliza procedures e functions que foram criadas e estão em uma package.

      O problema esta ocorrendo quando é executada a function que remove os caracteres acentuados.

      Essa função recebe apenas a palavra, segue abaixo o corpo da função.

      function fc_remove_acentuacao
      (
      p_string    in varchar2
      )
      return varchar2
      is
      v_string           varchar2(100);

      v_lcsql            varchar2(1000);

      v_sem_acentuacao   varchar2(100);

      begin
      v_lcsql:=null;

      if trim(p_string) is not null then
      v_string:=p_string;
      v_lcsql:=’select translate(”’||v_string||”’,”ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü”,”ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu”) from dual’;

      execute immediate v_lcsql into v_sem_acentuacao;

      else
      v_sem_acentuacao:=null;

      end if;

      return v_sem_acentuacao;

      end fc_remove_acentuacao;

      Capturando as linhas do v_lcsql, temos:

      select translate(‘operadora’,’ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü’,’ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu’) from dual

      Retorna:  operadora

      select translate(‘ambulatorial’,’ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü’,’ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu’) from dual

      Retorna:  ambulatorial

      SÓ QUE QUANDO A FUNÇÃO RECEBE AS PALAVRAS ‘convênio próprio’, o translate muda o 2º parâmetro ao invés de manter como faz nas linhas acima.

      ‘ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü’ para ‘ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü’

      A linha capturada ficou assim:

      select translate(‘convênio próprio’,’ÁÇÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕËÜáçéíóúàèìòùâêîôûãõëü’,’ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu’) from dual

      retorna: convênio próprio  ( pois ele não entende o que precisa ser mudado )

      Muito estranho esse comportamento, se executo um teste na função de forma direta na package, ela funciona corretamente.

      Alguém já viu isso acontecer?

      Obrigado.

      Airton

      #164779
      Avatar photoJosé Laurindo Chiappa
      Moderador

        Blz ? Então, PRIMEIRO vou dizer EXATAMENTE O MESMO que já havia dito em https://www.profissionaloracle.com.br/forums/topic/remover-acentuacao-nao-funciona-dentro-de-uma-package/ : em ESPECIAL se vc está mexendo com funcionalidades de Internet e/ou Java, é BEM COMUM que seja assumido characterset UNICODE em strings vindas e/ou enviadas para esse origem , E/OU se a sua rotina PL/SQL é chamada a partir de Java e/ou APEX e/ou algum tipo de WEBSERVER : SE o seu database Não É compatível com UNICODE, taí feito o salseiro…. SE FOR ISSO, a solução provavelmente é vc converter a string para o characterset do seu banco, mas antes de assumir qualquer coisa, DEBUGUE ISSO : experimente chamar a função diretamente do sqlplus , por exemplo, passando pra ela uma string SUA que vc ABSOLUTAMENTE SABE que NÂO CONTÉM UNICODE, faça o ** DEBUG ** com INSTR QUE NEM EU INDIQUEI lá na thread original acima citada….. Outro teste PORRETA pra vc ver se tem UNICODE no meio é vc usar as funções de UNICODE como UNISTR, e a tira-prosa, que é a DUMP, com ela vc vai ver EXATAMENTE os códigos de caracteres que a sua rotina está recebendo como argumento…..
        EM SEGUNDO LUGAR, eu vi que no código-fonte da sua procedure vc colocou pro translate NÃO os códigos dos caracteres desejados, mas sim inseriu os caractres diretamente : CONFIRME se eventualmente a tool que vc usou pra criar a procedure/rotina PL/SQL por má-config não enfiou strings UNICODE ou em um characterset DIFERENTE do characterset do database, aí na hora do database salvar teu PL/SQL nas tabelas internas lidas pela DBA_SOURCE OBVIAMENTE as strings VÃO ser convertidas pro characterset do database, com Possível perda e/ou conversões falhas – plz VERIFIQUE na coluna TEXT da DBA_SOURCE dessa sua rotina COMO é que estão os caracteres do TRANSLATE….

        []s

        Chiappa

        #164780
        Avatar photoJosé Laurindo Chiappa
        Moderador

          Demonstração que a função retorna OK **** SIM ****, mesmo passando essa string ‘convênio próprio’ que vc indica, SE ela tiver sido criada com uma tool COMPATÍVEL com o characterset do banco E a string esteja codificada num characterset igualmente Compatível – só vou CORRIGIR o ** Óbvio ** bug que tem nessa versão que vc mostrou, que é : um SELECT (seja via EXECUTE IMEMDIATE, seja direto) *** TEM *** que ser INTO algumacoisa, e nesse código vc não está colocando o resultado do SELECT em lugar algum….. E óbvio também, necessidade NENHUMA de usar SQL DINÂMICO via EXECUTE IMMEDIATE (isso é a MARCA de um código amadorístico, usar recursos de forma Equivocada/desnecessária), E ALÉM DISSO é ABSURDO “forçar” uma chamada e um tráfego de rede até o database engine com essa ref à DUAL só pra usar a TRANSLATE, então NÃO VOU ME DAR AO TRABALHO :


          => conecto ao banco via sqlplus, que SEI que é uma tool que ejá está corretamente configurada aqui no meu banco :

          C:\Users\jlchi>sqlplus scott/tiger@xepdb1

          SQL*Plus: Release 21.0.0.0.0 - Production on Ter Mar 14 11:01:57 2023
          Version 21.3.0.0.0

          Copyright (c) 1982, 2021, Oracle. All rights reserved.

          Horário do último log-in bem-sucedido: Qui Mar 09 2023 10:59:57 -03:00

          Conectado a:
          Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
          Version 21.3.0.0.0

          => só mostrando que os caracteres especiais (acentuados) que eu DIGITAREI NO TECLADO diretamente SÂO exibidos corretamente :

          SCOTT@xepdb1::CONTAINER=XEPDB1> select 'ÁÉÍÓÚáéíóú' from dual;

          'ÁÉÍÓÚÁÉÍÓÚ'

          ÁÉÍÓÚáéíóú

          1 linha selecionada.

          => criação da função em si :

          SCOTT@xepdb1::CONTAINER=XEPDB1> create or replace function fc_remove_acentuacao (p_string in varchar2) return varchar2
          2 is
          3 v_sem_acentuacao varchar2(100);
          4 begin
          5 if trim(p_string) is not null then
          6 v_sem_acentuacao := translate(p_string, 'ÁÇÉÍÓÚAEIOUÂEÎÔUAOËÜáçéíóúaeiouâeîôuaoëü',
          7 'ACEIOUAEIOUAEIOUAOEUaceiouaeiouaeiouaoeu'
          8 ) ;
          9 else
          10 v_sem_acentuacao:=null;
          11 end if;
          12 --
          13 return v_sem_acentuacao;
          14 end fc_remove_acentuacao;
          15 /

          Funçăo criada.

          SCOTT@xepdb1::CONTAINER=XEPDB1>

          ==> vou executar a função, no caso via SELECT diretamente na linguagem SQL, mas ela PODERI ser executado sem problemas diretamente a partir do sqlplus, ou a partir de um outro PL/SQl, ou a partir duma app externa, sem probs :

          select FC_REMOVE_ACENTUACAO('convênio próprio') from dual;

          FC_REMOVE_ACENTUACAO('CONVENIOPRÓPRIO')

          convenio proprio

          1 linha selecionada.

          SCOTT@xepdb1::CONTAINER=XEPDB1>

          ===> c.q.d. , ok ?? TÁ PROVADO que a sua Suposição de que "não funciona para a string 'convênio próprio' tá COMPLETAMENTE FURADA, absolutamente NÂO É ISSO : plz FAÇA os debugs e verificações indicados, que vc CHEGA NA CAUSA REAL.....

          []s

          Chiappa

        Visualizando 3 posts - 1 até 3 (de 3 do total)
        • Você deve fazer login para responder a este tópico.
        plugins premium WordPress