Imagina a situação: você é admin de um banco de dados grandão. Do nada, alguém apaga uma informação importante da tabela e todo mundo grita: "Quem fez isso?!". Pra evitar esse tipo de perrengue, os bancos de dados permitem registrar mudanças e acompanhar o que rolou com os dados. Tudo isso rola com log e auditoria.
- Log de mudanças permite guardar o histórico do que rolou: qual registro mudou, como e quando.
- Auditoria de dados serve pra uma checagem mais profunda, incluindo não só as mudanças, mas também info sobre o usuário que fez a parada.
Agora que você já entendeu o "porquê", bora aprender o "como".
Criando uma tabela pra logs
Antes de configurar os triggers, a gente precisa de uma tabela pra guardar os logs das mudanças. Olha só esse exemplo:
-- Criando tabela pra logar mudanças
CREATE TABLE change_logs (
log_id SERIAL PRIMARY KEY, -- Identificador único do registro
table_name TEXT NOT NULL, -- Nome da tabela onde rolou a mudança
operation TEXT NOT NULL, -- Tipo de operação: INSERT, UPDATE, DELETE
change_time TIMESTAMP DEFAULT NOW(), -- Momento da mudança
old_data JSONB, -- Dados antes da mudança (pra UPDATE/DELETE)
new_data JSONB -- Dados depois da mudança (pra INSERT/UPDATE)
);
O que tá rolando aqui?
log_id— identificador único pra cada registro do log.table_name— a gente vai registrar qual tabela foi alterada.operation— tipo da operação:INSERT,UPDATEouDELETE.change_time— marca o momento exato da mudança.old_dataenew_data— dados antes e depois da mudança, em formato JSON.
Logando mudanças com trigger
Agora que temos a tabela de logs, bora criar um trigger pra uma das tabelas, tipo students. Ele vai registrar todas as mudanças: adicionar novos estudantes, atualizar ou deletar. Olha o que vamos fazer:
- Vamos escrever uma função em PL/pgSQL que adiciona registros na tabela de logs.
- Vamos criar um trigger na tabela
students.
A função vai receber info sobre a operação (INSERT, UPDATE, DELETE), além dos dados que mudaram (OLD e NEW).
-- Função pra registrar mudanças na tabela de logs
CREATE OR REPLACE FUNCTION log_student_changes()
RETURNS TRIGGER AS $$
BEGIN
-- Logando operação INSERT
IF TG_OP = 'INSERT' THEN
INSERT INTO change_logs (table_name, operation, new_data)
VALUES ('students', 'INSERT', row_to_json(NEW));
-- Logando operação DELETE
ELSIF TG_OP = 'DELETE' THEN
INSERT INTO change_logs (table_name, operation, old_data)
VALUES ('students', 'DELETE', row_to_json(OLD));
-- Logando operação UPDATE
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO change_logs (table_name, operation, old_data, new_data)
VALUES ('students', 'UPDATE', row_to_json(OLD), row_to_json(NEW));
END IF;
RETURN NULL; -- Retorna NULL porque é um AFTER-trigger
END;
$$ LANGUAGE plpgsql;
Aqui:
TG_OP— variável especial que guarda a operação atual:INSERT,UPDATE,DELETE.row_to_json(OLD)erow_to_json(NEW)— transformam os dados da linha pra JSON, pra facilitar o armazenamento.RETURN NULL— como é umAFTER-trigger, não precisa retornar dados alterados.
Agora vamos ligar nossa função à tabela students.
-- Criando trigger pra logar mudanças
CREATE TRIGGER students_log_trigger
AFTER INSERT OR UPDATE OR DELETE ON students
FOR EACH ROW
EXECUTE FUNCTION log_student_changes();
O que tá rolando aqui?
AFTER INSERT OR UPDATE OR DELETE— o trigger dispara depois das operações na tabelastudents.FOR EACH ROW— o trigger roda pra cada linha alterada.EXECUTE FUNCTION log_student_changes()— chama nossa função de log.
Testando o trigger
Chegou a hora de testar nosso trigger.
- Inserindo um novo registro
INSERT INTO students (name, age, grade)
VALUES ('Otto Lin', 20, 'A');
Bora ver o que foi registrado na tabela de logs:
SELECT * FROM change_logs;
Exemplo de resultado:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 1 | students | INSERT | 2023-10-10 12:00:00 | NULL | {"name": "Otto Lin", "age": 20, ...} |
- Atualizando um registro
UPDATE students
SET grade = 'B'
WHERE name = 'Otto Lin';
De novo, vamos checar a tabela de logs:
SELECT * FROM change_logs ORDER BY change_time DESC;
Resultado:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 2 | students | UPDATE | 2023-10-10 12:05:00 | {"name": "Otto Lin", "age": ...} | {"name": "Otto Lin", "age": ..., ...} |
- Deletando um registro
DELETE FROM students
WHERE name = 'Otto Lin';
E mais uma vez, bora conferir o log:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 3 | students | DELETE | 2023-10-10 12:10:00 | {"name": "Otto Lin", "age": ...} | NULL |
Exemplos de uso na vida real
- Log de operações em tabelas críticas: por exemplo, uma tabela de contas bancárias precisa registrar todas as mudanças pra evitar fraude.
- Auditoria do sistema: você pode guardar registros pra cumprir normas ou analisar o que os usuários estão fazendo.
- Garantir recuperação de dados: se alguém apagar dados sem querer, dá pra recuperar usando a tabela de logs.
Peculiaridades e pegadinhas
Quando for implementar log com triggers, é importante pensar na performance. Se o trigger dispara toda hora, pode sobrecarregar o banco. Então:
- Use log só nas tabelas realmente importantes.
- Se o volume de logs ficar gigante, pense em estratégias de arquivamento.
Triggers são tipo corda de guitarra bem afinada: exigem ajuste fino, mas deixam tudo rodando bonito, automatizando tarefas chatas e garantindo controle sobre os dados.
GO TO FULL VERSION