Stored Procedure no MySQL com erro

MySQL

25/04/2015

Feras, tenho esse script e está dando erro. O que pode ser? Estou rodando no MySQL

USE bancovendas
CREATE PROCEDURE PROC_VERIFICA_ACESSO_MENU (
CODUSUARIO INTEGER, CODMENU INTEGER)
RETURNS (CONSULTAR CHAR(1))
AS
DECLARE VARIABLE GU_CONSULTAR CHAR(1);
BEGIN
CONSULTAR = 'N';
FOR SELECT PU_CONSULTAR FROM PERMISSOES_USUARIOS WHERE USU_CODIGO = :CODUSUARIO AND MEN_CODIGO = :CODMENU
UNION
SELECT PG_CONSULTAR FROM PERMISSOES_GRUPOS WHERE GRU_CODIGO IN (SELECT GRU_CODIGO FROM GRUPOS_USUARIOS WHERE USU_CODIGO = :CODUSUARIO) AND MEN_CODIGO = :CODMENU
INTO :GU_CONSULTAR
DO
BEGIN
IF (:GU_CONSULTAR = 'S') THEN
BEGIN
CONSULTAR = 'S';
EXIT;
END
END
END

Erro ao executar:
1 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(CONSULTAR CHAR(1))
AS
DECLARE VARIABLE GU_CONSULTAR CHAR(1)' at line 2 SQL.sql 4 1
Frederico Brigatte***

Frederico Brigatte***

Curtidas 0

Respostas

Marisiana Battistella

Marisiana Battistella

25/04/2015

Já conseguistes encontrar a solução?
O problema está na variável GU_CONSULTAR, quando vc utiliza ela no corpo da procedure, vc inclui dois pontos...
Eu acho que nesse caso é sem os dois pontos.
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

25/04/2015

Esse artigo possui uma explicação detalhada: Stored Procedures no MySQL
GOSTEI 0
Marcos P

Marcos P

25/04/2015

Com esse link da Marisiana, fica fácil compreender a estrutura de uma stored procedure no MySql.

Sobre a query original...

1. Não existe declaração de RETURNS no escopo da procedure ( isso somente serve se você estiver criando uma FUNCTION )
2. DECLARE, deve estar contido ENTRE o begin e o end ( do corpo da procedure )
3. GU_CONSULTAR é variável local. Nesse caso,não é necessário colocar ":" antes de utilizá-la.
4. GU_CONSULTAR vai receber o resultado do UNION de dois selects, ou seja, possivelmente múltiplos registros. Tentar armazenar essas linhas em uma variável declarada como Char(1), não parece muito correto...
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

25/04/2015

Obrigada por contribuir Marcos!
Percebi que a sintaxe no MySQL é um pouco diferente do Oracle, então não dei muitos palpites... =D
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Ainda não consegui resolver o problema. Esse link postado já verifiquei. Consegui fazer algumas modificações, mas parece que está num loop e não sai. Está assim:

Essa é uma

PROCEDURE bancovendas.PROC_VERIFICA_ACESSO_MENU(IN CODUSUARIO INTEGER, IN CODMENU INTEGER, OUT CONSULTAR CHAR(1))
BEGIN 
  DECLARE GU_CONSULTAR CHAR(1); 
  SET CONSULTAR = 'N';
Loop_Label:  LOOP SELECT PU_CONSULTAR FROM PERMISSOES_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO AND
    MEN_CODIGO = CODMENU
  UNION
  SELECT PG_CONSULTAR FROM PERMISSOES_GRUPOS
    WHERE GRU_CODIGO IN (
    SELECT GRU_CODIGO FROM GRUPOS_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO) AND
    MEN_CODIGO = CODMENU
  INTO GU_CONSULTAR;
  /*DO
  BEGIN*/
    IF (GU_CONSULTAR = 'S') THEN
    /*BEGIN*/
     SET CONSULTAR = 'S';
     LEAVE Loop_Label;
    END IF;
  END LOOP Loop_Label;
END


Essa é outra:

PROCEDURE bancovendas.PROC_VERIFICA_DIREITOS_ACESSO(IN CODUSUARIO INTEGER, IN CODMENU INTEGER, OUT NOVO CHAR(1), OUT ALTERAR CHAR(1), OUT APAGAR CHAR(1))
BEGIN
DECLARE ADM CHAR(1);
DECLARE GU_NOVO CHAR(1);
DECLARE GU_ALTERAR CHAR(1);
DECLARE GU_APAGAR CHAR(1);
/*BEGIN*/
  SET NOVO = 'N'; 
  SET ALTERAR = 'N'; 
  SET APAGAR = 'N';
  SELECT USU_ADMIN FROM USUARIOS
    WHERE USU_CODIGO = CODUSUARIO
  INTO ADM;
  IF (ADM = 'S') THEN
    /*BEGIN*/
    SET NOVO = 'S';
    SET ALTERAR = 'S';
    SET APAGAR = 'S';
    /*EXIT;*/
  END IF; /*IF*/
 
Loop_Label:  LOOP SELECT PU_NOVO, PU_ALTERAR, PU_APAGAR
    FROM PERMISSOES_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO AND
    MEN_CODIGO = CODMENU
  UNION
  SELECT PG_NOVO, PG_ALTERAR, PG_APAGAR
    FROM PERMISSOES_GRUPOS
    WHERE GRU_CODIGO IN (SELECT GRU_CODIGO
    FROM GRUPOS_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO) AND
    MEN_CODIGO = CODMENU
  INTO GU_NOVO, GU_ALTERAR, GU_APAGAR;
  /*DO
  BEGIN*/
    IF (GU_NOVO = 'S') THEN
      SET NOVO = 'S';
    END IF;
    IF (GU_ALTERAR = 'S') THEN
      SET ALTERAR = 'S';
    END IF;
    IF (GU_APAGAR = 'S') THEN
      SET APAGAR = 'S';
    END IF;
  END LOOP Loop_Label;
END
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

25/04/2015

Qual é o erro que estão ocorrendo agora?
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Nao da erro. Ele trava.
GOSTEI 0
Marcos P

Marcos P

25/04/2015

Frederico,

Foi você que desenvolveu essas procedures ?

Qual o objetivo e a lógica de cada uma dessas procedures ?
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

https://www.devmedia.com.br/artigo-clube-delphi-76-controle-de-acesso/11344

Foi tirado desse artigo. É pra Interbase. Estou tentando modificar para MySql.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Poderia me dar uma ajuda para solucionar isso?
GOSTEI 0
Jothaz

Jothaz

25/04/2015

Se quer realmente ajuda precisa ser mais claro na elaboração do post.

Tente responder as questões abaixo:

1 - Você postou duas SP, para qual você precisa de ajuda?

2 - Qual a estrutura da sua tabela? Se possível post o conteúdo da sua tabela!

3 - Pelo que entendi é um controle de permissão? É isso?

4 - Você disse que parece estar em loop. O que porque do uso do loop?

5 - Já tentou retirar o loop e testar o que acontece?

6 - Não vi o "return" da SP, o que você pretende retornar?

7 - Você esta fazendo a seguinte operação:
    IF (GU_NOVO = 'S') THEN
      SET NOVO = 'S';


Qual o motivo disso? É muito mais simples retornar um select com "GU_NOVO" (pois ele já contém 'S') e tratar na aplicação.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Ké um controle de permissão. No artigo é para INTERBASE. Como converter essas duas SPs para o mysql?. Do jeito que esta ai, não apresenta erro. Fica travado. Eu postei o link que estou fazendo como referencia. Lá tem tudo, script tabela, stored procedure, mas é para Inter base. Gostaria de saber o que esta errado ai e como seria o correto, não sei como faz isso.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Ké um controle de permissão. No artigo é para INTERBASE. Como converter essas duas SPs para o mysql?. Do jeito que esta ai, não apresenta erro. Fica travado. Eu postei o link que estou fazendo como referencia. Lá tem tudo, script tabela, stored procedure, mas é para Inter base. Gostaria de saber o que esta errado ai e como seria o correto, não sei como faz isso.
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

25/04/2015

Você tem que procurar entender a lógica dela, o que ela faz... Depois disso, você recreia ela de acordo com a sintaxe do MySQL.
GOSTEI 0
William

William

25/04/2015

Só dei uma lida por cima, mas senão dá erro e trava então tem grandes chances de estar ficando preso no loop, você já tentou executar somente essa instrução SQL para ver quantos registros ela retorna ou qual tempo de processamento dela:

SELECT PU_CONSULTAR FROM PERMISSOES_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO AND
    MEN_CODIGO = CODMENU
  UNION
  SELECT PG_CONSULTAR FROM PERMISSOES_GRUPOS
    WHERE GRU_CODIGO IN (
    SELECT GRU_CODIGO FROM GRUPOS_USUARIOS
    WHERE USU_CODIGO = CODUSUARIO) AND
    MEN_CODIGO = CODMENU
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Já, pior que já tentei isso. Trava também.
GOSTEI 0
Marcos P

Marcos P

25/04/2015

O select acima não está processando ?

Rode-os separadamente... os dois travam ?

Se forem os dois, você tem acesso a essas tabelas ? Qual a estrutura de índices envolvida ? Você consegue acompanhar o processamento dessas queries no servidor ?

Se for apenas um, informe qual...
GOSTEI 0
William

William

25/04/2015

Então meu amigo, o problema não é na procedure e sim na sua query, agora tem que analisar ela e identificar o ponto de gargalo.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Então William, o problema está no artigo, pq não mudei nada na query e sim na stored procedure para o MySql
GOSTEI 0
Jothaz

Jothaz

25/04/2015

Então William, o problema está no artigo, pq não mudei nada na query e sim na stored procedure para o MySql


O artigo do qual você postou o link é um artigo exclusivo para assinantes, então quem não é assinante, como eu não tenho como ver o conteúdo e contribuir.

A ideia seria como foi sugerida pelo William ir executando por partes, faça um select simples sem UNION e verifique se esta travando.

Ou tente rodar algo assim:

SELECT PU_CONSULTAR FROM PERMISSOES_USUARIOS


e vá acrescentando complexidade, depois que a query rodar parta para a SP.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Jothaz, vc tem face ou skype?
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Então, Jothaz, não estou conseguindo, você me ajuda? Ai posto depois aqui para quem precisar também.
GOSTEI 0
Jothaz

Jothaz

25/04/2015

Tenho, mas como estou no serviço não tenho como acessar, pois é bloqueado.

Você já tentou criar outra tabela com qualquer conteúdo e testar?

Veja se seu servidor MySQL esta funcinando.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Me passa que adiciono vc, Assim que puder falar vc me chama la.
GOSTEI 0
Marcos P

Marcos P

25/04/2015

Frederico,

Existem diversas diferenças entre a sintaxe do MySql e do Interbase.

Faça o seguinte... crie as tabelas no MySql e popule-as com alguns dados.

Depois disso, separe nas procedures todas as queries e teste-as ( uma-a-uma ).

Depois de homologar as queries, sobrará "apenas" a estrutura das procedures ( declarações, condicionais, loops e demais controles... ), as quais posso tentar te ajudar.

Coloque teu skype aqui que eu te chamo mais tarde...

Enquanto isso, teste as queries !
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Ok, Marcos P, me ajude, não sei mais o que fazer. Meu skype é: frederico.brigatte@itelefonica.com.br Qual é o seu que já adiciono aqui.
GOSTEI 0
Marcos P

Marcos P

25/04/2015

Te chamo na sequencia... pois tenho algumas coisas pra resolver aqui !

T+
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Ok, te aguardo.
GOSTEI 0
Jothaz

Jothaz

25/04/2015

Ok, te aguardo.


Olha você esta mais que bem assessorado, pois o Marcos tem um vaso conhecimento e boa vontade em compartilhá-lo.
GOSTEI 0
Frederico Brigatte***

Frederico Brigatte***

25/04/2015

Marcos P, desde já agradeço a ajuda de ontem. Tentei fazer a segunda mas sem sucesso. Fiquei com algumas dúvidas que vou peguntar por aqui por enquanto. O que consegui fazer, mas não sei ao certo se estou no caminho.

Minhas dúvidas são:

1 - Alguns comandos e variáveis deixaram de ter, isso deve ser por causa do banco de dados que não aceita. Cada um tem sua sintaxe. É isso mesmo?
2 - Não sei se os IF's estão no lugar certo, essa é uma dúvida.
3 - Percebi que tem 3 SELECT na segunda stored procedure. O IF tem que usar pra cada uma, seguindo a sintaxe IF EXISTS (...) ELSIF EXISTS(...)
4 - Os comandos INTO e UNION eu entendi o significado mas não consegui converter para o MySQL

Perceba na que tentei fazer, parei no segundo SELECT, bem no comando UNION eu parei, rs, mas não sei ao certo se o que fiz está ok.

Obs: Jothaz, obrigado pela ajuda.

Minha 2ª STORED PROCEDURE 

DROP PROCEDURE IF EXISTS `bancovendas`.`PROC_VERIFICA_DIREITOS_ACESSO`;

DELIMITER $$
CREATE PROCEDURE `bancovendas`.`PROC_VERIFICA_DIREITOS_ACESSO` (IN CODUSUARIO INTEGER, IN CODMENU INTEGER, OUT NOVO CHAR(1), OUT ALTERAR CHAR(1), OUT APAGAR CHAR(1))

SET NOVO = 'N';
SET ALTERAR = 'N';
SET APAGAR = 'N';

IF EXISTS (SELECT USU_ADMIN FROM USUARIOS 
           WHERE USU_CODIGO = CODUSUARIO)
THEN 
 SET NOVO = 'S';
 SET ALTERAR = 'S';
 SET APAGAR = 'S';

ELSEIF EXISTS (SELECT PU_NOVO, PU_ALTERAR, PU_APAGAR
               FROM PERMISSOES_USUARIOS
               WHERE USU_CODIGO = CODUSUARIO AND
               MEN_CODIGO = CODMENU)




Essa é a original:

CREATE PROCEDURE PROC_VERIFICA_DIREITOS_ACESSO (
  CODUSUARIO INTEGER, CODMENU INTEGER)
RETURNS (NOVO CHAR(1), ALTERAR CHAR(1),
  APAGAR CHAR(1))
AS
DECLARE VARIABLE ADM BOOLEAN;
DECLARE VARIABLE GU_NOVO BOOLEAN;
DECLARE VARIABLE GU_ALTERAR BOOLEAN;
DECLARE VARIABLE GU_APAGAR BOOLEAN;
BEGIN
  NOVO = 'N'; 
  ALTERAR = 'N';
  APAGAR = 'N';
  SELECT USU_ADMIN FROM USUARIOS
    WHERE USU_CODIGO = :CODUSUARIO
  INTO :ADM;
  IF (:ADM = TRUE) THEN
  BEGIN
    NOVO = 'S';
    ALTERAR = 'S';
    APAGAR = 'S';
    EXIT;
  END
 
  FOR SELECT PU_NOVO, PU_ALTERAR, PU_APAGAR
    FROM PERMISSOES_USUARIOS
    WHERE USU_CODIGO = :CODUSUARIO AND
    MEN_CODIGO = :CODMENU
  UNION
  SELECT PG_NOVO, PG_ALTERAR, PG_APAGAR
    FROM PERMISSOES_GRUPOS
    WHERE GRU_CODIGO IN (SELECT GRU_CODIGO
    FROM GRUPOS_USUARIOS
    WHERE USU_CODIGO = :CODUSUARIO) AND
    MEN_CODIGO = :CODMENU
  INTO :GU_NOVO, :GU_ALTERAR, :GU_APAGAR
  DO
  BEGIN
    IF (:GU_NOVO = TRUE) THEN
      NOVO = 'S';
    IF (:GU_ALTERAR = TRUE) THEN
      ALTERAR = 'S';
    IF (:GU_APAGAR = TRUE) THEN
      APAGAR = 'S';
  END
END
GOSTEI 0
POSTAR