Stored Procedure no MySQL com erro
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***
Respostas
Marisiana Battistella
25/04/2015
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.
Marisiana Battistella
25/04/2015
Marcos P
25/04/2015
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...
Marisiana Battistella
25/04/2015
Percebi que a sintaxe no MySQL é um pouco diferente do Oracle, então não dei muitos palpites... =D
Frederico Brigatte***
25/04/2015
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
Marisiana Battistella
25/04/2015
Frederico Brigatte***
25/04/2015
Marcos P
25/04/2015
Foi você que desenvolveu essas procedures ?
Qual o objetivo e a lógica de cada uma dessas procedures ?
Frederico Brigatte***
25/04/2015
Foi tirado desse artigo. É pra Interbase. Estou tentando modificar para MySql.
Frederico Brigatte***
25/04/2015
Jothaz
25/04/2015
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.
Frederico Brigatte***
25/04/2015
Frederico Brigatte***
25/04/2015
Marisiana Battistella
25/04/2015
William
25/04/2015
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
Frederico Brigatte***
25/04/2015
Marcos P
25/04/2015
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...
William
25/04/2015
Frederico Brigatte***
25/04/2015
Jothaz
25/04/2015
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.
Frederico Brigatte***
25/04/2015
Frederico Brigatte***
25/04/2015
Jothaz
25/04/2015
Você já tentou criar outra tabela com qualquer conteúdo e testar?
Veja se seu servidor MySQL esta funcinando.
Frederico Brigatte***
25/04/2015
Marcos P
25/04/2015
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 !
Frederico Brigatte***
25/04/2015
Marcos P
25/04/2015
T+
Frederico Brigatte***
25/04/2015
Jothaz
25/04/2015
Olha você esta mais que bem assessorado, pois o Marcos tem um vaso conhecimento e boa vontade em compartilhá-lo.
Frederico Brigatte***
25/04/2015
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