Você está na página 1de 10

Procedures e Funes em PL/SQL

Procedures

Uma procedure nada mais do um bloco PL/SQL nomeado. A grande vantagem


sobre um bloco PL/SQL annimo que pode ser compilado e armazenado no banco de
dados como um objeto de schema. Graas a essa caracterstica as procedures so de
fcil manuteno, o cdigo reutilizvel e permitem que trabalhemos com mdulos de
programa.
Uma procedure , ento, um bloco PL/SQL nomeado que pode aceitar
argumentos (tambm chamado de parmetros) e pode ser chamada por um programa,
uma sesso SQL ou uma trigger.
Durante a instalao do banco de dados Oracle um script executado
automaticamente e cria toda a estrutura necessria para que as procedures sejam
executadas. Eventualmente esse procedimento automtico pode falhar devido a
alguma falha fsica no disco rgido, nesse caso o usurio SYS pode recriar a estrutura
atravs do script SQL DBMSSTDX.SQL.
Para criar uma procedure o usurio precisa ter o privilgio de sistema CREATE
PROCEDURE, para criar a procedure em outros schemas o usurio deve ter o
privilgio de CREATE ANY PROCEDURE. Este um ponto muito interessante sobre
as procedures, os privilgios para criao de procedures tm que ser concedidos
explicitamente, ou seja, no pode ser adquirido atravs de roles.
Para executar uma procedure externa necessrio ter o privilgio de EXECUTE. Caso
queira alterar a procedure de outro schema deve ter o privilgio de sistema ALTER
ANY PROCEDURE.
A sintaxe bsica de uma procedure :

CREATE [OR REPLACE] PROCEDURE [schema.]nome_da_procedure


[(parmetro1 [modo1] tipodedado1,
parmetro2 [modo2] tipodedado2,
...)]
IS|AS
Bloco PL/SQL

Onde:

REPLACE indica que caso a procedure exista ela ser eliminada e


substituda pela nova verso criada pelo comando;

BLOCO PL/SQL inicia com uma clusula BEGIN e termina com END
ou END nome_da_procedure;

NOME_DA_PROCEDURE indica o nome da procedure;

PARMETRO indica o nome da varivel PL/SQL que passada na


chamada da procedure ou o nome da varivel que retornar os valores
da procedure ou ambos. O que ir conter em parmetro depende de
MODO;

MODO Indica que o parmetro de entrada (IN), sada (OUT) ou


ambos (IN OUT). importante notar que IN o modo default, ou seja,
se no dissermos nada o modo do nosso parmetro ser,
automaticamente, IN;

TIPODEDADO indica o tipo de dado do parmetro. Pode ser


qualquer tipo de dado do SQL ou do PL/SQL. Pode usar referencias
como %TYPE, %ROWTYPE ou qualquer tipo de dado escalar ou
composto. Ateno: no possvel fazer qualquer restrio ao
tamanho do tipo de dado neste ponto.

IS|AS a sintaxe do comando aceita tanto IS como AS. Por


conveno usamos IS na criao de procedures e AS quando
estivermos criando pacotes.

BLOCO PL/SQL indica as aes que sero executadas por aquela


procedure.

Exemplo de procedure:
CREATE OR REPLACE PROCEDURE Aumenta_Salario
FUNCIONARIO.Cd_Funcionario%TYPE) IS
BEGIN
UPDATE
FUNCIONARIO
SET
Cd_Salario = Cd_Salario * 1.10
WHERE
Cd_Funcionario = F_Cd_Funcionario;
END Aumenta_Salario;

(F_Cd_Funcionario

IN

Neste exemplo estamos criando uma procedure para aumentar o salrio de um


funcionrio em 10%. A primeira linha define o NOME DA PROCEDURE, que vai ser
AUMENTA_SAL.
A linha dois define o parmetro P_EMPNO no modo IN. Ou seja, vai ser um
dado informado na chamada da procedure. Em seguida determinamos que ele ser do
mesmo tipo e tamanho que a coluna EMPNO da tabela EMP. Isso feito atravs da
referncia EMP.EMPNO%TYPE.
Podemos verificar o estado de nossa procedure atravs de uma simples
consulta:
SELECT object_name, status
FROM user_objects
WHERE object_name LIKE '%AUMENTA%';

Agora podemos verificar o funcionamento de nossa procedure:


SELECT Cd_Funcionario, Cd_Salario from FUNCIONARIO;
FUNC

SAL

---------- ---------001

10000

002

6000

003

4000

CALL AUMENTA_SAL(001);

Ou
EXECUTE AUMENTA_SAL(001);
SELECT Cd_Funcionario, Cd_Salario from FUNCIONARIO;
EMPNO

SAL

---------- ---------001

11000

002

6000

003

4000

Podemos notar que o salrio do funcionrio 001 aumentou em 10%.

Funes

Sintaxe Bsica:
CREATE [OR REPLACE] FUNCTION nome_da_funo
[( parameter1 [ mode1] datatype1,
parameter2 [ mode2] datatype2,
. . .)]
RETURN tipo_de_dado
IS|AS
Bloco PL/SQL;

Ao contrrio das procedures as funes tem que retornar ao menos um valor.


CREATE

OR

REPLACE

FUNCTION

FUNCIONARIO.Cd_Funcionario%TYPE)

Get_Salario(F_Cd_Funcionario
RETURN

FUNCIONARIO.Cd_Salario%TYPE;
BEGIN
SELECT Cd_Salario
INTO valor_salario
FROM FUNCIONARIO
WHERE Cd_Funcionario = F_Cd_Funcionario;
RETURN valor_salario;
END Get_Salario;

Executando
VARIABLE Get_Sal NUMBER;
EXECUTE :Get_Sal := Get_Salario('001');
PRINT Get_Sal;

NUMBER

IS

IN

valor_salario

SQL
Gatilho (Trigger)
Apesar de Trigger SQL serem muito teis, no aconselhvel a utilizao deste
tipo de instruo, pelo fato de prejudicar a performance. A trigger um tipo de
procedure que executada automaticamente aps uma ao especifica que ocorre em
uma tabela ou view (por isso prejudica a performance).
Definio um bloco PL/SQL que disparado de forma automtica e implcita
sempre que ocorrer um evento associado a uma tabela:
INSERT
UPDATE
DELETE
No pode ser chamado explicitamente.
Utilidades
Manuteno de tabelas de auditoria, manuteno de tabelas duplicatas,
implementao de nveis de segurana mais complexos, gerao de valores de
colunas referentes a atributos derivados, validao de restries de integridade mais
complexas que as suportadas diretamente pelo SGBD.
Estrutura
CREATE OR REPLACE TRIGGER nome_gatilho
BEFORE | AFTER
DELETE OR INSERT OR UPDATE OF coluna1, coluna2, ...
ON nome_da_tabela / view
REFERENCING OLD AS nome NEW AS nome
FOR EACH ROW
WHEN condio
DECLARE
rea de declarao
BEGIN
rea de comandos
END;

Clusulas

Tempo
o BEFORE: antes do evento
o AFTER: depois do evento
O gatilho somente ser
Eventos de disparo
disparado se alguma coluna
o INSERT
especificada aps a clusula
o UPDATE
UPDATE OF for alterada
o DELETE
WHEN
o Restringe as tuplas que disparam o gatilho.
COMANDO
o Aciona o gatilho antes ou depois de um comando,
independentemente do nmero de tuplas afetadas
o No requer a clusula FOR EACH ROW

o No permite o uso dos prefixos :OLD e :NEW


LINHA
o Aciona o gatilho uma vez para cada linha afetada pelo comando ao
qual o gatilho est associado
o Requer a clusula FOR EACH ROW
o Permite o uso dos prefixos :OLD e :NEW
o Permite o uso das clusulas REFERENCING e WHEN
o No pode ler ou modificar a tabela qual o gatilho est associado,
caso da Tabela Mutante.
Referncias aos valores dos atributos
o :NEW.nome_atributo
Indica um novo valor para um campo que est sendo
alterado por um comando INSERT ou UPDATE
o :OLD.nome_atributo
Indica o valor anterior de um campo que est sendo alterado
por um comando DELETE ou UPDATE
REFERENCING OLD AS antigo NEW AS novo substitui OLD por antigo e NEW
POR novo.
Restries ao uso de Triggers

O nmero mximo de gatilhos que podem ser especificados por tabela


12.
No possvel criar dois gatilhos diferentes com as mesmas
caractersticas para uma mesma tabela.
Chaves primrias, nicas ou estrangeiras no podem ser alteradas por
gatilhos.
No podemos realizar os comandos COMMIT, ROLLBACK e
SAVEPOINT em um Trigger, mesmo que seja uma procedure executada
em um Trigger.

No podemos fazer select na mesma tabela que sofre a ao de um


Trigger, pois isso pode provocar um erro chamado MUTANT TABLE.
Mesmo porque se quisermos saber o valor de uma coluna do registro que
est sendo tratado em um Trigger basta colarmos :new.nomecoluna ou
:old.nomecoluna para termos respectivamente os valores atuais e
anteriores a alterao.

Predicados:
Retornam TRUE se o gatilho foi disparado por:
o INSERT: predicado inserting.
o UPDATE: predicado updating.
o DELETE: predicado deleting.
Exemplo
IF inserting THEN comandos_insero;
ELSIF deleting THEN comandos_remoo;
ELSE comandos_atualizao;
END IF;

Tipos de Gatilhos
Os Triggers podem ser do tipo ROW LEVEL (Linha) ou STATEMENT (Tabela).
Trigger ROW LEVEL:
Os Triggers do tipo ROW LEVEL podem ser usados sempre que
precisarmos que um Trigger trate de valores em uma transao, e por sua
vez so disparados a cada ocorrncia de uma transao sobre uma
tabela. Se um UPDATE atualizar, por exemplo, 1000 linhas em uma
tabela que possua um Trigger de Update do tipo row level, sero
disparadas 1000 vezes.
Os Triggers do tipo row level so utilizadas para operaes como:
o Gravao de LOGS de auditoria de uma aplicao;
o Verificao de dados (Consistncia);
o Implementao de integridade referencial;
Trigger STATEMENT:
Os Triggers do tipo STATEMENT tem a finalidade de tratar a execuo de
aes sobre tabelas independentemente de quantas linhas forem
afetadas. Atravs deste tipo de Trigger podemos registrar a execuo de
comandos INSERT, UPDATE e DELETE contra tabelas que tenham
Triggers contemplando essas aes. Caso um comando UPDATE
atualize 1000 linhas, um Trigger deste tipo apenas dispararia 1 nica vez.
Este tipo de Trigger no pode referenciar qualquer valor contido em uma
coluna da tabela. Isso ocorre porque se o mesmo dispara uma nica vez.
Este tipo de Trigger funciona nos casos de registro de transaes
ocorridas, independentemente do nmero de linhas afetadas.
COLUMN Trigger:
Triggers de Coluna so disparados sempre que a determinada coluna
relacionada no Trigger sofrer a ao ligada ao mesmo. Com isso se a
ao ocorrer em outras colunas que no aquelas associadas ao Trigger, o
Trigger no ser disparado. Isso evita de certa forma que um Trigger seja
disparado se a ao no ocorra, nada ser disparado. Isso pode ser til
em casos de auditoria de mudanas em determinadas colunas, por
exemplo:
o Toda vez que um salrio for alterado na tabela de funcionrio um
Trigger gravar em uma tabela chamada log_funcionrio um
registro contendo o cdigo do empregado e os salrios anteriores e
atuais.
Exemplo
CREATE OR REPLACE TRIGGER Auditoria_Funcionrio AFTER INSERT OR
DELETE OR UPDATE OF Cd_Salario ON FUNCIONARIO REFERENCING OLD AS
Antigo NEW AS Novo FOR EACH ROW
BEGIN
INSERT INTO LOG_FUNCIONARIO (Cd_Funcionario, Cd_Salario_Ant,
Cd_Salario_Atu, Cd_user, Dt_trasac)
VALUES (:Novo.Cd_Funcionario, :Antigo.Cd_Salario ,
:Novo.Cd_Salario , user, SYSDATE);
TABLE Trigger:
END;

Trigger de tabela ocorrem independentemente das colunas afetadas pela


ao. Isso quer dizer que se uma ao ocorre, no importa qual coluna

seja afetada, a ao que o Trigger cobre no est ligado a nenhuma


coluna. Estes Triggers podem ser teis em aes como o exemplo a
seguir;
Toda vez que um dado referente ao funcionrio for alterado (no importa
a coluna) a trigger bkp_funcionario executada fazendo a cpia de toda a
tabela funcionario para a tabela bkp_funcionario.
Exemplo
CREATE OR REPLACE TRIGGER Bkp_Funcionrio AFTER INSERT OR DELETE
OR UPDATE ON FUNCIONARIO REFERENCING OLD AS Antigo NEW AS Novo
BEGIN
DELETE BKP_FUNCIONARIO;
INSERT INTO BKP_FUNCIONARIO (Cd_Funcionario, De_Nome,
Cd_Unidade, Cd_Departamento, cd_cargo, dt_admis, dt_demis,
cd_salario, Cd_user, Dt_trasac)
SELECT F.Cd_Funcionario as Cd_Funcionario, F.De_Nome as
De_Nome, F.Cd_Unidade as Cd_Unidade, F.Cd_Departamento as
Cd_Departamento, F.cd_cargo as cd_cargo, F.dt_admis as
dt_admis, F.dt_demis as dt_demis, F.cd_salario as cd_salario,
user as Cd_user, SYSDATE as Dt_trasac
FROM FUNCIONARIO F ;
END;

Momento (Antes ou Depois)


Antes (Before):
Os Triggers do tipo BEFORE como podemos deduzir, disparam antes que
a ao ocorra. Isso leva a entender que antes que uma ao de banco de
dados ocorra o Trigger ser disparado, o que pode fazer com que a ao
nem venha a ocorrer. Um Trigger pode impedir que uma ao venha a
ocorrer, portanto podemos usar um Trigger deste tipo em situaes como,
por exemplo:
o Validao de dados;
o Carregamento de dados obrigatrios (datas, usurios, etc..);
o Impedimento de aes em horrios no previstos.
After (Depois):
Os Triggers do tipo AFTER ocorrem depois que a ao tenha ocorrido, ou
seja eles so disparados depois, com isso NO podemos com esses tipos
de Triggers fazer o que fazemos com Triggers do tipo BEFORE. Aqui a
ao j ocorreu ento o que podemos fazer com Triggers deste tipo a
auditoria.
Modificadores OLD e NEW
Podemos nos casos de Triggers de linha, fazer referncia a valores contidos nas
colunas e com isso podemos querer saber os valores antes da alterao e depois dos
valores efetivamente alterados. Isso vale na ao de UPDATE, nos casos de INSERT e
DELETE os valores de OLD (INSERT) e NEW (DELETE) so nulos. Estes
modificadores podem ser usados APENAS em TRIGGERS. No podemos us-los em
procedures, functions ou packages.
Os valores so referenciados da seguinte forma :OLD.nomecoluna e
:NEW.nomecoluna;

No importa se o Trigger for BEFORE ou AFTER os modificadores OLD e


NEW no so afetados.

Clausula WHEN
Caso o Trigger tenha alguma condio para ser executado, podemos incluir uma
clusula chamada WHEN. Nesta colocamos as condies que o Trigger ir disparar.
Caso precisemos tratar o valor de alguma coluna, usamos os modificadores OLD e
NEW, mas nessa clausula no colocaremos os : na frente, pois nesse caso ocorrer
erro.
Exemplo
create or replace TRIGGER Audita_Transacao2 BEFORE UPDATE ON
FUNCIONARIO
REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW
WHEN (NEW.Dt_Demis is not null)
BEGIN
raise_application_error(-20001, 'Operao no pode ser
executada. O funcionario ' || :OLD.Cd_Funcionario || ' esta
demitido!');
END;

No exemplo acima o Trigger somente ser executado (BEGIN...END) se a


condio WHEN vier a ocorrer.
Operadores, INSERTING, UPDATING E DELETING
Podemos criar Triggers para serem disparados para vrias aes de banco de
dados. Dessa forma como podemos diferenciar uma ao de insert de outra de delete
ou ainda update. Estes modificadores podem ser feitos APENAS dentro de Triggers,
portanto se usarmos esses operadores em procedures, functions, Packages ou mesmo
PL/SQL annimos os mesmos ocasionaro erros de compilao.
Exemplo
create or replace TRIGGER Auditoria_Funcionrio2 AFTER INSERT OR DELETE OR UPDATE
ON FUNCIONARIO REFERENCING OLD AS Antigo NEW AS Novo FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO LOG_FUNCIONARIO (Cd_Funcionario, Cd_Salario_Ant, Cd_Salario_Atu,
Fg_Acao, Cd_user, Dt_trasac)
VALUES (:Novo.Cd_Funcionario, :Antigo.Cd_Salario , :Novo.Cd_Salario , 'I',
user, SYSDATE);
ELSIF UPDATING THEN
INSERT INTO LOG_FUNCIONARIO (Cd_Funcionario, Cd_Salario_Ant, Cd_Salario_Atu,
Fg_Acao, Cd_user, Dt_trasac)
VALUES (:Novo.Cd_Funcionario, :Antigo.Cd_Salario , :Novo.Cd_Salario , 'U',
user, SYSDATE);
ELSIF DELETING THEN
INSERT INTO LOG_FUNCIONARIO (Cd_Funcionario, Cd_Salario_Ant, Cd_Salario_Atu,
Fg_Acao, Cd_user, Dt_trasac)
VALUES (:Novo.Cd_Funcionario, :Antigo.Cd_Salario , :Novo.Cd_Salario , 'D',
Comando
INSTEAD
OF
user,
SYSDATE);
END IF;
END;

Triggers deste tipo foram implementadas a partir da verso 9i e tem a finalidade


de permitir que havendo aes de modificao sobre vises, que os comandos possam
ser realizados nas tabelas associadas a essas vises.

Em outras palavras o INSTEAD OF indica que a trigger ir ser executada no


lugar da instruo que disparou a trigger. Literalmente, a instruo substituda pela
trigger. Essa tcnica permite que faamos, por exemplo, alteraes em uma tabela
atravs de uma view. usado nos casos em que a view no pode alterar uma tabela
por no referenciar uma coluna com a constraint not null. Nesse caso a trigger pode
atualizar a coluna que a view no tem acesso.
Dois detalhes muito importantes sobre INSTEAD OF:
S funcionam com views;
sempre de linha. Ser considerado assim, mesmo que "FOR EACH
ROW" for omitido.
Exemplo
create or replace TRIGGER NOVO_FUNCIONARIO
INSTEAD OF INSERT ON EMPREGADOS FOR EACH ROW
BEGIN
INSERT INTO EMPREGADOS (Cd_Funcionario, De_Nome, Cd_Unidade,
Cd_Departamento, cd_cargo, dt_admis, dt_demis, cd_salario)
VALUES (:NEW.Cd_Funcionario, :NEW.De_Nome, :NEW.Cd_Unidade,
:NEW.Cd_Departamento, :NEW.cd_cargo, :NEW.dt_admis,
:NEW.dt_demis, :NEW.cd_salario );
END;

Habilitar/Desabilitar
ALTER TRIGGER
Habilita/desabilita um ou mais gatilhos
ALTER TRIGGER nome_gatilho
ENABLE | DISABLE;

Exemplo:
nome do gatilho
ALTER TRIGGER Audita_Transacao ENABLE;
ALTER TRIGGER Funcionario ENABLE ALL TRIGGERS;
nome da tabela
Compilar
ALTER TRIGGER
Compila novamente um gatilho
ALTER TRIGGER nome_gatilho
COMPILE;

Exemplo:
ALTER TRIGGER Audita_Transacao COMPILE;
Remover
DROP TRIGGER
Remove um gatilho do banco de dados
DROP TRIGGER nome_gatilho;

Exemplo:
DROP TRIGGER Audita_Transacao;