1
resposta

Pergunta sobre where no desafio 2

CREATE OR REPLACE FUNCTION cria_instrutor() RETURNS TRIGGER AS $$ 
    DECLARE
        media_salarial DECIMAL;
        maior_salario DECIMAL;
        instrutores_recebem_menos INTEGER DEFAULT 0;
        total_instrutores INTEGER DEFAULT 0;
        salario DECIMAL;
        percentual DECIMAL (5,2);
    BEGIN
        SELECT AVG(instrutor.salario) INTO media_salarial FROM instrutor WHERE id <> NEW.id;
        SELECT MAX(instrutor.salario) INTO maior_salario FROM instrutor WHERE id <> NEW.id;

        IF NEW.salario > maior_salario THEN
            NEW.salario := maior_salario;        
            INSERT INTO log_instrutores (informacao) VALUES (NEW.nome || 'salario recusado, instrutor receberá o teto');
        ELSE 
            NEW.salario > media_salarial THEN 
            INSERT INTO log_instrutores (informacao) VALUES (NEW.nome || 'recebe acima da média');
        END IF;

        FOR salario IN SELECT instrutor.salario FROM instrutor WHERE id <> NEW.id LOOP 
            total_instrutores := total_instrutores + 1;

            IF NEW.salario > salario THEN 
                instrutores_recebem_menos := instrutores_recebem_menos + 1;
            END IF;
        END LOOP;

        percentual = instrutores_recebem_menos::DECIMAL / total_instrutores::DECIMAL * 100;

        INSERT INTO log_instrutores (informacao)
            VALUES (NEW.nome || ' recebe mais do que' || percentual || '% da grade de instrutores');

        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

estou sem o PostgreSQL instalado para saber se não houe erro ... Mas a minha pergunta é a seguinte: preciso colocar o where id <> NEW.id nos select avg e max, já que estou fazendo na trigger before?

esse where não permite que o novo registro faça parte do cálculo, mas como a trigger está rodando antes do insert esse registro já não estaria fora desse cálculo?

1 resposta

Olá Tiago, tudo bem?

Peço desculpas pela demora no retorno.

Como o salário do novo instrutor precisa ser comparado com os salários dos instrutores já inseridos na tabela de instrutores, o WHERE id <> NEW.id é utilizado para que o salário do novo instrutor não entre no AVG para calcular a média salarial e no MAX para calcular o maior salário, como você mencionou.

  • O primeiro select com o AVG, realiza uma busca na tabela de instrutores, onde apenas os instrutores que tenham o ID diferente do ID do novo instrutor inserido terão o valor do salário informado no AVG para obter a média salarial dos instrutores.
SELECT AVG(instrutor.salario) INTO media_salarial FROM instrutor WHERE id <> NEW.id;
  • O segundo select com o MAX, realiza uma busca na tabela de instrutores, onde apenas os instrutores que tenham o ID diferente do ID do novo instrutor terão o valor do salário informado no MAX para obter o maior salário dos instrutores.
SELECT MAX(instrutor.salario) INTO maior_salario FROM instrutor WHERE id <> NEW.id;

Mesmo utilizando a trigger com o before, o valor do salário do novo instrutor entra no cálculo, já que objetivo desta função é saber justamente se o salário do novo instrutor inserido na tabela de instrutor é maior que os dos instrutores já existentes na tabela, caso seja, a função deve realizar o ajuste do salário.

Na minha tabela de instrutor já existe o Tiago que tem como salário um valor de 1200:

Tabela de instrutores, com o intrutor tiago com o salario no valor de 1200

Ao realizar um novo insert, informando um novo instrutor que receba mais que o Tiago, como por exemplo: Insert into instrutor (id, nome, salario) values(23,'Danielle Oliveira', 1500);

A função será executada, quando o cálculo do salário for realizado será identificado que o novo instrutor está com o salário maior, assim o salário dele será ajustado para o valor do salário do Tiago:

  • Tabela log instrutores:

Tabela de log instrutores, com as informações do novo instrutor inserido

  • Tabela instrutor:

Tabela de instrutor, com o antigo instrutor e com o novo instrutor inserido, já com o seu salario alterado pela função

Qualquer dúvida fico à disposição e bons estudos!