- Este tópico contém 3 respostas, 2 vozes e foi atualizado pela última vez 4 anos, 6 meses atrás por José Laurindo Chiappa.
-
AutorPosts
-
4 de maio de 2020 às 9:19 pm #145963SilvaParticipante
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;5 de maio de 2020 às 11:32 am #145965José Laurindo ChiappaModeradorBlz ? 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álidoBlz ??
5 de maio de 2020 às 7:23 pm #145973SilvaParticipanteBoa 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é.
5 de maio de 2020 às 9:48 pm #145975José Laurindo ChiappaModeradorBlz, 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
-
AutorPosts
- Você deve fazer login para responder a este tópico.