Você está na página 1de 13

28/03/2016

Introduo
O que PLSQL?
a linguagem procedural do SGBD Oracle
uma extenso do SQL
Banco de Dados II Mistura linguagem de programao com SQL

Prof Elyda Laisa Outros SGBD tambm possuem linguagens


Aula 07 PLSQL procedurais
Mas, ao contrrio da SQL, no h um padro

Introduo
Permite criar programas que ficaro
armazenados no banco de dados e que podem
ser acessados por quaisquer aplicaes

PLSQL

Estrutura Estrutura
A estrutura bsica de um programa PLSQL a Um primeiro programa:
seguinte: SET SERVEROUTPUT ON

DECLARE
v_width INTEGER;
v_height INTEGER := 2;
v_area INTEGER := 6;
Os blocos
BEGIN
entre [] so -- configura a largura igual rea dividida pela altura
opcionais v_width := v_area / v_height;
DBMS_OUTPUT.PUT_LINE('v_width = ' || v_width);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Division by zero');
END;

1
28/03/2016

Estrutura Estrutura Hello World


Os blocos PLSQL podem ser:
Blocos annimos: construdos dinamicamente Este um bloco annimo no rotulado
e executados apenas uma vez. Podem ou no
ter um rtulo Permite exibir dados na tela
Subprogramas: consistem em procedures e
funes. Podem ser armazenados no banco de SET SERVEROUTPUT ON
dados como objetos independentes, como begin
parte de um pacote ou como mtodos de um
tipo de objeto
DBMS_OUTPUT.PUT_LINE('Teste de pl/sql!!!');
end;
Triggers: consistem em um bloco PL/SQL que
est associado a um evento que ocorre no
banco de dados Pacote de sada de dados

7 8

Estrutura Hello World Estrutura Hello World


Nome da procedure
Este um bloco annimo rotulado Este um subprograma (PROCEDURE)

Nome do bloco CREATE OR REPLACE PROCEDURE HELLOWORLD


AS
begin
SET SERVEROUTPUT ON DBMS_OUTPUT.PUT_LINE('Teste de pl/sql!!!');
<<PrimeiroPrograma>> end;
begin
DBMS_OUTPUT.PUT_LINE('Teste de pl/sql!!!'); Para execut-la:
end PrimeiroPrograma;
BEGIN
HELLOWORLD;
9 END; 10

Estrutura Hello World Estrutura


Nome da function
Este um subprograma (FUNCTION) Podemos utilizar quaisquer tipos de blocos
CREATE OR REPLACE FUNCTION FHELLOWORLD RETURN BOOLEAN Mas se quisermos armazen-los, devemos utilizar
IS subprogramas (Procedures ou Functions)
BEGIN Tanto Procedures quanto Functions podem
DBMS_OUTPUT.PUT_LINE('HELLO WORLD');
RETURN TRUE;
possuir argumentos
END;

Para execut-la: DECLARE


RetVal BOOLEAN;
BEGIN
RetVal := OE.FHELLOWORLD;
COMMIT;
END; 11 12

2
28/03/2016

Variveis e Tipos
Declarao de Varivel:

Nome_da_varivel [CONSTANT] datatype [NOT NULL]


[{:= | DEFAULT} valor];

Conhecendo as variveis e tipos


Onde nome_da_varivel o identificador,
datatype tipo e valor o contedo inicial da
VARIVEIS E TIPOS varivel
Os tipos de dados disponveis so basicamente os
tipos Oracle
14

Variveis e Tipos Variveis e Tipos


Declarao de Varivel: Outros tipos podem ser citados:
Alguns exemplos: TYPE: representa o tipo de uma coluna em uma
tabela
bonus NUMBER := 150;
country VARCHAR2(128); v_Nome EMPLOYEES.FIRST_NAME%TYPE;
counter NUMBER;
done BOOLEAN;

As declaraes de variveis so realizadas no ROWTYPE: representa uma linha da tabela no


bloco DECLARE banco de dados
linha_Empregado EMPLOYEES%ROWTYPE;

15 16

Variveis e Tipos Variveis e Tipos


Outros tipos podem ser citados (cont.): Outros tipos podem ser citados (cont.):
REGISTROS Semelhantes aos registros em C
CURSOR Armazenam o resultado completo de
uma consulta
TYPE reg_Empregado IS RECORD (
codigo NUMBER,
nome VARCHAR2(5) CURSOR c_Empregado IS
); SELECT FIRST_NAME, SALARY
FROM EMPLOYEES
WHERE MANAGER_ID = 100

17 18

3
28/03/2016

Variveis e Tipos Variveis e Tipos


Outros tipos podem ser citados (cont.): Outros tipos podem ser citados (cont.):
VARRAYS Armazenam um nmero fixo de
elementos NESTED TABLES Armazenam um nmero
dinmico de elementos
TYPE NumberList IS VARRAY(10) OF NUMBER(3) NOT NULL;
--Array de tuplas da tabela students
TYPE StudentList IS VARRAY(100) OF students%ROWTYPE; TYPE NumbersTab IS TABLE OF NUMBER;
--Nested Table de empregados
TYPE EmployeesTab IS TABLE OF employees%ROWTYPE;

19 20

Variveis e Tipos
Outra forma de atribuir um valor varivel
por meio do comando SELECT INTO:
DECLARE
v_Cargo EMPLOYEES.JOB_ID%TYPE;
BEGIN
SELECT JOB_ID
INTO v_Cargo
FROM EMPLOYEES
WHERE EMPLOYEE_ID = 108;
ESTRUTURAS DE CONTROLE
DBMS_OUTPUT.PUT_LINE(v_Cargo);
END;

21

Estruturas de Controle Estruturas de Deciso


Estruturas de Deciso: As estruturas de As estruturas IF-THEN-ELSE tm a seguinte
deciso podem ser do tipo IF-THEN-ELSE e sintaxe:
CASE
IF condicao THEN
Sequncia_de_instrues;
Estruturas de Repetio: As estruturas de ELSIF condicao THEN
repetio em PLSQL podem ser do tipo LOOP- Sequncia_de_instrues;
EXIT WHEN, WHILE e FOR ELSE
Sequncia_de_instrues;
END IF;

23 24

4
28/03/2016

Estruturas de Deciso Estruturas de Deciso


EXEMPLO IF-THEN-ELSE
Estruturas de deciso do tipo CASE tm a seguinte
DECLARE
sintaxe: v_Comissao EMPLOYEES.COMMISSION_PCT%TYPE;
CASE [expressao] BEGIN
SELECT COMMISSION_PCT
WHEN condicao_1 THEN INTO v_Comissao
Sequncia_de_instrues; FROM EMPLOYEES
WHEN condicao_2 THEN WHERE EMPLOYEE_ID = 108;
Sequncia_de_instrues;
... IF v_Comissao <= 0.1 THEN
DBMS_OUTPUT.PUT_LINE ('Baixo Custo');
WHEN condicao_n THEN ELSIF v_Comissao BETWEEN 0.2 AND 0.5 THEN
Sequncia_de_instrues; DBMS_OUTPUT.PUT_LINE ('Alto Custo');
ELSE ELSE
Sequncia_de_instrues; DBMS_OUTPUT.PUT_LINE ('Sem Comissao');
END CASE; END IF;
END;
26

DECLARE
v_Regiao COUNTRIES.REGION_ID%TYPE; Estruturas de Repetio
BEGIN
SELECT REGION_ID
Estruturas de Deciso INTO v_Regiao As estruturas do tipo LOOP-EXIT WHEN tm a seguinte
FROM COUNTRIES
WHERE COUNTRY_NAME = 'Egypt'; sintaxe:
EXEMPLO CASE CASE v_Regiao LOOP
WHEN 1 THEN
DBMS_OUTPUT.PUT_LINE ('Europe');
Sequncia_de_instrues
WHEN 2 THEN EXIT WHEN condio;
DBMS_OUTPUT.PUT_LINE ('Americas'); END LOOP
WHEN 3 THEN SET SERVEROUTPUT ON;
DBMS_OUTPUT.PUT_LINE ('Asia'); DECLARE
WHEN 4 THEN v_counter INTEGER := 0;
DBMS_OUTPUT.PUT_LINE ('Middle East / BEGIN
Africa'); LOOP
ELSE v_counter := v_counter + 1;
DBMS_OUTPUT.PUT_LINE ('Sem Regiao'); EXIT WHEN v_counter = 5;
END CASE; END LOOP;
END; DBMS_OUTPUT.PUT_LINE(v_counter);
27 28
END;

Estruturas de Repetio EXEMPLO


LOOP-EXIT WHEN Estruturas de Repetio
DECLARE
total NUMBER := 0; As estruturas do tipo WHILE tm a seguinte sintaxe:
counter NUMBER := 0;
BEGIN WHILE condio LOOP
LOOP Sequncia_de_instrues;
counter := counter + 1; END LOOP;
total := total + counter * counter;
SET SERVEROUTPUT ON;
EXIT WHEN total > 25000;
DECLARE
END LOOP; v_counter INTEGER := 0;
DBMS_OUTPUT.PUT_LINE ('Contador: ' BEGIN
|| TO_CHAR(counter) WHILE v_counter < 5 LOOP
|| ' Total: ' v_counter := v_counter + 1;
|| TO_CHAR(total) END LOOP;
);
END; DBMS_OUTPUT.PUT_LINE(v_counter);
END;
29 30

5
28/03/2016

Estruturas de Repetio EXEMPLO WHILE


Estruturas de Repetio
DECLARE
sal employees.salary%TYPE := 0;
mgr_id employees.manager_id%TYPE;
lname employees.last_name%TYPE; J as estruturas do tipo FOR tm a seguinte sintaxe:
emp number :=100;
BEGIN FOR contador IN [REVERSE] limite_inferior .. limite_superior LOOP
WHILE emp <= 145 LOOP Seqncia_de_instrues;
SELECT salary, manager_id, last_name INTO sal, mgr_id, lname END LOOP;
FROM employees
WHERE employee_id = emp; SET SERVEROUTPUT ON;
BEGIN
IF sal < 10000 AND sal IS NOT NULL THEN FOR v_counter IN 1..5 LOOP
INSERT INTO temp VALUES (sal, lname); DBMS_OUTPUT.PUT_LINE(v_counter);
COMMIT; END LOOP;
END IF; END;

emp:=emp+1;
END LOOP;
31 32
END;

Estruturas de Repetio EXEMPLO FOR


Questes de Fixao
1. Faa um procedimento em PL/SQL que receba por parmetro
um nmero, e imprima na tela a tabuada completa
BEGIN
--no necessrio declarar v_counter 2. Criar um bloco PL/SQL para atualizar a tabela abaixo,
--ela ser automaticamente declarada conforme segue:
FOR v_Counter IN 1..50 LOOP Produtos categoria A devero ser reajustados em 5%
INSERT INTO temptb VALUES (v_Counter, 'Loop Index');
COMMIT; Produtos categoria B devero ser reajustados em 10%
END LOOP; Produtos categoria C devero ser reajustados em 15%
END;

33 34

Questes de Fixao Questes de Fixao


Crie um bloco PL/SQL que compute o valor da Crie um bloco PL/SQL que dever receber o nmero
comisso de um determinado funcionrio com base de matrcula de um funcionrio e retornar o seu
no salrio do funcionrio. Exiba tambm o salrio nome e o nome de seu departamento
total.

Crie um bloco PL/SQL que premie um funcionrio,


anexando um asterisco coluna STARS para cada US$
100 do salrio do funcionrio.

6
28/03/2016

Excees
Voltando estrutura dos blocos PLSQL:

TRATANDO EXCEES

38

Excees
Excees H diversos erros pr-definidos, entre os quais:

Os erros em PLSQL podem ser de dois tipo:


De compilao: O compilador informa os
erros e voc tem de corrigi-los.

De execuo: as excees so levantadas e


capturadas pelos handlers de exceo.
Veremos como corrigir erros pr-definidos
E como criar nossas prprias excees

39 40

Excees Excees
Para trat-las devemos seguir esta sintaxe: Exemplo:
DECLARE
EXCEPTION sal employees.salary%TYPE := 0;
WHEN nome_da_exceo THEN mgr_id employees.manager_id%TYPE;
lname employees.last_name%TYPE;
Seqncia_de_instrues1;
BEGIN
WHEN nome_da_exceo THEN SELECT salary, manager_id, last_name INTO sal, mgr_id, lname
Seqncia_de_instrues2; FROM employees;
WHEN OTHERS THEN EXCEPTION
Seqncia_de_instrues3; WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN
END; INSERT INTO log_table VALUES ('A insert erro occurred',
SYSDATE);
COMMIT;
41
END; 42

7
28/03/2016

CREATE OR REPLACE PROCEDURE award_bonus


(emp_id NUMBER, bonus NUMBER) AS
commission REAL; comm_missing EXCEPTION;
BEGIN
SELECT commission_pct / 100 INTO commission
FROM employees
Excees WHERE employee_id = emp_id;

Podemos IF commission IS NULL THEN


RAISE comm_missing;
tambm ELSE
criar UPDATE employees
SET salary = salary + bonus*commission
nossas WHERE employee_id = emp_id; Subprogramas em detalhes
prprias END IF;

excees:
EXCEPTION
WHEN comm_missing THEN
PROCEDURES E FUNCTIONS
DBMS_OUTPUT.PUT_LINE (Employee doesnt
receive comm');
commission := 0;
WHEN OTHERS THEN
43 44
NULL; END award_bonus;

Procedures
Procedures
Modo Descrio
Uma procedure no possui valor de retorno O valor do parmetro real passado para a procedure quando ela
IN invocada. Dentro da procedure, o parmetro formal atua como uma
Para declar-la, utiliza-se a seguinte sintaxe: constante PL/SQL - ele considerado de leitura e no pode ser alterado.

CREATE [OR REPLACE] PROCEDURE nome_de_procedure


OUT Qualquer valor que o parmetro real tenha ignorado quando a
[(argumento [{IN | OUT| IN OUT}] tipo)] {IS | AS}
procedure chamada. Dentro da procedure, o parmetro formal atua
como uma varivel no inicializada PL/SQL e, portanto tem um valor
NULL. Ele pode ser lido e escrito.
Os tipos de argumentos tanto de procedures
quanto functions podem ser IN, OUT ou IN IN Combina IN e OUT. O valor do parmetro real passado para a
OUT OUT procedure quando a procedure invocada. Dentro da procedure, o
parmetro formal atua como uma varivel inicializada e poder ser lido e
gravado. Quando a procedure conclui e o controle retorna ao ambiente
Se no for especificado, o valor padro IN de chamada, o contedo do parmetro formal atribudo ao parmetro
45 real. 46

Procedures Procedures
Embora seja interessante, no recomendado Exemplo de procedure:
que uma procedure possua argumentos do
tipo OUT CREATE OR REPLACE PROCEDURE NOVO_PERIODO
(P_COD_PERIODO IN NUMBER,
P_DATA_INCIAL IN DATE,
P_DATA_FINAL IN DATE)
IS
BEGIN
INSERT INTO PERIODO_LETIVO VALUES(P_COD_PERIODO,
P_DATA_INCIAL, P_DATA_FINAL);
END;

47 48

8
28/03/2016

Fixao Functions
Crie um procedure que receba como As funes tm obrigatoriamente valor de
parmetro o cdigo de um produto e o valor e retorno
verifique se o produto existe A sintaxe de declarao a seguinte:
Em caso positivo, a procedure deve atualizar o
preo do produto, multiplicando-o pelo valor. CREATE [OR REPLACE] FUNCTION nome_de_funo
A atualizao ser feita na tabela de produtos [(argumento [{IN | OUT| IN OUT}] tipo)] ,
...
Lembre-se que para chamar uma stored argumento [{IN | OUT| IN OUT}] tipo)]
procedure o seguinte comando deve ser RETURN tipo_de_retorno {IS |AS}
executado: corpo_da_funo
BEGIN
nome_procedure (args);
50
END;

Fixao Functions
Crie uma funo que receba como parmetro Exemplo de Function:
o raio e retorne a rea do crculo CREATE OR REPLACE FUNCTION salario
(v_empno in employees.employee_id%type)
RETURN number
IS
v_emp_sal employees.salary%type := 0;
BEGIN
SELECT salary INTO v_emp_sal
FROM employees
WHERE employee_id = v_empno;
RETURN (v_emp_sal);
END salario;

52

Record
uma estrutura de dados heterognea:
DECLARE
TYPE tipo_regEmpregado IS RECORD (
codigo NUMBER,
nome VARCHAR2(50));
reg_Empregado tipo_regEmpregado;

BEGIN
SELECT employee_id, first_name
INTO reg_Empregado.codigo, reg_Empregado.nome
UTILIZANDO TIPOS NO FROM employees
WHERE employee_id = 100;
PRIMITIVOS DBMS_OUTPUT.PUT_LINE (reg_Empregado.codigo);
DBMS_OUTPUT.PUT_LINE (reg_Empregado.nome);
END;
53 54

9
28/03/2016

Varrays
Record
O Record tambm pode ser declarado com Armazenam uma quantidade pr-
%ROWTYPE: determinada de elementos
CREATE OR REPLACE PROCEDURE process_employee Um exemplo simples:
IS
rec_employee employees%ROWTYPE;
DECLARE
BEGIN
TYPE ARRAY_T IS VARRAY(3) OF VARCHAR2(10);
SELECT *
ARRAY ARRAY_T := ARRAY_T('MATT', 'JOANNE', 'ROBERT');
INTO rec_employee
BEGIN
FROM employees
FOR i IN 1..ARRAY.COUNT LOOP
WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(ARRAY(i));
DBMS_OUTPUT.PUT_LINE (rec_employee.employee_id);
END LOOP;
DBMS_OUTPUT.PUT_LINE (rec_employee.last_name);
END;
DBMS_OUTPUT.PUT_LINE (rec_employee.salary);
END; 55 56

CREATE OR REPLACE PROCEDURE PROCESS_EMPLOYEE


IS
Varrays
TYPE TREC_EMPLOYEE IS RECORD (codigo NUMBER, Nested Table
nome VARCHAR2(50));
Mais TYPE TARR_EMP IS VARRAY(2) OF TREC_EMPLOYEE;
Armazenam elementos sem necessidade de
ARR_EMP TARR_EMP;
um BEGIN determinar previamente seu tamanho
ARR_EMP:=TARR_EMP(null,null) ;
exemplo: SELECT EMPLOYEE_ID, FIRST_NAME
INTO ARR_EMP(1)
FROM EMPLOYEES DECLARE
WHERE EMPLOYEE_ID = 100; TYPE NumbersTab IS TABLE OF NUMBER;
v_Numbers NumbersTab := NumbersTab(1, 2, 3);
SELECT EMPLOYEE_ID, FIRST_NAME BEGIN
INTO ARR_EMP(2)
FROM EMPLOYEES
v_Numbers(1) := 7;
WHERE EMPLOYEE_ID = 101; v_Numbers(2) := -1;
END;
FOR i IN ARR_EMP.FIRST .. ARR_EMP.LAST LOOP
DBMS_OUTPUT.PUT_LINE (ARR_EMP(i).codigo);
DBMS_OUTPUT.PUT_LINE (ARR_EMP(i).nome);
57 58
END LOOP; END;

Nested Table
Cursor
Outro exemplo:
DECLARE J sabemos como declarar um cursor:
TYPE TYP_REC IS RECORD ( CURSOR c_Empregado IS
ID_NUMBER VARCHAR2(50), SELECT FIRST_NAME, SALARY
FROM EMPLOYEES
DESCRIPTION VARCHAR2(50)); WHERE MANAGER_ID = 100
TYPE TYP_NTAB IS TABLE OF TYP_REC;
NTAB TYP_NTAB := TYP_NTAB(); Agora veremos como manipul-los
So trs etapas: OPEN, FETCH e CLOSE
BEGIN Para inicializar o cursor utiliza-se a instruo OPEN, que
FOR I IN 1..10 LOOP identifica o conjunto de resultados
NTAB.EXTEND; Em seguida, executa-se o FETCH repetidamente at que
NTAB(I).ID_NUMBER:='ID NUMBER #'||I; todas as linhas tenham sido recuperadas (ou o BULK
NTAB(I).DESCRIPTION:='TEST CASE '||I; COLLECT para buscar todas as linhas de uma s vez)
DBMS_OUTPUT.PUT_LINE(NTAB(I).ID_NUMBER|| Quando a ltima linha tiver sido processada, deve-se
' '||NTAB(I).DESCRIPTION); liberar o cursor com a instruo CLOSE
59 60
END LOOP; END;

10
28/03/2016

Cursor - OPEN, FETCH e CLOSE


Fixao
DECLARE Crie um cursor para exibir as colunas
my_sal employees.salary%TYPE;
factor INTEGER := 2;
PRODUCT_ID, PRODUCT_NAME e MIN_PRICE
CURSOR c1 IS da tabela PRODUCT_INFORMATION no
SELECT factor*salary FROM employees WHERE job_id = 'IT_PROG';
BEGIN schema OE
OPEN c1; -- factor initially equals 2
LOOP
FETCH c1 INTO my_sal; -- Podemos ter mais de uma coluna
DBMS_OUTPUT.PUT_LINE(my_sal);
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END;

61

Cursor - FOR Fixao


O comando for substitui os comandos OPEN, FETCH e CLOSE: Crie um cursor que exiba os salrios dos
funcionrios com acrscimo de 10%
DECLARE
CURSOR c_customers is Use o cursor com FOR
SELECT cust_first_name FROM customers;
counter integer :=0;
BEGIN
FOR n IN c_customers LOOP
counter := counter +1;
dbms_output.put_line('Customer('||counter||'):
||n.cust_first_name);
END LOOP;
END; 63

Questes de Fixao
1. Criar uma procedure que dever receber o cdigo
de um empregado e a partir deste dado imprimir
o seu nome, e-mail e nome do departamento.

2. Crie uma Procedure que verifique o status dos


clientes cujos cdigos esto entre 213 e 250.
Armazene em uma tabela a quantidade de clientes
gold, Silver e Platinum
Utilize o usurio OE
TRIGGERS
3. Calcule e exiba em tela o valor total, com desconto,
de cada pedido da tabela ORDER_ITENS
65

11
28/03/2016

Triggers Triggers
Trigger uma procedure executada (ou H dois tipos de triggers
disparada) automaticamente pelo banco de Triggers de linha: o cdigo do trigger pode ser
dados quando uma instruo DML executado uma vez para cada linha afetada
executada Este tipo de trigger tem acesso a valores novos e
antigos de uma coluna
So teis em vrias ocasies
Triggers de instruo: executada uma vez para
todas as linhas
Um trigger pode ser disparado antes ou
depois de uma instruo DML

Triggers Triggers
Detalhando:
Sintaxe da trigger BEFORE | AFTER: a trigger disparada antes/depois do
evento_trigger; INSTEAD OF: a trigger disparada no lugar do
CREATE [OR REPLACE] TRIGGER nome_trigger
evento_trigger; FOR: permite criar um trigger composto
{BEFORE | AFTER | INSTEAD OF | FOR} evento_trigger Evento_trigger: o evento que dispara a trigger
ON nome_tabela FOR EACH ROW: identifica um trigger de linha
[FOR EACH ROW]
[{ FORWARD | REVERSE} CROSSEDITION ]
FORWARD | REVERSE CROSSEDITION: identifica o momento
[{FOLLOWS | PRECEDES } esquema.outro_trigger] de executar a trigger durante ou depois uma atualizao de
[{ENABLE | DISABLE}] patch
[WHEN condiao_trigger] FOLLOWS | PRECEDES: especifica se a trigger vem depois ou
BEGIN antes de outra
corpo_trigger; ENABLE |DISABLE: identifica se a trigger inicialmente
END nome_trigger;
habilitada ou no
Condicao_trigger: condio booleana que identifica quando a
trigger executa seu cdigo

Triggers Triggers
DROP TRIGGER STORE.BEFORE_PRODUCT_PRICE_UPDATE;
Exemplo:
CREATE OR REPLACE TRIGGER STORE.before_product_price_update
BEFORE UPDATE OF price
ON STORE.PRODUCTS FOR EACH ROW
WHEN (
CREATE OR REPLACE TRIGGER AJUSTE_ADMINISTRADOR
new.price < old.price * 0.75
BEFORE UPDATE OF LOGIN ON TB_ADMINISTRADOR
)
BEGIN
BEGIN
RAISE_APPLICATION_ERROR (-20096, 'Nao e possivel alterar o nome
dbms_output.put_line('product_id = ' || :old.product_id);
de um usuario ja cadastrado');
dbms_output.put_line('Old price = ' || :old.price);
END;
dbms_output.put_line('New price = ' || :new.price);
dbms_output.put_line('The price reduction is more than 25%');

-- insert row into the product_price_audit table


INSERT INTO product_price_audit ( product_id, old_price, new_price )
VALUES ( :old.product_id, :old.price, :new.price );
END before_product_price_update;
/

12
28/03/2016

Triggers Triggers
A trigger anterior disparada caso um Crie uma trigger que funcione como um log,
produto tenha uma diminuio em mais de armazenando os seguintes dados em uma
25% nova tabela chamada log:
Para cada insero, alterao e deleo de um
funcionrio: um ID, a data e hora atual, o valor
anterior, o tipo de ao (CUD)

Resposta no prximo slide

CREATE OR REPLACE TRIGGER LOG_VIDEOS AFTER INSERT OR UPDATE OR DELETE


ON TB_VIDEO FOR EACH ROW
Trigger
BEGIN
IF(INSERTING) THEN
INSERT INTO TB_LOG ( NID_LOG, DDATA_HORA, VVALOR_ANTERIOR, VACAO,
EDITOR)
VALUES (SEQ_LOG_ID.NEXTVAL, SYSDATE, NULL , 'CADASTRO', :NEW.EDITOR );

ELSIF (UPDATING) THEN


INSERT INTO TB_LOG ( NID_LOG, DDATA_HORA, VVALOR_ANTERIOR, VACAO,
EDITOR)
VALUES (SEQ_LOG_ID.NEXTVAL, SYSDATE, SUBSTR ('TIT: ' || :OLD.VTITULO || '.
DESC: ' || :OLD.VDESCRICAO || '. VER: ' || :OLD.NVERSAO || '. DUR: '
||:OLD.NDURACAO, 1, 254), 'ATUALIZACAO', :NEW.EDITOR);

ELSIF (DELETING) THEN


INSERT INTO TB_LOG ( NID_LOG, DDATA_HORA, VVALOR_ANTERIOR, VACAO,
EDITOR)
VALUES (SEQ_LOG_ID.NEXTVAL, SYSDATE, SUBSTR ('TIT: ' || :OLD.VTITULO || '.
DESC: ' || :OLD.VDESCRICAO || '. VER: ' || :OLD.NVERSAO || '. DUR: '
||:OLD.NDURACAO, 1, 254), 'EXCLUSAO', :NEW.EDITOR);
END IF;
END;

13