Ir para conteúdo

Arquivado

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

felipekraemer

Problema com Trigger

Recommended Posts

Olá, estou tendo um problema com uma trigger. Explicando a situação:

Eu tenho as seguintes tabelas:

CREATE TABLE `pessoas` (
  `codigo` int(11) NOT NULL,
  `nome` varchar(70) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`codigo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `programa_semanal` (
  `semana` date NOT NULL,
  `tema` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
  `presidente` int(11) DEFAULT NULL,
  `orador` int(11) DEFAULT NULL,
  PRIMARY KEY (`semana`),
  KEY `FK_Orador_idx` (`orador`),
  KEY `FK_Presidente_idx` (`presidente`),
  CONSTRAINT `FK_Orador` FOREIGN KEY (`orador`) REFERENCES `pessoas` (`codigo`),
  CONSTRAINT `FK_Presidente` FOREIGN KEY (`presidente`) REFERENCES `pessoas` (`codigo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

O que acontece:

Eu tenho um cadastro de pessoas e um cadastro de programação semanal que vou alimentando no início de cada mês as semanas seguintes. Neste cadastro antecipado, informo a semana e o tema, e as informações são inseridas na tabela programa_semanal.

Alguns dias antes de determinada semana chegar, eu preciso editar a programação e escolher, dentre a lista de pessoas, quem vai ser o presidente e quem vai ser o orador, e as informações são editadas na tabela programa_semanal. Eu posso também, caso a semana não tenha passado, editar a programação semanal e escolher outras pessoas como presidente e orador.

Para evitar que algumas pessoas sejam escolhidas com mais frequência do que outras como presidentes ou oradores, eu criei outra tabela que tem a seguinte estrutura:

CREATE TABLE `participacao` (
  `codigo_pessoa` int(11) NOT NULL,
  `semana` date NOT NULL,
  `tipo_participacao` varchar(1) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`codigo_pessoa`,`semana`),
  CONSTRAINT `FK_Pessoa` FOREIGN KEY (`codigo_pessoa`) REFERENCES `pessoas` (`codigo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Quando eu gravar as alterações na tabela programa_semanal, a ideia é que a trigger faça uma inserção ou uma alteração nesta tabela participacao, levando em consideração o seguinte:

  1. Quando eu faço INSERT na tabela programa_semanal, as colunas 'presidente' e 'orador' ficam com valor NULL, pois estou apenas cadastrando as semanas antecipadamente.
    Neste caso a trigger não deve fazer nada pois o presidente e o orador ainda não foram escolhidos.
  2. Quando eu faço UPDATE na tabela programa_semanal é quando as colunas 'presidente' e 'orador' ficam com valor inteiro.
    Neste caso, a trigger deve validar se o valores antigos das colunas 'presidente' e 'orador' na tabela programa_semanal são nulos:
    - Se forem nulos, a trigger deve fazer INSERT na tabela participação, pois é a primeira vez que o presidente e o orador foram definidos para aquela semana.
    - Se não forem nulos, a trigger deve fazer UPDATE na tabela participacao, pois resolvi escolher outra pessoa como presidente ou orador naquela semana.
    - Tanto no INSERT quanto no UPDATE as colunas 'codigo_pessoa' e 'semana' vem da tabela programa_semanal e a coluna 'tipo_participacao' recebe o valor 'O' caso seja orador, ou valor 'P' caso seja presidente;

Isso me permitiria, na hora de escolher o presidente e o orador para determinada semana, fazer um SELECT ordenando pelas pessoas que a mais tempo não são escolhidas como presidente ou como orador, para que todos tenham as mesmas chances de participar.

No momento, a trigger está definida assim:

DELIMITER $$
DROP TRIGGER IF EXISTS updateParticipantes;
$$
DELIMITER //
CREATE TRIGGER updateParticipantes AFTER UPDATE ON programa_semanal
    FOR EACH ROW
    BEGIN
        IF old.presidente <> new.presidente THEN
            IF old.presidente IS NULL THEN
                INSERT INTO participacao (codigo_pessoa, semana, tipo_participacao) VALUES (new.presidente, new.semana, 'P');
            ELSE
                UPDATE participacao SET codigo_pessoa = new.presidente 
                WHERE participacao.semana = new.semana
                AND participacao.tipo_participacao = 'P';
            END IF;
        END IF;
        
        IF old.orador <> new.orador THEN
            IF old.orador IS NULL THEN
                INSERT INTO participacao (codigo_pessoa, semana, tipo_participacao) VALUES (new.orador, new.semana, 'O');
            ELSE
                UPDATE participacao SET codigo_pessoa = new.orador
                WHERE participacao.semana = new.semana
                AND participacao.tipo_participacao = 'O';
            END IF;
        END IF;        
    END

Só que ela não está funcionando e eu não consigo entender o por quê. Quando eu executo este script para deleção / criação da trigger não dá nenhum erro de execução, então até onde eu entendo não há erro de sintaxe na definição da trigger.

Só que quando atualizo a tabela programa_semanal com valores para presidente e orador, nada acontece na tabela participacao. Mas se eu colocar algum INSERT ou UPDATE logo após o BEGIN, isso funciona, então aparentemente o problema é nos IFs.

Alguém poderia me ajudar a entender o que está errado?

Muito obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Alterei a lógica da trigger, dizendo a mesma coisa de forma diferente, e funcionou:

DELIMITER $$
DROP TRIGGER IF EXISTS updateParticipantes;
$$
DELIMITER //
CREATE TRIGGER updateParticipantes AFTER UPDATE ON programa_semanal 
FOR EACH ROW
BEGIN
        IF OLD.presidente IS NULL THEN
            IF NEW.presidente IS NOT NULL THEN
            
				INSERT INTO participacao (codigo_pessoa, semana, tipo_participacao) VALUES (NEW.presidente, OLD.semana, 'P');
                
		   END IF;
		ELSE             
		    IF NEW.presidente IS NOT NULL THEN
            
				UPDATE participacao SET codigo_pessoa = NEW.presidente WHERE participacao.semana = OLD.semana AND participacao.tipo_participacao = 'P';
                
            END IF;
        END IF;
        
        
        IF OLD.orador IS NULL THEN
            IF NEW.orador IS NOT NULL THEN
            
				INSERT INTO participacao (codigo_pessoa, semana, tipo_participacao) VALUES (NEW.orador, OLD.semana, 'O');
                
		   END IF;
		ELSE             
		    IF NEW.orador IS NOT NULL THEN
				
                UPDATE participacao SET codigo_pessoa = NEW.orador WHERE participacao.semana = OLD.semana AND participacao.tipo_participacao = 'O';
                
            END IF;
        END IF;

END$$
DELIMITER ;

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por dfoliveira82
      Bom dia senhores,
       
      sou novo no Oracle, antes trabalhava com SQL SERVER, e me deparei com algo que ja estou a horas tentando solucionar mas nao consegui.
      Nessa Trigger que vou postar, quando mando compilar ela, fala que esta faltando uma virgula, apos o values, mas nao precisa dela e nao acho onde pode ser essa virgula faltante.
      CREATE OR REPLACE TRIGGER JOBS_CL_INSERE_USUARIO AFTER INSERT OR UPDATE OF EXPORTADA_AVA ON SITE_USUARIOS REFERENCING NEW AS NEW BEGIN INSERT INTO BLACKBEAN.TBL_USERS VALUES (NULL, 'INSERT', NULL, 'db', '0', '0', '0', TO_CHAR(:NEW.CPF), MD5(:NEW.CPF||'port@l'), TO_CHAR(:NEW.CPF), SUBSTRING(:NEW.NOME, 1, INSTR(:NEW.NOME, ' ')-1), SUBSTRING(:NEW.NOME, INSTR(:NEW.NOME, ' ')+1, LEN(:NEW.NOME)), 'email@email.com', NULL, NULL, DATE_TO_UNIX_TS(SYSDATE), NULL, NULL); END; / Se alguem puder me ajudar agradeceria.
    • Por Carlos Antoliv
      Senhores, bom dia.
       
      tenho um campo status. Então, a ideia é mudar o status. Consigo alterar o status quando necessário. Daí, pensei em todas vez que alterar, salvar o id do usuário, data, hora, o último status alterado...
      consigo fazer isso com INSERT, depois do UPDATE.
       
      Nao uso trigger. Até tentei fazer, mas não saiu como eu queria.
       
      Então, para os maiores entendedores do assunto, a melhor prática seria a TRIGGER ou INSERT ? Melhor prática ou o que mais funciona na prática ?
       
      Alguém poderia dissertar sobre isso ?
      Vlw..abço
    • Por mateus.andriollo
      Gostaria de saber se alguém tem uma trigger para fazer log de qualquer tipo de transação de dados em qualquer tabela do banco. Porém, preciso carregar um campo UserName que será setado a cada conexão via login php
      SET @UserName = 'ZeBala' Achei vários exemplos porém tenho q criar um trigger para cada tabela
       
      CREATE TRIGGER roles_audit_au AFTER UPDATE ON `<nome_tabela>` Existe uma forma de não ser direcionada?
    • Por gcors88
      Prezados, desenvolvi um gatilho onde este tem comunicação com outra tabela, uma é a coleta_sinal_vital, e onde o gatilho foi criado é na table  itcoleta_sinal_vital ( esta possui uma fk da primeira), a questão é que dentro do gatilho realizo um select na primeira tabela para consultar o valor inserido em uma coluna da primeira tabela, faço essa consulta baseada nessa fk que esta sendo inserida ou seja where = :new.cd_coleta_sinal_vital, a questão é que no momento em que esse select é executado ele não retorna dado nenhum, acredito que isto ocorre porque a inserção em ambas as tabelas é feito de forma simultânea, pois se comparado posteriormente o valor da coluna sempre é inserido, gostaria de saber se existe alguma forma de aplicar uma espera ou atraso neste gatilho para que ele possa capturar este valor sem problemas, grato!
    • Por José Peixoto
      Olá,
       
      há alguma forma de fazer uma trigger só ser executada depois que a outra executar? 
       
      Por exemplo: a trigger2 só é disparada quando a trigger1 fizer o commit das informações.
       
      Obrigado desde já :)
×

Informação importante

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