Imagina que você tá desenvolvendo um app pra gerenciar estudantes e cursos, e tem uma tabela students. Nessa tabela tem o campo last_modified, que precisa ser atualizado automaticamente toda vez que algum dado do registro muda (tipo quando você muda o nome do estudante ou a idade dele).
Ao invés de ficar atualizando o last_modified manualmente em cada query SQL, bora criar um trigger que faz isso pra gente.
Estrutura da tabela students
Pra começar, bora criar a tabela students que a gente vai usar no exemplo. Essa tabela tem as infos básicas dos estudantes:
CREATE TABLE students (
student_id SERIAL PRIMARY KEY, -- Identificador único do estudante
name VARCHAR(100) NOT NULL, -- Nome do estudante
age INT, -- Idade do estudante
last_modified TIMESTAMP NOT NULL DEFAULT NOW() -- Hora da última alteração
);
- O campo
last_modifiedjá vem preenchido com a hora atual (NOW()) quando o registro é criado. - Esse campo vai ser atualizado automaticamente quando os dados do estudante mudarem.
Vamos colocar alguns dados de teste na tabela:
INSERT INTO students (name, age)
VALUES
('Otto Lin', 20),
('Maria Chi', 22),
('Alex Song', 19);
Agora os dados na tabela ficam assim:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 20 | 2023-10-15 12:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Criando a função pra atualizar o last_modified
A função em PL/pgSQL vai ser usada pelo trigger pra atualizar o valor do campo last_modified. Ela vai ser chamada automaticamente antes de alterar o registro.
Bora criar a função update_last_modified:
CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
-- Atualiza o campo last_modified pra hora atual
NEW.last_modified := NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
NEW— é uma variável especial que tem os dados novos do registro (depois da alteração).- A gente coloca em
NEW.last_modifiedo valor deNOW()(data e hora atual). - A função retorna a variável
NEWatualizada, que é o que o trigger precisa pra funcionar direito.
Criando o trigger
Agora bora criar o trigger que vai chamar automaticamente a função update_last_modified toda vez que um registro da tabela students for atualizado.
CREATE TRIGGER set_last_modified
BEFORE UPDATE ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();
O que tá rolando aqui:
BEFORE UPDATEdiz que o trigger roda antes da operação de update.FOR EACH ROWquer dizer que o trigger roda pra cada linha alterada.EXECUTE FUNCTION update_last_modified()manda chamar a funçãoupdate_last_modified.
Testando o trigger
Agora bora ver como o trigger funciona. Vamos selecionar os dados atuais da tabela students:
SELECT * FROM students;
Resultado:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 20 | 2023-10-15 12:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Agora vamos atualizar a idade do estudante com student_id = 1:
UPDATE students
SET age = 21
WHERE student_id = 1;
Vamos selecionar de novo os dados da tabela:
SELECT * FROM students;
Resultado esperado:
| student_id | name | age | last_modified |
|---|---|---|---|
| 1 | Otto Lin | 21 | 2023-10-15 14:00:00 |
| 2 | Maria Chi | 22 | 2023-10-15 12:00:00 |
| 3 | Alex Song | 19 | 2023-10-15 12:00:00 |
Repara: o campo last_modified do registro com student_id = 1 foi atualizado pra hora atual, enquanto os outros ficaram iguais.
Expandindo a lógica do trigger
Agora, imagina que você quer que o campo last_modified só seja atualizado se mudar certos campos. Tipo, se mudar só o nome ou a idade do estudante, o trigger roda, mas se mudar outra coisa, não.
Pra isso, dá pra colocar uma condição com o operador WHEN na definição do trigger.
Bora criar um novo trigger com condição:
DROP TRIGGER IF EXISTS set_last_modified ON students;
CREATE TRIGGER set_last_modified
BEFORE UPDATE ON students
FOR EACH ROW
WHEN (OLD.name IS DISTINCT FROM NEW.name OR OLD.age IS DISTINCT FROM NEW.age)
EXECUTE FUNCTION update_last_modified();
Aqui:
- A condição
WHENcheca se os valores antigos (OLD) são diferentes dos novos (NEW) nos camposnameeage. - Se nenhum desses campos mudou, o trigger não roda.
Bora atualizar de novo os dados na tabela e testar essa lógica nova.
Dicas pra usar triggers
- Não exagere nos triggers. Eles são práticos, mas podem deixar a lógica do banco mais complicada e a depuração mais difícil.
- Sempre documenta o que o trigger faz e quando ele deve ser usado.
- Usa condições
WHENpra evitar que o trigger rode sem necessidade. - Lembra que triggers podem afetar a performance do banco, principalmente se a tabela for grande.
Erros comuns ao trabalhar com triggers
Alteração errada dos dados. Tipo, esquecer de setar o valor pra NEW e retornar os dados originais sem mudar nada.
Condições erradas. Por exemplo, esquecer de colocar a condição WHEN e o trigger roda até quando não precisa mudar nada.
Recursão. Se o trigger chama uma função que chama o trigger de novo, pode acabar criando um loop infinito. O PostgreSQL tem proteção contra recursão, mas é melhor evitar esse tipo de situação.
Esse exemplo mostra como triggers podem facilitar a vida pra atualizar dados automaticamente. Em projetos reais, essa técnica é muito usada pra log de alterações, garantir integridade dos dados e automatizar tarefas chatas.
GO TO FULL VERSION