Pular para o conteúdo

Tagged: ,

  • This topic has 7 replies, 3 voices, and was last updated 1 year, 11 months ago by Avatar photoJosé Laurindo Chiappa.
Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #160631
    Avatar de airoospairoosp
    Participant

      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_acentos

      Só 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

      #160680
      Avatar de MottaMotta
      Participant

        Airton ,
        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. 🙂

        #160682
        Avatar photoJosé Laurindo Chiappa
        Moderator

          Blz, 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

          #160703
          Avatar photoJosé Laurindo Chiappa
          Moderator

            Ah, 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….

            #160734
            Avatar de airoospairoosp
            Participant

              Boa 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
              Is

              nom_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

              #160735
              Avatar de airoospairoosp
              Participant

                Complementando 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.

                #160815
                Avatar photoJosé Laurindo Chiappa
                Moderator

                  Blz ? 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…

                  #160816
                  Avatar photoJosé Laurindo Chiappa
                  Moderator

                    Ah, 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…

                  Viewing 8 posts - 1 through 8 (of 8 total)
                  • You must be logged in to reply to this topic.
                  plugins premium WordPress