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

      Boa noite!

      Quando é realizado case com char o mesmo não é executado, solicitando que declare o identificador ‘I’. Como solucionar o problema?

       

      O que deveria fazer: digitar a letra I e aparecer a mensagem;

      DECLARE
      vMensagem Varchar2(200);
      vOpcao char(1) := &op;
      BEGIN
      CASE vOpcao
      WHEN ‘I’ THEN
      vMensagem := ‘Inclusão’;
      ELSE
      vMensangem := ‘opção inválida’;
      END CASE;
      DBMS_OUTPUT.PUT_LINE(vMensagem);
      END;

      #145965
      Avatar photoJosé Laurindo Chiappa
      Moderador

        Blz ? Então, na verdade vc está ** ERRANDO COMPLETAMENTE ** a forma de utilização do CASE, nunca que vai funcionar… Pra começo de conversa, CASE só PODE ser usado DENTRO DE COMANDOS SQL, o manual mesmo nos diz claramente (ênfase com *s é minha) :

        “CASE Expressions

        CASE expressions let you use IF … THEN … ELSE logic *** in SQL statements *** …..

        okdoc ?? Usar ele FORA de um comando SQL qquer, SELECT que seja, simplesmente Não Funciona!!! Já sobre a sintaxe, se vc consultar o mesmo manual Oracle Database SQL Reference no capítulo de CASE Expressions ele já diz que vc OU PODE fazer uma comparação simples (só igualdade) citando só o nome da fonte de dado logo após o CASE e os valores de comparação no WHEN, OU PODE ter uma comparação complexa (ie, com IN, NOT, <>, etc) SE vc citar a comparação na íntegra (incluindo a fonte de dados!!) no WHEN – pelo que vi vc queria MISTURAR os dois conceitos, nunca que vai funcionar…. E tem também esses caracteres ; que vc colocou junto com as comparações do CASE, também NÃO FAZEM O MENOR SENTIDO…. E não esquecendo a cerejinha do bolo também, vc não usou aspas na valoração para a variável vOpcao, que é uma string  : em ALGUNS CASOS o Oracle até consegue fazer as conversões implícitas necessárias MAS NEM SEMPRE – eu recomendo FORTEMENTE que vc NUNCA, em CASO ALGUM, confie nessas conversões e especificações de dados Implícitas, cedo ou tarde isso VAI virar e te morder o calcanhar….

        E FINALMENTE, ao corrigir o seu exemplo e tentar executar, obtive :

        SCOTT@xepdb1::CONTAINER=XEPDB1> ed
        Gravou file afiedt.buf
        
        1 DECLARE
        2 vMensagem Varchar2(200);
        3 vOpcao char(1) := &op;
        4 BEGIN
        5 SELECT CASE vOPcao WHEN 'I' THEN 'Inclusão'
        6 ELSE 'Opção Inválida!!'
        7 END
        8 INTO vMensagem
        9 FROM dual;
        10 DBMS_OUTPUT.PUT_LINE(vMensagem);
        11* END;
        SCOTT@xepdb1::CONTAINER=XEPDB1> /
        Informe o valor para op: I
        vOpcao char(1) := I;
        *
        ERRO na linha 3:
        ORA-06550: linha 3, coluna 22:
        PLS-00201: o identificador 'I' deve ser declarado
        ORA-06550: linha 3, coluna 11:
        PL/SQL: Item ignored
        ORA-06550: linha 5, coluna 16:
        PLS-00320: a declaração do tipo desta expressão está incompleta ou incorreta
        ORA-06550: linha 5, coluna 16:
        PL/SQL: ORA-00904: "VOPCAO": identificador inválido
        ORA-06550: linha 5, coluna 4:
        PL/SQL: SQL Statement ignored
        
        SCOTT@xepdb1::CONTAINER=XEPDB1>
        

        ==> Pra variar vc Não Mostra mas IMAGINO QUE DEVE SER ESSA a msg referente a variável não declarada que vc diz que recebeu… OU SEJA, a falta de aspinha tá fazendo o compilador de PL/SQL não conseguir delimitar onde acabou a valoração da vOpcao….
        Antes de corrigir isso, uma colocação : O PROBLEMA AQUI é CONCEITUAL imho, pois o PL/SQL, como liguagem AUTO-CONTIDA QUE É, absolutamente Não Tem Comandos para INPUT de valores….. Esse conceito de variáveis de substituição foi criado NO SQLPLUS para ser usado NA LINGUAGEM SQL… E OUTRA COISA : uma variável de substituição é normalmente usada para SUBSTITUIR parte de um comando SQL, usar isso dentro de um bloco PL/SQL não é garantido…
        Ou seja : sim, em algumas circunstâncias vc até consegue usar esse recurso EXTERNO ao PL/SQL num bloco PL/SQL mas é o mesmo caso de conversão implícita : vc está usando algo de uma maneira NÃO PREVISTA, CEDO ou TARDE isso VAI se virar contra vc e VAI te morder no calcanhar….Sorry, mas PL/SQL *** não é a linguagem Adequada *** para vc construir Menus ou rodar programas interativos, que interagem com o usuário : PL/SQL é uma linguagem EXCEPCIONAL para tratar e manipular dados, no back-end, situação para a qual ela conta com INÚMERAS otimizações internas, como caches próprios, compilação automática, conhecimento de TODOS os datatypes da linguagem SQL e do database, opções de array processing/bulk collect, etc, etc, mas simplesmente Não é Adequada para outros tipos de programação, tais como : menus para usuários, acessar qquer hardware da máquina-cliente do usuário que está executando o PL/SQL, desenhar telas para o usuário, etc, etc…

        Okdoc ?? Isso dito, somente PARA EXEMPLO (eu Não recomendo usar isso em ambiente Realista, de Produção!!) segue a correção final do seu “problema” : note TUDO o que eu fiz : eu COLOQUEI aspinhas na especificação de uma variável substituição de string, USEI o CASE ** dentro de um comando SQL **, como ele foi FEITO para ser usado (usei dentro de um SELECT no caso), E já que (ao que entendi) vc quer usar a comparação SIMPLIFICADA, onde vc só indica a fonte dos dados E o valor a ser comparado no WHEN, assim o fiz :

        SCOTT@xepdb1::CONTAINER=XEPDB1> DECLARE
         2 vMensagem Varchar2(200);
         3 vOpcao char(1) := '&op';
         4 BEGIN
         5 SELECT CASE vOPcao WHEN 'I' THEN 'Inclusão'
         6 ELSE 'Opção Inválida!!'
         7 END
         8 INTO vMensagem
         9 FROM dual;
        10 DBMS_OUTPUT.PUT_LINE(vMensagem);
        11 END;
        12 /
        
        Informe o valor para vop: I
        antigo 3: vOpcao char(1) := '&op';
        novo 3: vOpcao char(1) := 'I';
        Inclusão
        
        Procedimento PL/SQL concluído com sucesso.

        ==> aí vou rodar de novo o bloco PL/SQL que está na memória ainda E vou informar um outro valor diferente de I:

        SCOTT@xepdb1::CONTAINER=XEPDB1> /
        Informe o valor para vop: U
        antigo 3: vOpcao char(1) := '&op';
        novo 3: vOpcao char(1) := 'U';
        Opção Inválida!!
        
        Procedimento PL/SQL concluído com sucesso.
        
        SCOTT@xepdb1::CONTAINER=XEPDB1>

        Belezinha ? Conceitos esclarecidos ??

        Abraços,

        Chiappa

        OBS :

        a) só reforçando o Conceito de que quem está fazendo o INPUT NÃO É a linguagem PL/SQL (que não tem essa capacidade) MAS SIM o programa sqlplus, posso usar um Ajuste no sqlplus para que Não Seja Exibida a substituição de valores, assim :

        SCOTT@xepdb1::CONTAINER=XEPDB1> set verify OFF

        => Agora, se eu executar o MESMO bloco PL/SQL que está na memória, duas vezes :

        SCOTT@xepdb1::CONTAINER=XEPDB1> l
         1 DECLARE
         2 vMensagem Varchar2(200);
         3 vOpcao char(1) := '&op';
         4 BEGIN
         5 SELECT CASE vOPcao WHEN 'I' THEN 'Inclusão'
         6 ELSE 'Opção Inválida!!'
         7 END
         8 INTO vMensagem
         9 FROM dual;
        10 DBMS_OUTPUT.PUT_LINE(vMensagem);
        11* END;
        SCOTT@xepdb1::CONTAINER=XEPDB1> /
        Informe o valor para op: I
        Inclusão
        
        Procedimento PL/SQL concluído com sucesso.
        
        SCOTT@xepdb1::CONTAINER=XEPDB1> /
        Informe o valor para op: U
        Opção Inválida!!
        
        Procedimento PL/SQL concluído com sucesso.
        
        SCOTT@xepdb1::CONTAINER=XEPDB1>
        

        Veja que eu não recebi o aviso / mensagem referente à substituição e ao INPUT provocado pelo sql*plus…

        b) só comentando, imagino que vc SAIBA que o PL/SQL é uma linguagem CASE INSENSITIVE para operadores, comandos E variáveis : assim, esse camel-case que vc usa nas variáveis, como vOpcao por exemplo, só server de auxílio VISUAL , pois INTERNAMENTE vai ser destruído, tudo é convertido para maisúsculas pelo compilador PL/SQL – isso fica Cristalinamente CLARO na msg de erro lá da execução sem aspinhas :

        ORA-06550: linha 5, coluna 16:
        PL/SQL: ORA-00904: “VOPCAO”: identificador inválido

        Blz ??

        #145973
        Silva
        Participante

          Boa noite José!, tudo bem?

          Bom, inicialmente agradeço toda a explicação e contextualização do assunto, já que foi fundamental para mim entender o processo.

          Eu não sabia das questões de aspas e como havia rodado um teste com número no lugar de letra, achei que seria basicamente a mesma lógica. Contudo, pude entender como funciona e como usar.

           

          Além disso, agradeço também a resolução do problema.

           

          Abraços,

          Excelente didática, parabéns!.

          At.te. Thiago José.

          #145975
          Avatar photoJosé Laurindo Chiappa
          Moderador

            Blz, fico contente de ter ajudado, espero que não só a questão da exigência de aspas-simples para delimitar string Mas também o Fato do CASE não poder ser usado fora de comando SQL, os pontos-e-virgula que o PL/SQL demanda que vc só ponha no final lógico do comando (que no caso dum CASE é no END que fecha esse case, e Não no WHEN como vc tinha usado) e os outros pontos tenham ficado claros… E como sempre, qquer dúvida é só perguntar, se eu souber responder tamos aí….

            Abraços,

            Chiappa

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