SQL - Triggers [MySQL 5.1]

5 respostas
L

Olá a todos,

Estou desenvolvendo uma estrutura de dados que necessita de algumas restrições que não podem ser explicitadas com elegância através de contraints check. Portanto, decidi utilizar triggers para resolver o problema, porém, no SGBD que estou utilizando a solução se tornou mais deselegante ainda (rs).

Enfim, necessito checar determinada condição com os novos dados a serem inseridos no banco e caso determinada condição não seja satisfeita preciso interromper a inserção. No entanto, desconheço algum comando do MySQL 5.1 que efetue tal tarefa, ou seja, interromper uma inserção.

Contudo, resolvi o problema com a seguinte trigger (o que não me deixo muito feliz):

DELIMITER $$

USE `REUNIOES`$$

CREATE TRIGGER checkTypeValue 
BEFORE INSERT ON Reuniao
FOR EACH ROW
BEGIN
	IF ( NEW.idConselho <> 2 AND NEW.tipo NOT IN ( 'O', 'E' ) ) THEN
		SET NEW.tipo := NULL;
	END IF;		
END $$

DELIMITER ;

Ou seja, para interromper a inserção atribuo a flag NULL para um atributo obrigatório (POG).

Caso alguém conheça alguma solução mais elegante para esse problema, por favor, me informem.

5 Respostas

E

Olá,

Você não possui objetos que realizam as funções de persistência (DAOs)?

Se sim, você faria essa verificação no método “adicionar” da entidade que deseja gravar.

Se não, a própria documentação do MySQL recomenda o uso de Triggers em casos onde você precisa trabalhar com várias linguagens acessando o mesmo banco (17.2 no manual), se esse não for o seu caso acho que seria interessante usar DAOs

[ ]'s

D

Ev3rton, o ideal nem seria fazer esta validação na DAO, mas, numa camada de negócios. Assim se trava as chamadas desnecessárias à recursos mais específicos.
Caso contrário e, sendo o mesmo o desenvolvedor do banco, poderia resolver com uma simples stored procedure, validando as entradas (já que está deselegante) e, claro, caso fosse preciso ou já existisse uma trigger. Assim sendo, a trigger se torna a solução mais adequada. Não sei por que este medo de utilizar esta ferramenta…

L

Olá Pessoa,

Primeiramente muito obrigado pela atenção Ev3rton e drsmachado.

Sobre a resposta do Ev3rton: eu utilizo sim DAOs e faço as validações como descrito pelo drsmachado (na camada de negócios) [estou utilizando Hibernate e Spring para desenvolver o software], porém, realmente a validação que desejo é de extrema importância para a integridade dos dados, sendo assim, julgo de responsabilidade do banco mantê-lo integro.

Sobre a resposta do drsmachado: importante seu comentário sobre as stored procedure, porém, não seria muito limpo inserir uma tupla através de uma SP já que é uma validação muito simples, o que pode ser resolvido com uma trigger. Muito obrigado pela resposta.

Agora sobre a solução atual: pesquisei um pouco mais e desenvolvi a seguinte solução:

DELIMITER $$

USE `REUNIOES`$$

CREATE TRIGGER checkTypeValue 
BEFORE INSERT ON Reuniao
FOR EACH ROW
BEGIN
	DECLARE dummy INT;

	IF ( NEW.idConselho <> 2 AND NEW.tipo NOT IN ( 'O', 'E' ) ) THEN
		SET NEW := "The type of the meeting is not valid";
	END IF;		
END $$

DELIMITER ;

Ainda não é elegante o suficiente, porém, quando há um erro a seguinte resposta é emitida:

#1231 - Variable 'new' cannot be set to the value of 'The type of the meeting is not valid'

Esse proposta pelo menos exibe alguma mensagem que ajudará o usuário a encontrar o motivo do erro. Mas para mim, o melhor seria o MySQL 5.1 conter recursos como:

throw new Exception( "The type of the meeting is not valid" );

Isso resolveria o meu problema com muita elegância.

Muito obrigado pela ajuda, qualquer outra sugestão será muito bem vinda.

L

Na versão 5.1 do MySQL não tem mas, na versão 5.6 existe o seguinte:

SIGNAL STATE '45000' SET MESSAGE_TEXT = '&lt;SUA MENSAGEM&gt;';

O código 45000 é para mensagens customizadas, existem outros códigos para outros erros já mapeados.

L
DELIMITER $$  
  
USE `REUNIOES`$$  
  
CREATE TRIGGER checkTypeValue   
BEFORE INSERT ON Reuniao  
FOR EACH ROW  
BEGIN  
    DECLARE dummy INT;  
  
    IF ( NEW.idConselho &lt;&gt; 2 AND NEW.tipo NOT IN ( 'O', 'E' ) ) THEN  
        SIGNAL STATE '45000' SET MESSAGE_TEXT = 'The type of the meeting is not valid';
    END IF;       
END $$  
  
DELIMITER ;
Criado 13 de maio de 2011
Ultima resposta 11 de jun. de 2014
Respostas 5
Participantes 4