Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Marcos S.

Trigger UPDATE

Recommended Posts

Olá pessoal! tudo certo?

Preciso de uma pequena ajuda de vocês!

Tenho um banco de dados onde contém a tabela "Motorista". Nela, existem os campos "codEmpresa" (referenciada como chave a tabela principal "Empresa") e "lider" (campo do tipo BIT) que devemos analisar. Como mostra abaixo:

 

banco.jpg


Preciso criar uma TRIGGER UPDATE que faça a seguinte condição:

 

- Não é permitido mais de um "lider" por "codEmpresa", ou seja, deve ficar nesta mesma condição em destaque na imagem acima.

 

- Se um outro "lider" for alterado para 1, o antigo lider deve ser 0 automaticamente.

 

Para isso estava tentando criar uma TRIGGER AFTER UPDATE, como mostra abaixo:

 

[inline]USE `tms`;
DELIMITER $$
CREATE DEFINER=`root`@`%` TRIGGER tg_lider_unico_update AFTER UPDATE ON tms.motorista
FOR EACH ROW
BEGIN
IF EXISTS (SELECT m.lider FROM tms.motorista m, NEW WHERE m.codEmpresa = NEW.codEmpresa GROUP BY m.codEmpresa HAVING SUM(m.lider) > 1) THEN
SET NEW.lider = 1;
SET OLD.lider = 0;
END IF;
END[/inline]

 

Talvez tenha errado feio em como fazer, mas dessa maneira não funciona! Porque "NEW" não é suportado por AFTER UPDATE e se for fazer por BEFORE UPDATE, é acusado que "OLD" não é suportado.

 

Como solucionar?

 

Agradeço desde já pela ajuda!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nao permitir dois lideres creio que dá numa trigger de before insert /update que verifique se nao existe outro lider, existindo gera um erro.

 

Atualizar o outro pode cair num caso de mutant table

Compartilhar este post


Link para o post
Compartilhar em outros sites

USE `tms`;
 DELIMITER $
 CREATE DEFINER=`root`@`%` TRIGGER tg_lider_unico_update BEFORE UPDATE ON tms.motorista
 FOR EACH ROW
 BEGIN
 IF (SELECT m.lider FROM tms.motorista m WHERE m.codEmpresa = NEW.codEmpresa AND m.lider = 1) IS NOT NULL AND NEW.lider=1 THEN
   --aqui sabemos que para aquela empresa existe um lider e que estamos tentando atualizar outro registro para que ele seja o lider,lembre-se que essa trigger é before update
   UPDATE tms.motorista SET lider=0 WHERE codEmpresa=NEW.codEmpresa;
   --pronto, nao tem mais ngm como lider na empresa, agora é só deixar que o update prossiga pra que um novo lider seja selecionado 
END IF;
 END

EDIT: para o insert vc pode usar uma logica semelhante

EDIT2: achei massa como vc interpretou o OLD, heheh

O OLD e o NEW dentro da trigger se referem ao(aos) registro(s) que vc esta atualizando, vamos supor que vc esteja atualizando o registro 2, o OLD vai pegar o valor antigo da linha e o NEW os novos que vc quer colocar nela.

se vc usar SET OLD.lider=0, como vc fez acima, simplesmente implica que o valor ANTIGO da linha 2 sera 0, o que nao faz sentido para o seu objetivo.

 

qualquer duvida só avisar

 

OBS.: talvez falte um parenteses no IF, mas é só concertar :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

 


USE `tms`;
 DELIMITER $
 CREATE DEFINER=`root`@`%` TRIGGER tg_lider_unico_update BEFORE UPDATE ON tms.motorista
 FOR EACH ROW
 BEGIN
 IF (SELECT m.lider FROM tms.motorista m WHERE m.codEmpresa = NEW.codEmpresa AND m.lider = 1) IS NOT NULL AND NEW.lider=1 THEN
   --aqui sabemos que para aquela empresa existe um lider e que estamos tentando atualizar outro registro para que ele seja o lider,lembre-se que essa trigger é before update
   UPDATE tms.motorista SET lider=0 WHERE codEmpresa=NEW.codEmpresa;
   --pronto, nao tem mais ngm como lider na empresa, agora é só deixar que o update prossiga pra que um novo lider seja selecionado 
END IF;
 END

EDIT: para o insert vc pode usar uma logica semelhante

EDIT2: achei massa como vc interpretou o OLD, heheh

O OLD e o NEW dentro da trigger se referem ao(aos) registro(s) que vc esta atualizando, vamos supor que vc esteja atualizando o registro 2, o OLD vai pegar o valor antigo da linha e o NEW os novos que vc quer colocar nela.

se vc usar SET OLD.lider=0, como vc fez acima, simplesmente implica que o valor ANTIGO da linha 2 sera 0, o que nao faz sentido para o seu objetivo.

 

qualquer duvida só avisar

 

OBS.: talvez falte um parenteses no IF, mas é só concertar :)

 

Agradeço a ajuda! Mas infelizmente não está funcionando :(

 

Quando atualizo a tabela no campo em destaque...

 

bancoo.jpg

 

Aparece a seguinte mensagem...

 

" ERROR 1442: 1442: Can't update table 'motorista' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

SQL Statement:
UPDATE `tms`.`motorista` SET `lider`=1 WHERE `codigo`='2' "

Compartilhar este post


Link para o post
Compartilhar em outros sites

hmmm, verdade, pro before insert vai funcionar, mas pro update vai entrar em um loop massa, vou pensar um pouco depois posto algo

 

Olá amigo!

 

Será que este é um caso impossível?

 

Porque mesmo que seja criado Stored Procedure ou Function para fazer UPDATE por fora da Trigger, como tentei de várias maneiras por aqui, o MySql não permite que a Trigger seja criada!

 

E outra...ele também não permite a execução da sintaxe normal de UPDATE no corpo da Trigger, pois ocorre o caso de mutant table, como nosso amigo Motta disse.

 

O que fazer neste caso, Senhores?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Faça uma procedure para "limpar" os outros líderes que sejam diferentes do passado pelo parametro.

Chame esta procedure após o update.

 

E a solução mais simples que me ocorre.

 

Resolver mutant table não é simples.

 

Eu faria o mais simples , a trigger gera um erro avisando que existe outro (e qual líder) , cabe ao usuário , mudar o atual , incluir ou alterar o novo.

 

O perigo é ficar sem líder, a regra de negócio permite ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Faça uma procedure para "limpar" os outros líderes que sejam diferentes do passado pelo parametro.

Chame esta procedure após o update.

 

E a solução mais simples que me ocorre.

 

Resolver mutant table não é simples.

 

Eu faria o mais simples , a trigger gera um erro avisando que existe outro (e qual líder) , cabe ao usuário , mudar o atual , incluir ou alterar o novo.

 

O perigo é ficar sem líder, a regra de negócio permite ?

 

Não teve outro jeito, a solução foi feita pela aplicação mesmo.

A aplicação limpa o campo de líder antigo da empresa específica e registra o novo líder, sendo que na tabela está sem restrição alguma em relação a esta regra.

 

Obrigado pela ajuda, meus amigos! Foi um grande aprendizado! =D

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.