- Este tópico contém 2 respostas, 2 vozes e foi atualizado pela última vez 1 ano, 8 meses atrás por José Laurindo Chiappa.
-
AutorPosts
-
13 de março de 2023 às 8:25 pm #164768AirtonParticipante
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
14 de março de 2023 às 10:48 am #164779José Laurindo ChiappaModeradorBlz ? 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
14 de março de 2023 às 11:11 am #164780José Laurindo ChiappaModeradorDemonstraçã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.0Copyright (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
-
AutorPosts
- Você deve fazer login para responder a este tópico.