Trabalhando com Triggers no Oracle
Tags: triggers, oracle, database, oracledb
Published: 2023-11-13 19:51:22

**Introdução**
As triggers são componentes de código PL/SQL, relacionados aos comandos de inserção, atualizar e excluir (INSERT, UPDATE e DELETE), que servem como um tipo de armazenamento, auxiliando, principalmente, na manutenção da integridade dos dados do banco de dados. Com isso em mente, iremos ver mais um pouco sobre esse mecanismo que desempenham um papel crucial no gerenciamento de banco de dados e automação de tabelas.  

**Definição**
Uma trigger são mecanismos do tipo procedimento armazenado, que são executados assim que os dados sofrem mudanças num banco de dados. Estes, que são por meio do DML (Data Manipulation Language) utilizando INSERT, UPDATE ou DELETE numa tabela ou view. São engatilhadas em qualquer situação válida dentro do sistema do banco. Também podem ser acionadas por meio do DDL (Data Definition Language), usando CREATE, ALTER e DROP. 


**Sintaxe de uma Trigger**
Para que possamos criar uma trigger, precisamos utilizar a sua declaração, que é:  
**CREATE TRIGGER**

Sua declaração pode variar, de acordo com o tipo de Trigger que você deseja criar, podendo ser um Dml Trigger, Schema Trigger ou Database Trigger. 

As Triggers que normalmente são mais usadas são as Triggers de DML, então, vamos ver alguns exemplos com esses casos. 

```
CREATE [OR REPLACE] TRIGGER TRIGGER_NAME 
{BEFORE | AFTER} dml_event ON TABLE_NAME
[FOR EACH ROW] 
  [DECLARE variable] 
  BEGIN 
  pl_sql_code 
  [EXCEPTION exception_code] 
  END; 
```
Vamos ver em detalhes o que cada item dentro da nossa declaração faz:

- OR REPLACE: Usada de forma opcional. Caso você use-a, qualquer outra trigger que conter o mesmo nome, será substituída por essa Trigger que você está criando; 
- nome_trigger: Nome dado a trigger dentro do banco de dados (database); 
- BEFORE | AFTER: Definide se você deseja que a trigger seja disparada antes ou depois de alguma declaração ou evento; 
- evento_dml: Esse é o responsável pelo disparo da nossa trigger, ele pode ser usado juntamente com INSERT, UPDATE ou DELETE; 
- nome_tabela: Esse é o nome da tabela que disparará o evento para nossa trigger; 
- FOR EACH ROW: Usado para definir de o gatilho será disparado para cada linha de comando, caso não use essa declaração, a trigger só será disparada uma vez; 
- DECLARE: Caso você necessite de variáveis dentro da sua trigger, você pode usar o declare. Lembrando que elas só podem e serão usadas dentro da trigger; 
- codigo_pl_sql: Aqui é onde escreveremos o comportamento da nossa trigger e tudo o que ela irá fazer;
- EXCEPTION: Nossa exception é o nosso retorno caso haja algum erro, esperado ou não. 

Quando escrevemos triggers para dml, a sua finalidade é ser para uma instrução, com isso, precisamos fazer a referenciação aos dados dentro da instrução. Como por exemplo: 

- Dados que estão sendo inseridos em um INSERT; 
- Dados sendo atualizados em um UPDATE (podendo ser os dados antigos ou novos); 
- Dados sendo excluídos em um DELETE.

Podemos referenciá-los com duas variáveis.  
- :NEW 
- :OLD 

Vamos a um exemplo: 
- Supondo que você deseja pegar o valor de um salário antes que um UPDATE seja inserido, você pode usar: 
:OLD.salario 

- Caso você deseje pegar o valor de um novo salário após um INSERT, você pode usar:
:NEW.salario 

Há diversos modo de utilizarmos Triggers, abaixo, temos uma tabela onde podemos ver as situações na qual podemos utilizá-las com :NEW e :OLD. 

![Esta tabela descreve quando você pode ou não ler ou atualizar esses valores](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0zf0ugrnyitvnsj14xh.PNG)

Vamos ver agora alguns exemplos de situações em que aplicamos as Triggers. 

**SINTAXE BEFORE INSERT TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
BEFORE INSERT ON table_name 
[FOR EACH ROW] 
  [DECLARE variables] 
  BEGIN 
  pl_sql_code 
  [EXCEPTION exception_code] 
  END; 
```

Algumas observações: 
- Você não pode criar uma Trigger BEFORE INSERT em uma VIEW, a menos que seja uma VIEW de edição;
- Se você executar uma Trigger de instrução e omitir a cláusula FOR EACH ROW, não poderá ler as variáveis :NEW e :OLD, pois eles não existem para um Trigger INSERT.

**SINTAXE AFTER INSERT TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
AFTER INSERT ON table_name 
[FOR EACH ROW] 
[DECLARE variables] 
BEGIN 
  pl_sql_code 
[EXCEPTION exception_code] 
END; 
```

Algumas observações: 
- Você não pode criar um gatilho AFTER INSERT em uma visualização, a menos que seja uma visualização de edição;
- Se você estiver executando um gatilho de instrução (omitindo a cláusula FOR EACH ROW), não poderá ler as variáveis :NEW ou :OLD;

- Se você estiver executando um gatilho de linha (usando FOR EACH ROW): 
- Você pode ler, mas não atualizar os :NEW valores; 
- Você não pode ler ou atualizar os valores :OLD, pois eles não existem para um gatilho INSERT. 

**SINTAXE BEFORE UPDATE TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
BEFORE UPDATE ON table_name 
[FOR EACH ROW] 
[DECLARE variables] 
BEGIN 
  pl_sql_code 
[EXCEPTION exception_code] 
END; 
```

Algumas observações: 

- Um TRIGGER BEFORE UPDATE é um TRIGGER executado antes de uma instrução UPDATE ser executada;
- Se você executar uma Trigger de instrução e omitir a cláusula FOR EACH ROW, não poderá ler as variáveis :NEW e :OLD, pois eles não existem para um Trigger INSERT; 
- Você não pode criar um gatilho BEFORE UPDATE em uma visualização, a menos que seja uma visualização de edição; 
- Se você estiver executando um gatilho de instrução (omitindo a cláusula FOR EACH ROW), não poderá ler as variáveis :NEW ou :OLD; 
- Se você estiver executando um gatilho de linha (usando FOR EACH ROW), poderá ler e atualizar os valores :NEW e :OLD.
 

**SINTAXE AFTER UPDATE TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
AFTER UPDATE ON table_name 
[FOR EACH ROW] 
[DECLARE variables] 
BEGIN 
  pl_sql_code 
[EXCEPTION exception_code] 
END; 
```

Algumas observações sobre o AFTER UPDATE: 
- Você não pode criar um gatilho AFTER UPDATE em uma visualização, a menos que seja uma visualização de edição; 
- Se você estiver executando um gatilho de instrução (omitindo a cláusula FOR EACH ROW), não poderá ler as variáveis :NEW ou :OLD; 
- Se você estiver executando um gatilho de linha (usando FOR EACH ROW), poderá ler, mas não atualizar, os valores :NEW e :OLD.

**SINTAXE BEFORE DELETE TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
BEFORE DELETE ON table_name 
[FOR EACH ROW] 
[DECLARE variables] 
BEGIN 
  pl_sql_code 
[EXCEPTION exception_code] 
END; 
```

Algumas observações: 
- Você não pode criar um gatilho BEFORE DELETE em uma visualização, a menos que seja uma visualização de edição; 
- Se você estiver executando um gatilho de instrução (omitindo a cláusula FOR EACH ROW), não poderá ler os valores :OLD; 
- Se você estiver executando um gatilho de linha (usando FOR EACH ROW), poderá ler e atualizar os valores :OLD. 

**SINTAXE AFTER DELETE TRIGGER**

```
CREATE [OR REPLACE] TRIGGER trigger_name 
AFTER DELETE ON table_name 
[FOR EACH ROW] 
[DECLARE variables] 
BEGIN 
  pl_sql_code 
[EXCEPTION exception_code] 
END; 
```
Algumas observações: 
- Você não pode criar um gatilho AFTER DELETE em uma visualização, a menos que seja uma visualização de edição; 
- Se você estiver executando um gatilho de instrução (omitindo a cláusula FOR EACH ROW), não poderá ler os valores :OLD; 
- Se você estiver executando um gatilho de linha (usando FOR EACH ROW), poderá ler, mas não atualizar os valores :OLD. 


**Quadro de vantagens e desvantagens**

**Vantagens**
- Mantém todas as alterações sob controle – UPDATE, DELETE, INSERT- nas tabelas criadas, quando ocorre a inserção/alteração de dados nas tabelas de auditorias; 
- Permitem uma replicação síncrona nas tabelas; 
- Operam com autorizações/padrões de segurança nas tabelas; 
- Fornecem alternativas para executar tarefas agendadas, já que, os triggers automaticamente auxiliam antes ou depois de uma alteração ser feita nos dados de uma tabela.
 
**Desvantagens**
- Podem impactar no desempenho do sistema, como aumentar a sobrecarga do banco de dados; 
- Só utilizam troubleshoots estendidas, o que invalida outras validações; 
- Por usar triggers, caso tenha um uso excessivo e/ou seja um banco de dados grande, implica numa dificuldade de refatorar ou na manutenbilidade do sistema.
  

**Usando Trigger SQL no Mercado**
Por seguinte, exemplos de empresas que podem utilizar essa ferramenta, para regras, segurança e velocidade: 

- **Entradas e atualizações de dados**
A trigger, pode entrar em uso nesse caso, quando uma empresa de vendas (mercado livre), o qual tem muitas atualizações por causa das compras e mudanças nos valores. 

- **Mudanças de valores**
A trigger, pode entrar em uso no caso de uma empresa de investimentos, pois a cada segundo os valores das bolsas são atualizados, sendo as funcionalidades do trigger são os eventos, possibilitando de configurar esses eventos para a cada segundo e verificar os campos dos valores. 

- **Verificar entradas inválidas**
Um exemplo simples é uma empresa de finanças que tem entradas de valores constantes, onde é importante utilizar o trigger e as ferramentas dele, para verificação de campos inválidos e evitar não quebrar ou parar o banco de dados. 

- **Geração de valores entres colunas**
Um exemplo é uma empresa de cobrança, onde tem que pegar o valor e adicionar os juros, essa é uma utilização do trigger nesse caso. 

- **Sincronização entre tabelas**
Exemplo de utilização é em uma empresa que tem o RH, e quando atualizar as informações dos usuários possam refletir em todos o sistema, como alteração de senha ou quando o usuário atualizar a senha, todos os sistemas da empresa devem atualizar essa atualização. 


**Considerações finais**
Em síntese, as triggers são um componente fundamental e de grande importância no desempenho, automatização, gerenciamento e construção de banco de dados. Portanto, se trata de uma ferramenta muito útil ao construir e gerenciar um sistema, especialmente, quando se trata de controle. 


**Referências bibliográficas**

- https://medium.com/edureka/triggers-in-sql-1c51b2bba4c1 
- https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-triggers.html#GUID-C08EA160-8FD2-4A10-9733-6F2D20C83E93 
- https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16 
- https://www.databasestar.com/oracle-triggers/#What_Are_Oracle_Triggers