You are on page 1of 5

Aula 3 de PL SQL (11/08/12)

Procedimento armazenado
um programa similar a uma funo.

A explicao da aula comparada com a resoluo do exerccio Aula 7. Ento ser percebida a diferena entre funo e procedimento.

Funo X Procedimento Neste exemplo, vamos comparar a soluo da Aula7 feita para funo e ver a mesma soluo em procedimento armazenado: -- Resoluo por funo:
create or replace function func_relat_emp (p_id number) return number is v_nome_dep c_depto.nome%type; v_qtd number(10);

cursor c_empreg (P_dep number) is select id, prim_nome|| ' ' || ult_nome as nome_emp from c_empr where id_Depto = p_dep; begin select nome into v_nome_dep from c_depto where id = p_id; for r_emp in c_empreg(p_id) loop

insert into emp_relatorio values (r_emp.id, r_emp.nome_emp, v_nome_dep); v_qtd := c_empreg%rowcount; end loop; commit;

return v_qtd;

end;

-- Resoluo por Procedimento:


In entrada (pode ser omitido),
create or replace procedure proc_emp_relat

Out - sada
( p_dep in number, p_qtd out number) -- observe que alem do paramentro ( p_dep) de entrada por ser um -- existe um parametro de sada ( p_qtd). as cursor c_relat_emp (p_depto in number) is select e.id, e.prim_nome || ' ' || e.ult_nome as emp_nome, d.nome procedimento

from c_empr e inner join c_depto D on e.id_depto = d.id where e.id_depto = p_depto;

Fez join s p ficar diferente da questo anterior.

-----

no cursor do procedimento se fez a opo de realizar a juno com c_depto para pegar o nome do departamento, repare que na funo o nome do departamento foi obtido na consulta select into. Qualquer das duas solues pode ser utilizada.

begin for r_emp in c_relat_emp(p_dep) loop insert into emp_relatorio values (r_emp.id, r_emp.emp_nome, r_emp.nome); p_qtd := c_relat_emp%rowcount; -- observe a atribuio do valor ao paramentro de saida e a ausencia -- do comando return. end loop; end;

Procedimento, quando for executado, vai at o fim, mesmo que encontre um exit ou break no meio do cdigo.

-- Exemplo de cdigo chamador -- Obs neste exemplo o modulo chamador alem de chamar a rotina proc_emp_relat,aps a execuo da mesmo insere na tabela emp_Relatorio o valor retornado pela rotina (v_qtd e a msg que este foi o valor retornado.

declare v_qtd number(8);

Em linha de cdigo JAVA, a chamada de um procedimento em PL/SQL :


Call <procedimento>

begin

proc_emp_relat(41,v_qtd); insert into emp_relatorio values (v_qtd, 'valor', 'voltou procedure'); end;

-- Verificao do que foi inserido na tabela emp_relatorio

select * from emp_Relatorio

Gatilho
uma sub-rotina q executada automaticamente de acordo com uma determinada situao. Existem gatilhos de 2 tipos: DML (Reagem a Insert, Update e Delete) Eventos de BD (Ex: Shutdown, login, etc..)

Trabalharemos apenas com o gatilho DML. Estes gatilhos podem ser AFTER ou BEFORE, ou ainda, INSTEAD OF: AFTER: Primeiro ele faz o comando DML e depois faz a lgica do gatilho

BEFORE: Primeiro ele faz a lgica do gatilho, e depois o comando DML.

INSTEAD OF: Ao receber um comando DML, ele o substitui pelo gatilho. Este gatilho permite, por exemplo, atualizar ou inserir dados em uma viso originada de 2 tabelas com Join.

Dentro de gatilho no pode ter controle de transao (COMIT e ROLLBACK). Os gatilhos podem ser em nvel de LINHA ou de COMANDO. Ex: Preciso fazer um gatilho que atue na atualizao de 10 linhas de uma tabela. Se resolvido com gatilho de LINHA: Este gatilho ser executado 10 vezes, 1 para cada linha. Se resolvido com COMANDO: Este gatilho ser executado 1 vez, e far a atualizao das 10 linhas da tabela.

Uma das maiores necessidades de utilizao de gatilhos manter os dados derivados atualizados. Ex: Idade, Clculo de saldo de Conta Corrente.

-Fazer um gatilho na tabela movimento que dispare ao ser inserido um novo registro na tabela e atualize a saldo da conta corrente do cliente na tabela conta_corrente. Para realizar o trabalho, crie as tabelas abaixo e popule a tabela de conta corrente utilizando os comandos abaixo
create table conta_corrente (nr number(6) primary key, nome varchar2(40), CPF char(11), saldo number(11,2));

Create table mov_cc (nr number(9) primary key, nr_cc number(6) references conta_corrente(nr), tipo char(1) not null, valor number(11,2)); insert insert insert insert insert insert into into into into into into conta_corrente conta_corrente conta_corrente conta_corrente conta_corrente conta_corrente values(101,'Carlos Rodrigues','12345678901',1020.45); values(111,'Jose Antonio Silva','67890154368',2045); values(121,'Carla Santos' ,'45698712345',3120.89); values(131,'Roberto Leito','12345678901',120); values(141,'Alberto Cesar','12345678901',2110.20); values(151,'Caio Domingues','12345678901',1000);

Soluo
create or replace trigger ins_mov_cc before insert on mov_cc for each row

Antes do INSERT Para cada linha (se omitido, vira gatilho de comando)

begin if upper(:new.tipo) = 'C' then update conta_corrente set saldo = saldo + :new.valor where nr = :new.nr_cc; elsif upper(:new.tipo) = 'D' then update conta_corrente set saldo = saldo - :new.valor where nr = :new.nr_cc; else raise_application_error (-20001, 'tipo nao valido'); end if; end;

Caso precise declarar variveis, cria-se aqui um declare para isso


:new

um registro com o valor novo da linha da tabela.

:old

Chamada de um erro, pois ocorreu uma aplicao que no Crdito (C) nem dbito (D). O -20001 indica erro de usurio. At 2000 so erros prprios do Oracle.

um registro com o valor antigo na tabela (que foi sobrescrito pelo novo)

insert into MOV_CC values (1,151,'C',1000)

select * from conta_corrente

Observe acima que o saldo da conta 151 foi atualizado pelo gatilho. Mais um exemplo:
insert into MOV_CC values (2,111,'D',2000)

O saldo da conta 111 foi atualizado pelo gatilho. (Esqueci de mostrar isso no print. Faltou repetir o select. O valor de saldo da conta 111 ficou em R$45,00).