- This topic has 7 replies, 3 voices, and was last updated 1 year, 11 months ago by José Laurindo Chiappa.
-
AuthorPosts
-
15 de dezembro de 2022 at 12:01 pm #160631airoospParticipant
Bom dia pessoal,
Beleza?
O cenário é o seguinte:
Desenvolvi uma procedure que faz a validação dos dados importados de um arquivo txt. Faço a carga usando DBMS_CLOUD.COPY_DATA, até ai tudo funciona.
No campo convenio a informação que vem é “OUTROS CONVÊNIOS” e para facilitar melhorando o processo de comparação, utilizei uma função chamada TIRA_ACENTOS, dessa forma os acentos ignorados.
v_sem_acento varchar2(100);
v_sem_acento:=fc_tira_acentos(convenio); passando o campo convenio
e a consulta dentro da procedure:
.
.
.
begin
select count(*) into v_registro
from tb_convenio
where descricao = v_sem_acento;exception
when no_data_found then v_registro:=0;
when others then
begin
v_erro:=sqlcode;
v_descerro:=sqlermm;
end;
end;
.
.
.aqui retorna v_registro = 1
O processo acima esta em uma procedure, e funciona. O detalhe é que há outros processos envolvidos no mesmo assunto, então criei uma package para agrupar estes objetos e manter uma organização.
Dentro da package tem:
– procedure que faz a leitura dos dados, joga para uma tabela auxiliar
– procedure de validação que contém o mesmo código acima
– a função fc_tira_acentosSó que ao executar a procedure/consulta dentro da package, o registro encontrado anteriormente não é mais localizado, retornando v_registro=0.
A minha pergunta é, uma procedure pode ter um comportamento de um jeito fora da package, e outro comportamento quando esta dentro da package?
Executando o debug dentro da package, vi a função fc_tira_acentos não remove a acentuação.
Banco utilizado, 19c.
Se alguém tiver alguma dica, sugestão, agradeço.
Obrigado.
Airton
15 de dezembro de 2022 at 11:49 pm #160680MottaParticipantAirton ,
A function foi duplicada ou movida ?
A coisas rodam no mesmo owner ?
A function faria a mesma coisa estando “empacotada” ou não , algo além da criação da package ocorreu ?
O que a function faz ? Pode publicá-la ?TI não é ciência exata , bruxarias acontecem. 🙂
16 de dezembro de 2022 at 7:20 am #160682José Laurindo ChiappaModeratorBlz, Airton ? Então, a PRIMEIRÍSSIMA COISA que eu penso quando alguém reporta comportamento diferente do mesmo código dentro e fora de um stored PL/SQL (seja package, procedure, function ou trigger) é o FATO (já muito falado mas por incrível que pareça) POUCO conhecido de que GRANTs dados para ROLEs são por default AUTOMATICAMENTE DESLIGADOS dentro de stored PL/SQL – tem um zilhão de artigos em muitos sites explicando e demonstrando isso, https://asktom.oracle.com/pls/apex/asktom.search?tag=procedures-roles-and-grants , https://asktom.oracle.com/pls/apex/asktom.search?tag=invoker-rights-and-dbms-job são só ALGUNS ….. O que eu SUPONHO estar acontecendo é que OU a própria função OU alguma função/procedure/package component que ela chama USA esse default, portanto falha, E (devido a EXCEPTIONs que ‘engolem’ o erro, Sem Aviso) vc nem vê isso…
SE FOR ISSO mesmo o seu problema, a solução é simples : OU vc dá os GRANTs diretos ao invés de dar para ROLEs, OU vc ativa a ROLE manualmente no seu código, OU (o melhor) vc DEIXA de especificar o comportamento default, usando o AUTHID apropriado…Abraços,
Chiappa
16 de dezembro de 2022 at 1:04 pm #160703José Laurindo ChiappaModeratorAh, outro ponto a verificar (bem óbvio, mas já que vc fala de v_registro, que DEVE ser variável, pode acontecer) é que as variáveis definidas dentro de uma PROCEDURE ou FUNCTION que está dentro de uma package são AUTOMATICAMENTE definidas como LOCAIS, ie, de escopo LIMITADO apenas ao componente onde foram declaradas, NECESSARIAMENTE ao terminar a execução da procedure ou function aonde a variável foi declarada é kaput, a variável SOME COMPLETAMENTE…. A suposição então é que vc declarou essa v_registro numa procedure ou function A, aí AUTOMATICAMENTE quando A terminou de executar, v_registro é ZERADA/ELIMINADA, aí por ISSO a fc_tira_acentos ** não ** encontra valor pra ela…..
SE FOR ISSO a solução é inacreditavelmente simples : ao invés de declarar a variável v_registro dentro de um sub-componente qquer da package, DECLARE ELA no “CABEÇALHO”, no SPEC da package, que assim ela se torna uma variável GLOBAL e NECESSARIAMENTE o valor dela VAI ser mantido enquanto a sessão que está executando os componentes da package não se encerrar….[]s
Chiappa
IMPORTANTE : esse ponto que eu citei de “… o valor dela (variável global definida no package spec) VAI ser mantido enquanto a sessão que está executando os componentes da package não se encerrar…” é Especialmente Importante se vc está usando algum POOL DE CONEXÂO : via de regra, nesse tipo de ambiente, CADA chamada ao banco VAI ser atendida por uma sessão diferente retirada do pool… Tipo, se a sua app que TRABALHA com pool de conexões faz :
select ….
package.procedureA;
UPDATE nãoseioque…
package.fc_tira_acentos…;==> depende COMPLETAMENTE de QUAL pool vc usa e de como, mas via de regra CADA UM desses 4 statements acima foi/pode ser atendido por uma sessão DIFERENTE vinda do pool – aí não adianta variável global, não adianta global Temporary Tables, não adianta array, pois esses TODOS são estruturas a nível de sessão… Veja lá se isso que eu falei TEM A VER no SEU ambiente….
E isso que eu falei do POOL DE CONEXÃO é um conceito bem básico e conhecido pra quem programa / desenvolve com tools web, mas (além da doc Oracle) se vc quiser mais refs https://asktom.oracle.com/pls/apex/asktom.search%3Ftag%3Dconnection-pooling explica o conceito em linhas gerais e https://community.oracle.com/tech/developers/discussion/4027057/package-level-global-variable-is-accessible-across-multiple-sessions e https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:871067287878indicam algumas alterativas, como tabelas reais, CONTEXTs, e armazenamento desses dados na própria app, por exemplo na forma de cookies….
16 de dezembro de 2022 at 4:52 pm #160734airoospParticipantBoa tarde pessoal,
Beleza?
Então, descobri o que esta causando o problema, esse processo de remover a acentuação faz parte de uma procedure que faz a carga de arquivo txt usando o código abaixo:
begin
v_url := ‘https://objectstorage.’||v_region||’.oraclecloud.com/n/’||v_namespace||’/b/’||v_bucket||’/o’;DBMS_CLOUD.COPY_DATA( table_name => v_nome_tabela, credential_name => v_credential, file_uri_list => v_url||'/'||v_arquivo, format => json_object('type' VALUE 'csv', 'rejectlimit' value 999999999) ); dbms_output.put_line(' finished successfully'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('ERROR2:' || SQLCODE || ' ' || SQLERRM); RAISE;
end;
Fiz vários testes, criando uma nova package e incluindo as procedures uma por vez.
Quando inclui o código acima DBMS_CLOUD.COPY_DATA, e depois quando o debug passou no processo “remove_acentos”, o mesmo executou mas não removeu a acentuação.Esse é o código da função:
function fc_tira_acentos
(
p_palavra in varchar2
)
return varchar2
Isnom_transformado VarChar2 (100);
Begin
nom_transformado := UPPER (TRIM (p_palavra)); nom_transformado := replace(nom_transformado,'Á','A'); nom_transformado := replace(nom_transformado,'À','A'); nom_transformado := replace(nom_transformado,'Ã','A'); nom_transformado := replace(nom_transformado,'Â','A'); nom_transformado := replace(nom_transformado,'Ä','A'); nom_transformado := replace(nom_transformado,'É','E'); nom_transformado := replace(nom_transformado,'Ê','E'); nom_transformado := replace(nom_transformado,'È','E'); nom_transformado := replace(nom_transformado,'Ë','E'); nom_transformado := replace(nom_transformado,'Í','I'); nom_transformado := replace(nom_transformado,'Ì','I'); nom_transformado := replace(nom_transformado,'Î','I'); nom_transformado := replace(nom_transformado,'Ï','I'); nom_transformado := replace(nom_transformado,'Ó','O'); nom_transformado := replace(nom_transformado,'Ò','O'); nom_transformado := replace(nom_transformado,'Õ','O'); nom_transformado := replace(nom_transformado,'Ô','O'); nom_transformado := replace(nom_transformado,'Ö','O'); nom_transformado := replace(nom_transformado,'Ú','U'); nom_transformado := replace(nom_transformado,'Ù','U'); nom_transformado := replace(nom_transformado,'Û','U'); nom_transformado := replace(nom_transformado,'Ü','U'); nom_transformado := replace(nom_transformado,'Ç','C'); nom_transformado := replace(nom_transformado,'.',' '); nom_transformado := replace(nom_transformado,'_',' '); nom_transformado := replace(nom_transformado,'-',' '); Return nom_transformado;
end fc_tira_acentos;
O que a DBMS_CLOUD.COPY_DATA, pode influenciar na função acima?
Obrigado
Airton
16 de dezembro de 2022 at 5:14 pm #160735airoospParticipantComplementando a mensagem acima:
Variáveis utilizadas na function que executa a DBMS_CLOUD.COPY_DATA.
resp DBMS_CLOUD_TYPES.resp;
v_nome_tabela varchar2(30);
v_credential varchar2(60);
v_tabela varchar2(2000);
v_url varchar2(3000);
v_tipo_arquivo varchar2(20);
v_contador number;
v_existe_tabela number;O desenvolvimento estou fazendo no PLSQL Developer, aplicação interna no próprio banco, a ser disparada via dbms_scheduler.
17 de dezembro de 2022 at 2:51 pm #160815José Laurindo ChiappaModeratorBlz ? Então, nunca usei essa package DBMS_CLOUD, então não sei pra que se usa, como se usa, e não faço idéia se ela se encaixa em qualquer um dos pontos que apontei , E também não tenho no momento acesso a um database Cloud para testar – assim, fica esse ponto para vc Verificar aí no local….
O que eu Recomendaria é que, SE o debugger dessa ferramenta PL/SQL Developer permitir ( o do Oracle SQl Developer eu TENHO CERTEZA que permite, mas essa aí eu não uso, não faço idéia) é PRIMEIRO colocar um BREAKPOINT LOGO depois de vc ter chamada a função e ver se ela gravou os dados no local/na maneira que deveria, e depois executar a função FC_TIRA_ACENTo ** passo-a-passo, LINHA A LINHA, e em cada linha vc pede pra mostrar o Conteúdo dessa variável nom_transformado, pra ver se ela está fazendo o que deveria….
Outra coisa : na rotina que vai chamando cada componente da package necessário, tire COMPLETAMENTE *** qualquer *** tipo de tratamento de erro : se ela for em PL/SQL, tire TODOS os exceptions…. Isso é pra ter CERTEZA que vc não tá caindo nalgum erro que a rotina “engole”/esconde , via tratamento de erros…Abraços,
Chiappa
OBS : repito, NUNCA fiz DEBUG de nada nessa ferramenta PL/SQL DEVELOPER, assim IGNORO se ela tem as mesmas exigências do debugger do Oracle SQL DEVELOPER, que eu uso sempre : veja lá nas docs da tool e sites de usuários dela se ele, por exemplo, EXIGE que os objetos TODOS a debugartenham sido compilados em DEBUG MODE, veja lá o procedimento pra Exibir conteúdo de variável, pra execução passo a passo… Não faço idéia…
17 de dezembro de 2022 at 3:02 pm #160816José Laurindo ChiappaModeratorAh, outro ponto Possível de falha : como eu disse, não faço idéia se essa DBMS_CLOUD é assim, mas sei que essas coisa de cloud e de internet muitas vezes assumem que tudo está codificado em caracteres UNICODE : de repente, PODE SER que esse caracter Ê que vc procura na função via REPLACE na verdade não está codificado EXATAMENTE assim, por isso falha…
Pra comprovar ou refutar isso, sugiro que vc coloque na função uma validação se o caracter existe ou não, tipo :….
function fc_tira_acentos(p_palavra in varchar2 ) return varchar2
Is
nom_transformado VarChar2 (100);
V_pos number := 0;
Begin
nom_transformado := UPPER (TRIM (p_palavra));
v_pos := instr(nom_transformado, ‘Ê’);
dbms_output.put_line(‘caracter existe na pos=’ || v_pos);
…. segue o resto… -
AuthorPosts
- You must be logged in to reply to this topic.