BDDAD Bases de Dados Oracle PL/SQL Triggers Nelson Freire (ISEP LEI-BDDAD 2017/18) 1/39
Triggers Sumário Introdução Conceito de Trigger Tipos de Triggers Designações de um Trigger Triggers DML Características Particulares Interesse Aspetos Gerais Lista de Triggers Associados a Tabela Ordem de Disparo de Triggers Impedir/Permitir Triggers Eliminar Triggers Limitação do Tamanho de um Trigger Uso de Triggers Comando CREATE TRIGGER Passos Para Criar um Trigger Pseudo-Registos NEW e OLD Tratamento Diferenciado de Comandos de Triggering Participação em Transações Limitação Mutating Table em Triggers de Linha Exemplo Nelson Freire (ISEP LEI-BDDAD 2017/18) 2/39
Oracle PL/SQL - Triggers Introdução Nelson Freire (ISEP LEI-BDDAD 2017/18) 3/39
Triggers Trigger Unidade de programação PL/SQL Tem um nome Armazenado na BD -- com/sem erros de compilação. Invocação: Automática -- realizada pela BD. Trigger dispara automaticamente. Permitida, por omissão. -- disparo do trigger desinibido. Pode ser impedida. -- disparo do trigger inibido. Explicita impossível. Ocorre: Quando surge o evento de triggering. Evento de Triggering Ocorre quando é executado um comando SQL sobre um dado item. Item: tabela / vista / esquema / BD. Comando SQL é designado comando de triggering. Disparo do Trigger (Timing-Point) Antes / depois da execução de comando de triggering. Conceito de Trigger Único / múltiplo ( para cada linha afetada pelo comando de triggering). invocação permitida invocação impedida Nelson Freire (ISEP LEI-BDDAD 2017/18) 4/39
Triggers Tipos de Triggers Triggers Trigger dispara quando Interesse Observações DML Executado comando DML (INSERT, UPDATE ou DELETE) sobre tabela / vista. Validar valores armazenados. Atribuir valores por omissão. Proibir certas operações DML. Mais usados por utilizadores de PL/SQL. DDL Executado comando DDL: CREATE, DROP, ALTER, GRANT, REVOKE, Auditoria Impedir a execução de certos comandos DDL. Eventos da BD BD arranca / termina. Utilizador da BD faz LOGON / LOGOFF. Ocorrem erros. Monitorar atividade na BD. Eventos da BD: STARTUP, SHUTDOWN, LOGON, LOGOFF, SERVERERROR, INSTEAD OF Executado comando CREATE Executado comando DML (INSERT, UPDATE ou DELETE) sobre vistas. Substituir a execução de comando de triggering pela execução de um dado código. Essencialmente, são alternativas a triggers DML sobre vistas. SUSPEND MODE Execução de comando é suspensa devido a problemas de espaço (falta de tablespace / quota excedida) Alertar alguém para o problema. Resolver o problema. Comandos entram em modo de suspensão até à resolução do problema. Item: DATABASE / SCHEMA Nelson Freire (ISEP LEI-BDDAD 2017/18) 5/39
Triggers Designações de um Trigger Baseadas Nome do comando de triggering -- ex: Trigger INSERT / Trigger LOGON Nome do item de triggering -- ex: Trigger DATABASE / Trigger SCHEMA Timing-point do disparo do trigger -- ex: Trigger BEFORE Statement / Trigger AFTER EACH ROW Nelson Freire (ISEP LEI-BDDAD 2017/18) 6/39
Oracle PL/SQL - Triggers Triggers DML Nelson Freire (ISEP LEI-BDDAD 2017/18) 7/39
Evento de Triggering Composto por: Comandos de triggering: Comandos DML: INSERT UPDATE DELETE Item sobre o qual atuam os comandos de triggering: Tabela / Vista Exemplos Um comando de triggering INSERT ON empregados -- tabela empregados UPDATE ON empregados DELETE ON empregados Múltiplos comandos de triggering INSERT OR UPDATE ON empregados INSERT OR DELETE ON empregados UPDATE OR DELETE ON empregados Características Particulares INSERT OR UPDATE OR UPDATE ON empregados Execução de comando DML Nelson Freire (ISEP LEI-BDDAD 2017/18) 8/39
Interesse Forçar Regras de negócio complexas -- impossível definir em CREATE TABLE. Regras de integridade referencial -- impossível definir em CREATE TABLE. Atribuir Valores por omissão -- impossível definir em CREATE TABLE. CONSTRAINT preferível a trigger Impedir Certas operações DML -- ex: após horas normais de serviço. Certas alterações de tabelas -- i.e., fazer a validação de alterações de tabelas. Transações inválidas -- i.e., provocar ROLLBACK de transação. Registar Eventos -- ex: erros Informação de auditoria Estatísticas do acesso a tabelas. Triggers não servem apenas para impor: Regras de negócio complexas. Restrições de integridade da BD. Nelson Freire (ISEP LEI-BDDAD 2017/18) 9/39
Comando CREATE TRIGGER 1/7 Sintaxe (simplificada) CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] [DECLARE] -- instruções de declarações BEGIN -- instruções executáveis [EXCEPTION] -- handlers de exceções END [nome_trigger]; Carateres especiais: [.] = opcional { } = alternativas nome do trigger (tgr_... por convenção) timing-point do disparo do trigger evento de triggering - 1 disparo para cada linha afetada (cada disparo sob condição) - sem cláusula: apenas 1 disparo corpo do trigger especifica a ação do trigger Exemplo Trigger sobre a tabela barcos NEW Pseudo-registo da linha afetada por comando de triggering. cor Campo do pseudo-registo. Nelson Freire (ISEP LEI-BDDAD 2017/18) 10/39
Comando CREATE TRIGGER 2/7 Cláusula CREATE [OR REPLACE] TRIGGER Especifica o nome do trigger. É um identificador Sujeito às regras dos identificadores. Iniciado por letra, Convenção Prefixo: trg_ Razão Evitar conflitos de nomes Tabela, função e procedimento podem ter o mesmo nome. OR REPLACE Opcional Omisso Gerada exceção se o trigger existir. nome do trigger CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] Nelson Freire (ISEP LEI-BDDAD 2017/18) 11/39
Cláusula BEFORE AFTER Especifica: Timing-point do disparo do trigger. Ação do trigger. BEFORE Antes da execução de comando de triggering. Interesse: Consultar / alterar as linhas afetadas por comando de triggering antes de processadas. Exemplo (ilustrado) Linhas afetadas por comando INSERT / UPDATE alteradas antes de serem inseridas / atualizadas na tabela barcos. AFTER Depois da execução de comando de triggering. Interesse: Consultar as linhas afetadas por comando de triggering depois de processadas. Exemplo Para registar numa tabela de logs as linhas eliminadas por DELETE. timing-point Comando CREATE TRIGGER CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] Nelson Freire (ISEP LEI-BDDAD 2017/18) 12/39 3/7
Cláusula INSERT DELETE UPDATE UPDATE OF Especifica: Evento de triggering. Em termos de: Comando / combinação de comandos DML. INSERT, UPDATE ou DELETE Item sobre o qual atuam esses comandos: Tabela / Vista Cláusula UPDATE OF lista_colunas Comando CREATE TRIGGER Para disparar o trigger: Só quando são atualizadas as colunas indicadas. 4/7 evento de triggering CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] Nelson Freire (ISEP LEI-BDDAD 2017/18) 13/39
Cláusula FOR EACH ROW [ WHEN (condição) ] Opcional Omissa: Trigger de tabela / instrução Especifica: Trigger de linha Comando CREATE TRIGGER Trigger de linha: Pode aceder aos dados das linhas afetadas por comando de triggering. Através dos pseudo-registos: NEW -- NEW na condição WHEN e :NEW no corpo do trigger. OLD -- OLD na condição WHEN e :OLD no corpo do trigger. Interesse: Processar os dados de cada linha da tabela afetada por comando de triggering. WHEN (condição): Condiciona o disparo do trigger. -- restringir a execução da ação do trigger. 5/7 Representa a linha a inserir / atualizar trigger de linha CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] Nelson Freire (ISEP LEI-BDDAD 2017/18) 14/39
Comando CREATE TRIGGER 6/7 Trigger de Tabela / Instrução Dispara só 1 vez -- ação do trigger executada 1 vez. Exemplo com comando de triggering UPDATE. Trigger não tem acesso aos dados de cada linha afetada. Pseudo-registos :NEW e :OLD ilegais Sem cláusula FOR EACH ROW Trigger de Linha Dispara múltiplas vezes: 1 vez para cada linha afetada pelo comando de triggering. Exemplo com comando de triggering UPDATE. 1 disparo sobre toda a tabela Com cláusula 1 disparo sobre cada linha Tem acesso aos dados de cada linha afetada -- através dos pseudo-registos NEW e OLD Nelson Freire (ISEP LEI-BDDAD 2017/18) 15/39
Cláusula WHEN (condição) Opcional Usada: Só em triggers de linha. -- senão, erro de compilação Especifica: Condição de disparo do trigger. Trigger designado Trigger Condicional. Interesse: Evitar disparos desnecessários do trigger. Condição Parêntesis Obrigatórios Pode referenciar: Pseudo-registos NEW e OLD -- sem prefixo dois pontos Pode invocar funções Só SQL predefinidas. Proibido incluir: Subquery Comando CREATE TRIGGER Nelson Freire (ISEP LEI-BDDAD 2017/18) 16/39 7/7 CREATE [OR REPLACE] TRIGGER nome_trigger { BEFORE AFTER } { INSERT DELETE UPDATE UPDATE OF lista_colunas } ON tabela/vista [ FOR EACH ROW [ WHEN (condição) ] ] de disparo do trigger
Passos para Criar Trigger DML 1. Decidir sobre: Evento de triggering: Disparo do trigger aplica-se apenas a um comando INSERT, UPDATE ou DELETE ou Disparo do trigger aplica-se a uma combinação desses comandos? Timing-point do disparo do trigger: Antes da execução de comando de triggering -- com cláusula BEFORE ou Depois da execução de comando de triggering? -- com cláusula AFTER 1 vez para o comando de triggering -- sem cláusula FOR EACH ROW ou 1 vez para cada linha afetada pelo comando de triggering? -- com cláusula FOR EACH ROW Condicionada -- com cláusula WHEN ou Não condicionada? -- sem cláusula WHEN 2. Escrever comando CREATE TRIGGER. 3. Compilar o comando criado. 4. Testar o trigger. Nelson Freire (ISEP LEI-BDDAD 2017/18) 17/39
Pseudo-Registos NEW e OLD 1/7 Estruturas de Dados Estruturas semelhantes ao registo PL/SQL. -- daí pseudo-registo. Tipo: nome_tabela%rowtype -- nome da tabela do evento de triggering. Contém: valores dos campos da linha afetada por comando de triggering. Referenciados como Variáveis No corpo do trigger Com prefixo : Sintaxe :NEW.campo :OLD.campo Na condição da cláusula WHEN Sem prefixo : Sintaxe NEW.campo OLD.campo NEW :NEW Nelson Freire (ISEP LEI-BDDAD 2017/18) 18/39
Disponíveis Apenas em triggers de linha. Pseudo-Registos NEW e OLD 2/7 Sem cláusula FOR EACH ROW => Trigger de Tabela :NEW gera erro de compilação Erro ORA-4082 Nelson Freire (ISEP LEI-BDDAD 2017/18) 19/39
NEW Disponível Apenas em triggers INSERT e UPDATE Contém: Valores dos campos da linha afetada depois das alterações realizadas. OLD Disponível Apenas em triggers UPDATE e DELETE Contém: Valores dos campos da linha afetada antes das alterações realizadas. Valores de OLD e NEW Para a linha em processamento pelo comando de triggering. Pseudo-Registos NEW e OLD 3/7 Comando de Triggering OLD.campo NEW.campo INSERT NULL Valor depois do INSERT UPDATE Valor antes do UPDATE Valor depois do UPDATE DELETE Valor antes do DELETE NULL Nelson Freire (ISEP LEI-BDDAD 2017/18) 20/39
Nomes NEW e OLD Podem ser personalizados. Na cláusula REFERENCING Comando CREATE TRIGGER Interesse Melhorar a legibilidade do código. Código mais específico da aplicação. Pseudo-Registos NEW e OLD 4/7 Sintaxe Exemplo Cláusula REFERENCING NEW substituído por NOVO :NEW substituído por :NOVO Nelson Freire (ISEP LEI-BDDAD 2017/18) 21/39
Limitações dos Pseudo-Registos Ilegais em operação ao nível do registo. -- legal apenas nível do campo do registo. Exemplo :NEW := NULL; -- :NEW.campo := NULL; -- é legal Ilegais como argumento de subprograma (função/procedimento). Mas é legal um campo do pseudo-registo. Ilegal modificar OLD.campo Porque é ilegal alterar valores armazenados na BD. Tentativa gera erro ORA-04085. Ilegal modificar NEW.campo se comando de triggering é DELETE. Tentativa gera erro ORA-04084. Trigger AFTER impedido de modificar NEW.campo Porque comando de triggering é executado antes. Tentativa gera erro ORA-04084. Pseudo-Registos NEW e OLD 5/7 Trigger BEFORE pode modificar NEW.campo Antes do comando INSERT / UPDATE do evento armazenar esse valor na tabela. Quando um comando DML faz disparar, simultaneamente, um trigger BEFORE e um trigger AFTER: Se o trigger BEFORE alterar NEW.campo então o trigger AFTER vê essa alteração. Nelson Freire (ISEP LEI-BDDAD 2017/18) 22/39
Pseudo-Registos NEW e OLD 6/7 Exemplo Trigger AFTER FOR EACH ROW Insere uma linha na tabela de logs LOG_EMPREGADOS depois de qualquer comando UPDATE afetar a coluna SALARIO da tabela EMPREGADOS Nelson Freire (ISEP LEI-BDDAD 2017/18) 23/39
Pseudo-Registos NEW e OLD 7/7 Exemplo - Trigger Condicional (com cláusula WHEN) Cria um trigger que: Imprime informação sobre atualizações na coluna SALARIO da tabela EMPREGADOS. Sempre que um comando UPDATE afeta a tabela EMPREGADOS. Exceto quando a informação é do Presidente. A BD avalia a condição WHEN para cada linha da tabela EMPREGADO afetada. Se TRUE: trigger é disparado antes da execução do comando de triggering. Senão: trigger não é disparado mas o comando de triggering continua a sua execução. Nelson Freire (ISEP LEI-BDDAD 2017/18) 24/39
Tratamento Diferenciado de Comandos de Triggering Requer Diretivas operacionais -- funções que retornam TRUE / FALSE. Directiva Operacional INSERTING UPDATING UPDATING('coluna') DELETING Retorna TRUE quando comando de triggering é INSERT UPDATE UPDATE que afeta a coluna especificada DELETE Evento do trigger com vários comandos DML Diretivas operacionais determinam o comando DML que disparou o trigger. Diretivas operacionais usadas em condições (expressões booleanas) Diretivas operacionais podem ser usadas em qualquer bloco PL/SQL. Contudo só são TRUE dentro de triggers ou código invocado dentro dum trigger DML Nelson Freire (ISEP LEI-BDDAD 2017/18) 25/39
Participação de Triggers em Transações Comandos DML Dentro dum Trigger Por omissão: Fazem parte da transação que originou o disparo do trigger. -- transação principal. i.e., trigger participa na transação principal. Consequência: Trigger quando termina com exceção não tratada: Provoca o ROLLBACK do comando que originou o disparo do trigger. Especificação de Instruções COMMIT/ROLLBACK Dentro do Trigger Apenas quando o trigger: É definido como transação autónoma. -- independente da transação principal. Exemplo Guarda informação de auditoria sobre tabela bonus_empregados: Instrução especifica que os comandos DML da ação do trigger constituem uma transação autónoma Não afeta transação principal Alteração da tabela é garantida. ROLLBACK da transação principal não afeta. Nelson Freire (ISEP LEI-BDDAD 2017/18) 26/39
Impede Leitura/escrita na tabela do evento de triggering. Justificação Tabela já está sendo alterada ( is mutating ) por comando DML (INSERT, UPDATE ou DELETE) que fez o trigger disparar. Exemplo Limitação Mutating Table em Triggers de Linha 1/3 Trigger de linha sobre tabela. Consulta da tabela que está sendo alterada por comando DML que fez o trigger disparar. Comando DML faz o trigger disparar e surge um erro... Trigger compilado sem erros. erro ORA-4091 Mutating Table Nelson Freire (ISEP LEI-BDDAD 2017/18) 27/39
Limitação Mutating Table em Triggers de Linha 2/3 Consequência 1. Rolled Back Trigger Comando de triggering 2. Controlo da Execução Retorna à aplicação que mandou executar o comando de triggering. Exemplo Trigger é rolled back. Comando de triggering é rolled back. Erro ORA-4091 Mutating Table Nelson Freire (ISEP LEI-BDDAD 2017/18) 28/39
Evitar o Erro Limitação Mutating Table em Triggers de Linha 3/3 Exemplo - Trigger AFTER EACH ROW para UPDATE da Mutating Table Alternativas: Usar uma tabela temporária. Usar um trigger DML composto. -- compound DML trigger Usar uma tabela temporária. Usar 2 triggers: Trigger de Linha Trigger de tabela / instrução Trigger de linha Trigger AFTER EACH ROW -- executado antes de triggers AFTER Atualiza a tabela temporária. Trigger de tabela / instrução Trigger AFTER Atualiza a mutating table com os valores da tabela temporária. Nelson Freire (ISEP LEI-BDDAD 2017/18) 29/39
Exemplo - Verificação de Restrição Complexa 1/3 Restrição empregados.salario [categorias.salario_min, categorias.salario_max] -- envolve 2 tabelas. Implementação Impossível com CONSTRAINT CHECK Limitada a colunas da mesma tabela. Possível com TRIGGER Faz a validação do salario Se inválido impede a execução de comandos INSERT / UPDATE Nelson Freire (ISEP LEI-BDDAD 2017/18) 30/39
Exemplo - Verificação de Restrição Complexa 2/3 Exceção própria (definida pelo programador) Obtém os salários, mínimo e máximo, do novo empregado ou da nova categoria do empregado. Lança exceção quando o novo salário é inválido Código do erro: inteiro [-20000, -20999] Procedimento (DBMS_STANDARD) Lança exceção própria e retorna código do erro e mensagem de erro. Comando INSERT/UPDATE pendente que disparou o trigger é ROLLED BACK. Nelson Freire (ISEP LEI-BDDAD 2017/18) 31/39
Exemplo - Verificação de Restrição Complexa 3/3 Comando DML impedido de executar, por ação do trigger. Salário inválido (fora dos limites da categoria) Exceção lançada pelo trigger provoca o ROLLED BACK do INSERT. Código de erro e mensagem de erro retornados por RAISE_APPLICATION _ERROR Nelson Freire (ISEP LEI-BDDAD 2017/18) 32/39
Oracle PL/SQL - Triggers Aspetos Gerais Nelson Freire (ISEP LEI-BDDAD 2017/18) 33/39
Triggers Lista de Triggers Associados a uma Tabela SQL Developer Separador Triggers da Tabela selecionada. Exemplo: Tabela EMPREGADOS separador Nelson Freire (ISEP LEI-BDDAD 2017/18) 34/39
Triggers Múltiplos Triggers Definidos Para: Mesmo comando de triggering Sobre a mesma tabela Ordem de Disparo: 1. Triggers de Tabela BEFORE 2. Triggers de Linha BEFORE 3. Triggers de Linha AFTER 4. Triggers de Tabela AFTER Exemplo: Ordem de Disparo de Triggers 1. BEFORE 2. AFTER 1. CREATE TRIGGER trg_1 BEFORE UPDATE ON tabelax 2. CREATE TRIGGER trg_2 BEFORE UPDATE ON tabelax FOR EACH ROW 3. CREATE TRIGGER trg_3 AFTER UPDATE ON tabelax FOR EACH ROW 4. CREATE TRIGGER trg_4 AFTER UPDATE ON tabelax Mesmo comando Mesma tabela Quando um comando DML faz disparar, simultaneamente, um trigger BEFORE e um trigger AFTER: Se o trigger BEFORE alterar NEW.campo então o trigger AFTER vê essa alteração. Nelson Freire (ISEP LEI-BDDAD 2017/18) 35/39
Triggers Permitir/Impedir Triggers Comando CREATE TRIGGER Cria trigger no estado enable (permitido) -- por omissão Criar Trigger Inibido Especificar a cláusula DISABLE Trigger de linha: FOR EACH ROW DISABLE [WHEN(condição)] Trigger de Tabela: Evento de triggering [REFERENCING ] DISABLE Interesse Permitir apenas triggers sem erros de compilação. Algumas Razões para Impedir Temporariamente um Trigger Trigger tem referência de um objeto indisponível. Necessidade de carregar rapidamente grandes quantidades de dados. Disparos de triggers consomem tempo de CPU. invocação permitida invocação impedida Comando para Impedir / Permitir Um trigger: ALTER TRIGGER [nome_esquema.] nome_trigger { ENABLE DISABLE } ; Todos os triggers sobre uma tabela específica ALTER TABLE nome_tabela { ENABLE DISABLE } ALL TRIGGERS ; Nelson Freire (ISEP LEI-BDDAD 2017/18) 36/39
Triggers Eliminar Trigger Comando DROP TRIGGER Sintaxe Exemplo DROP TRIGGER nome_trigger; Alternativa no SQL Developer Nelson Freire (ISEP LEI-BDDAD 2017/18) 37/39
Triggers Limitação do Tamanho de um Trigger Tamanho Máximo de um Trigger 32K bytes Recomendação Oracle Para lógica com mais de 60 linhas de código PL/SQL: Criar subprogramas (funções e procedimentos). Invocar esses subprogramas. Nelson Freire (ISEP LEI-BDDAD 2017/18) 38/39
Triggers Uso de Triggers Muito Cuidadoso Apenas: Quando necessário. Uso excessivo: Pode resultar em interdependências complexas. -- triggers em cascata. Dificulta a manutenção de grandes aplicações. Nelson Freire (ISEP LEI-BDDAD 2017/18) 39/39