Você está na página 1de 164

PL/SQL

Histrico
Desenvolvida pela Oracle em 1980, inicialmente sendo uma
linguagem puramente procedural

Atravs de um banco de dados Oracle implementa uma
linguagem de programao interpretada que proporciona um
ambiente independente de sistema operacional

Na estratgia de compilao interpretada cada programa escrito
em PL/SQL compilado numa forma intermediria. Este
chamado de Machine Readable Code (Mcode) Vantagem?

O Mcode armazenado no dicionrio de dados do banco de
dados e interpretado no run time



Prof. Arquimedes Lima 2
Histrico
Desde a verso 10g a compilao deixou de ser interpretada
para uma compilao nativa. Questo: A Oracle eliminou o
benefcio de ser independente de sistema operacional?

Ento qual a justificativa para compilao nativa?

A partir da verso Oracle 9i, Release 9 a linguagem PL/SQL
deixou de ser puramente procedural comtemplando os
conceitos de programao orientada objetos

possvel estender as funcionalidades da linguagem
escrevendo bibliotecas externas em C, C++ e Java. As rotinas
em Java podem ser armazenadas no prprio Database com
exceo da verso Express Edition (XE)






Prof. Arquimedes Lima 3
Caractersticas
Linguagem utilizada para programao de servidores de banco de
dados Oracle
Adicionado no Oracle 6
No possui recursos de interface (comunicao com usurios)
So definidos para realizar operaes especficas sobre os dados
Oferece uma maior flexibilidade na manipulao dos dados atravs da
mistura dos comandos SQL com a linguagem PL/SQL
Apresentam-se como:
Stored Procedure
Stored Function
Triggers
Pacotes (Packages)
Blocos annimos

Prof. Arquimedes Lima 4
Arquitetura
Linguagem de programao case-insensitive, assim como SQL

Baseada no conceito de programao estruturada, tipos de
dados estticos, programao modularizada, gerenciamento de
excees, programao paralela

Adota os mesmos operadores, delimitadores de strings e tipos
de dados declarativos do Pascal

Os tipos de dados declarativos so ditos fortes (strong
datatypes) pois no podem ter o tipo de dado modificado em
modo run time


Prof. Arquimedes Lima 5
Arquitetura
A linguagem PL/SQL suporta tipos de dados dinmicos

considerada como uma linguagem que segue o modelo
objeto relacional, tambm conhecido como modelo relacional
estendido

Toda vez que o usurio conecta no banco de dados atravs de
uma ferramenta cliente, a exemplo do SQL Plus, uma nova
sesso criada e nesta possvel executar sentenas em SQL
ou rotinas escritas em PL/SQL
Prof. Arquimedes Lima 6
Arquitetura
Prof. Arquimedes Lima 7
Vantagens
Melhor Performance
Boa produtividade
Possibilidade de definir as regras de negcio no servidor de
banco de dados
Integrao com os recursos do Oracle
Centralizao da lgica de negcio

Equivalentes em outros SGBDs:
Transcation SQL SQL Server
PL/PgSQL PostgreSQL


Prof. Arquimedes Lima 8
Blocos Estruturados
Com a linguagem PL/SQL possvel escrever blocos que
chamamos de annimos (unnamed blocks) que podem ser
utilizados em vrias situaes: Execuo de scripts de carga de
dados, processamento de rotinas avulsas Tem como objetivo
principal executar tarefas avulsas.
Prottipo de um bloco annimo:
Prof. Arquimedes Lima 9
Al mundo!

SET SERVEROUTPUT ON ;
BEGIN
dbms_output.put_line('Hello World.');
END;
/


Prof. Arquimedes Lima 10
Outro exemplo ...
SET SERVEROUTPUT ON ;
DECLARE
v_nome VARCHAR2(30);
BEGIN
v_nome := '&input';
dbms_output.put_line('Hello '||
v_nome );
END;
/
Prof. Arquimedes Lima 11
Blocos nomeados - Funes
FUNCTION function_name
[( parameter1 [IN][OUT] sql_data_type,
, parameter2 [IN][OUT] sql_data_type,
, parameter(n+1) [IN][OUT] sql_data_type )]
RETURN [ sql_data_type ]
IS
-- sentenas de declarao
BEGIN
-- sentenas de execuo
[EXCEPTION]
-- sentenas de tratamento de excees
END;
Prof. Arquimedes Lima 12
Exemplo Funo
create or replace function
f_obter_desconto( p_uf char,
p_salario number ) return number
is
v_perc_desc number(3,2);
begin
if p_uf in ( 'SE', 'BA', 'AL', 'PE' ) then
v_perc_desc := 0.05;
elsif p_uf in ( 'RJ', 'SP', 'MG', 'RS', 'PR' ) then
v_perc_desc := 0.07;
else
v_perc_desc := 0.04;
end if;

return trunc( p_salario * v_perc_desc, 2 );
end;
Prof. Arquimedes Lima 13
Blocos nomeados - Procedimentos
PROCEDURE procedure_name
[( parameter1 [IN][OUT] sql_data_type,
, parameter2 [IN][OUT] sql_data_type,
, parameter(n+1) [IN][OUT] sql_data_type )]
IS
-- sentenas de declarao
BEGIN
-- sentenas de execuo
[EXCEPTION]
-- sentenas de tratamento de excees
END;
Prof. Arquimedes Lima 14
Exemplo Procedimento
create or replace procedure
p_calc_desconto( p_uf char,
p_salario number,
p_desc out number )
is
v_perc_desc number(3,2);
begin
if p_uf in ( 'SE', 'BA', 'AL', 'PE' ) then
v_perc_desc := 0.05;
elsif p_uf in ( 'RJ', 'SP', 'MG', 'RS', 'PR' ) then
v_perc_desc := 0.07;
else
v_perc_desc := 0.04;
end if;
p_desc := trunc( p_salario * v_perc_desc, 2 );
end;
Prof. Arquimedes Lima 15
Exemplo Exceo
Tratamento de exceo quando o nome maior que a varivel

SET SERVEROUTPUT ON ;
DECLARE
v_nome VARCHAR2(10);
BEGIN
v_nome := '&input';
dbms_output.put_line('Hello '|| v_nome );
EXCEPTION
WHEN others THEN
dbms_output.put_line(SQLERRM);
END;
/

Prof. Arquimedes Lima 16
Variveis, Atribuies e
Operadores
Os nomes das variveis devem iniciar obrigatoriamente com
letras, deve conter somente caracteres alfabticos, nmeros e
os caracteres especiais $, _, #
Em linhas gerais uma varivel tem o escopo local. A exceo
desta regras so os blocos annimos alinhados que as
variveis ficam acessveis nas sub-rotinas
Vejamos o exemplo:
DECLARE
v_numero NUMBER;
BEGIN
v_numero := 1;
END;
/
Prof. Arquimedes Lima 17
Variveis, Atribuies e
Operadores
Quando o valor declarado sem especificar o valor inicial o
valor considerado NULL, conforme exemplo:
DECLARE
v_numero NUMBER;
BEGIN
if v_numero IS NULL then
dbms_output.put_line( 'Nmero nulo' );
end if;

v_numero := 1;

if v_numero IS NOT NULL then
dbms_output.put_line( 'Nmero no nulo' );
end if;
END;
/
Prof. Arquimedes Lima 18
Tipos de Variveis
VARCHAR2, NUMBER, CHAR e DATE

PLS_INTEGER, BINARY_FLOAT,
BINARY_INTEGER

BOOLEAN e PLS_INTEGER

TABLE, VARRAY e RECORD

Prof. Arquimedes Lima 19
Tipos de Variveis
CHAR(TAM)
Literal de armazenamento fixo. O Seu tamanho pode variar de 1 a
2000.
VARCHAR2(TAM)
Literal de armazenamento varivel. O tamanho mximo pode variar
de 1 a 4000.
NUMBER(P,S)
Armazenamento de ponto flutuante entre 1 x 10-130 e 9.99999 x
10125. p = indica a quantidade total de dgitos, incluindo as casas
decimais - s: nmero de dgitos decimais
DATE
Armazenamento de datas

Prof. Arquimedes Lima 20
Tipos de Variveis
BINARY_INTEGER
Valor inteiro que varia -2-31 a 231
BOOLEAN
Valores lgicos ( TRUE, FALSE )
VARRAYS
Vetores
IS TABLE OF
Tabela hash
IS RECORD
Registros
PLS_INTEGER
-2147483647 e 2147483647
Prof. Arquimedes Lima 21
Tipos de Variveis
BINARY_FLOAT
Representao de 32 bits

BINARY_DOUBLE
Representao de 64 bits
Prof. Arquimedes Lima 22
Operadores
Aritmticos
Adio ( + ) e Subtrao ( - )
Multiplicao ( * ) e Diviso ( / )
Concatenao ( || )
Comparao Bsica
Igualdade ( = ) e Diferena ( <>, != )
Maior ( > ) e Maior ou igual ( >= )
Menor ( < ) e Menor ou Igual ( <= )
[NOT] BETWEEN valor_inicial AND valor_final
IS [NOT] NULL

Prof. Arquimedes Lima 23
Operadores
IN
Verifica se o contedo de uma varivel est presente em
uma dada coleo
cod_curso IN ( 2, 5, 7, 9, 10 )
LIKE
Avalia se o contedo de uma varivel segue o padro
definido por uma literal
Os caracteres de substituio so:
%, para uma cadeia de caracteres
_, para um caracter
nome like 'Ana%'

Prof. Arquimedes Lima 24
Operadores
SOME e ANY
Deve ser utilizado com um dos seguintes operadores: =, >,
<, >= e <=
Verifica se o contedo de uma varivel quando aplicado um
dos operadores bsicos de comparao verdadeiro para
algum dos elementos da lista
media = some( 6, 7, 9 )
ALL
Com sintaxe semelhante ao SOME e ANY, o resultado ser
verdadeiro apenas se o contedo da varivel quando
aplicado o operador bsico de comparao for verdadeiro
para todos os elementos da lista
media > all( 6, 7, 9 )

Prof. Arquimedes Lima 25
Operadores
Operadores lgicos
NOT, AND, OR
Precedncia
Operadores multiplicativos ( *, / )
Operadores aditivos ( +, - )
Operadores de comparao ( =, >, is null, ... )
NOT
AND
OR
Os parnteses podem ser utilizados para alterar a
precedncia de avaliao das expresses

Prof. Arquimedes Lima 26
Principais Funes Numricas
ABS( n )
Obtm o mdulo de um nmero
Ceil( n )
Retorna o maior inteiro maior ou igual a n
EXP( n )
Retorna o valor de e (2.71828183) elevado a n
Floor( n )
Retorna o menor inteiro menor ou igual a n
LN( n )
Retorna o logaritmo natural de n

Prof. Arquimedes Lima 27
Principais Funes Numricas
LOG( b, n )
Retorna o logaritmo de n na base b
MOD( n, d )
Obtm o resto da diviso de n por b
POWER( n, m )
Recupera o valor de n elevado a m
ROUND( n, d )
Arredonda o valor de n na casa decimal d
O valor default zero
O valor de d pode ser negativo

Prof. Arquimedes Lima 28
Principais Funes Numricas
SQRT( n )
Obtm a raiz quadrada de n
TRUNC( n, m )
Trunca o valor de na na casa decimal definida por m
O valor default para m zero
O valor de m pode ser negativo
SIN( n )
Seno de n
COS( n )
Cosseno de n
TAN( n )
Tangente de n

Prof. Arquimedes Lima 29
Principais Funes Literais
ASCII( c )
Recupera o cdigo ascii de um determinado caractere
CHR( n )
Mapeia o caractere ascii referente ao nmero n
CONCAT( c1, c2 )
Retorna o resultado da concatenao de c1 com c2
INITCAP( c )
Retorna a literal c com todas as iniciais de palavras em
letras maisculas e o restante em letras minsculas

Prof. Arquimedes Lima 30
Principais Funes Literais
INSTR( c1, c2, n, m )
Recupera a posio, considerando que a primeira letra a
posio 1, onde c2 aparece em c1
O parmetro n opcional e indica a posio de incio da
busca em c1
O parmetro m determina qual a ocorrncia de c2 em c1
deve ser considerada
Os valores default de n e m so 1
A expresso instr( nome, 'es', 4, 2 ) indica que deve ser
retornada a posio da segunda ocorrncia da literal 'es' a
partir da quarta posio do contedo da varivel nome

Prof. Arquimedes Lima 31
Principais Funes Literais
LOWER( c ) e UPPER( c )
Converte todas as letras da literal c para minscula (lower)
ou maisculas (upper)
LPAD( c1, tam, c2 ) e RPAD( c1, tam, c2 )
Retorna a literal c1 preenchida esquerda (lpad) ou direita
(rpad) com a literal c2 at o tamanho definido pelo
parmetro tam
O parmetro c2 opcional, e quando no informado
considerado o espao em branco
LTRIM( c1, c2 ) e RTRIM( c1, c2 )
Retorna a literal c1 retirando as ocorrncia de c2 esquerda
(ltrim) ou direita (rtrim)
c2 opcional sendo que o default espao em branco

Prof. Arquimedes Lima 32
Principais Funes Literais
LENGTH( c1 )
Retorna o tamanho da literal c1
REPLACE( c1, c2, c3 )
Retorna o resultado da substituio de todas as ocorrncias
de c2 por c3 em c1
SUBSTR( c1, m, n )
Recupera uma substring de c1 iniciada na posio m com
tamanho n
n opcional, e quando omitido considerada toda a literal a
partir da posio m

Prof. Arquimedes Lima 33
Principais Funes de Data
ADD_MONTHS( d, n )
Retorna uma data que resultado da adio de n meses
data d
MONTHS_BETWEEN( d1, d2 )
Obtm o nmero de meses existente entre as datas d1 e d2
SYSDATE
Retorna a data atual do sistema, incluindo hora, minuto e
segundo
TRUNC( d )
Retorna a data d sem as informaes de hora, minuto e
segundos

Prof. Arquimedes Lima 34
Principais Funes de Converso
TO_DATE( lit, fmt )
Converte a literal lit para o tipo data utilizando o formato
especificado por fmt
TO_CHAR( d, fmt )
Converte uma data para uma literal com o formato definido
por fmt
TO_CHAR( n, fmt )
Converte um nmero para uma literal com o formato
definido por fmt
TO_NUMBER ( l, fmt )
Converte uma literal para um valor numrico utilizando como
formato de converso o parmetro fmt

Prof. Arquimedes Lima 35
Principais Funes de Converso
Se o padro de converso no for informado, o Oracle utilizar
o formato default da seo do usurio
Principais padres para nmero
D indica o separador de milhar de um nmero
G indica o separador decimal de um numero
0 define que um nmero deve ser retornado
9 indica que um nmero pode ser retornado
$ - define que o smbolo deve ser retornado
L define o smbolo local para moeda
Exemplos:

Prof. Arquimedes Lima 36
select to_char(1210.73, '9G999D00') formato_numerico
from dual;
select to_char(1210.73, 'L9G999D00') formato_moeda
from dual;
select to_char(21, '000099') zero_esquerda
from dual;
Principais Funes de Converso
Principais padres para data
DD Dia com dois dgitos
MM Ms com dois dgitos
YYYY Ano com 4 dgitos
HH24 Hora com 2 dgitos (0..23)
MI Minutos em 2 dgitos
SS Segundos com 2 dgitos
D Dia da semana (1..7)
DAY Descrio do dia
MONTH Descrio do ms
MON Trs letras iniciais do ms
Ex.: 'DD/MM/YYYY HH24:MI:SS
Prof. Arquimedes Lima 37
lgebra com Datas
A adio ou subtrao de nmeros inteiros a uma data
ocasionam, respectivamente, o acrscimo ou decrscimos de
dias data
A subtrao de duas datas retorna o nmero de dias existentes
entre elas
Datas no podem ser multiplicadas ou divididas
Adicionar 1 minuto a uma data equivale a adio de 1/1440 a
ela
Adicionar 1 segundo a uma data equivale a adio de 1/86400
a ela

Prof. Arquimedes Lima 38
Exemplos de Padres de Data
Uma data formatada com ano em quatro dgitos, horas, minutos
e segundos
DD/MM/YYYY HH24:MI:SS
15/10/2012 13:22:30
Formatao para recuperar a descrio do ms, a palavra de,
e o ano em quatro dgitos
MONTH de YYYY
ABRIL DE 2012
Formato para obter o nmero do dia de uma data (1-Domingo,
2-Segunda, etc ...)
D

Prof. Arquimedes Lima 39
Funo para Mapeamento de Valores
DECODE( var, val1, res1, ...,
valN, resN, resDefault)

Implementa uma condicional de uma linha
Se o valor da varivel var for igual a val1, o resultado da funo
ser res1. Se o valor de var no coincidir com nenhum dos
valores, ser retornado o resultado padro (resDefault)
O resultado padro opcional
Exemplo
DECODE( conceito, A, TIMO,
B, BOM,
C, REGULAR,
RUIM )
Prof. Arquimedes Lima 40
Outras Funes
GREATEST( arg1, arg2, arg3, ..., argn )
Recupera o maior valor existente entre os argumentos
LEAST( arg1, arg2, arg3, ..., argn )
Recupera o menor valor existente entre os argumentos
NVL( arg1, arg2 )
Testa o valor de arg1 de modo que se o mesmo for nulo, a
funo retorna o valor de arg2, caso contrrio, retorna o
prprio valor de arg1
USER
Recupera o nome do usurio corrente

Prof. Arquimedes Lima 41
Valor Default
Exemplo 01
DECLARE
v_num NUMBER := 1;
BEGIN
dbms_output.put_line( 'Valor padro --> '||
v_num );
END;
Exemplo 02
DECLARE
v_num NUMBER DEFAULT 1;
BEGIN
dbms_output.put_line( 'Valor padro --> '||
v_num );
END;

Prof. Arquimedes Lima 42
Constantes
DECLARE
v_pi CONSTANT NUMBER := 3.14;
BEGIN
dbms_output.put_line( 'PI --> '||
v_pi );
END;

Prof. Arquimedes Lima 43
Operadores
Em suma os operadores so os mesmos utilizados na
linguagem SQL (ser revisto posteriormente)
A comparao de negao pode ser realizada de quatro formas
distintas: <>, !=, ~=, ^=

DECLARE
v_num NUMBER := 1;
BEGIN
if v_num <> 2 then
dbms_output.put_line( 'Diferente de 2' );
end if;
if v_num != 2 then
dbms_output.put_line( 'Diferente de 2' );
end if;
END;
Prof. Arquimedes Lima 44
Estruturas de Controle
Estruturas Condicionais
IF ELSIF ELSE

CASE

Estruturas Iterativas
FOR

SIMPLE

WHILE


Prof. Arquimedes Lima 45
Estruturas Condicionais
(IF, CASE)
Prof. Arquimedes Lima 46
Sentena IF
Possui dois subtipos
IF THEN ELSE
IF THEN ELSIF THEN ELSE

Todas as sentenas IF so finalizadas com a palavra
reservada END IF

Assim como as sentenas CASE so finalizadas com a palavra
reservada END CASE

O ponto e vrgula sempre utilizado como finalizador de cada
frase

Prof. Arquimedes Lima 47
IF THEN - ELSE
Prottipo bsico

IF [NOT] left_operand1 = right_operand1 [[AND|OR]
[NOT] left_operand2 = right_operand2 [[AND|OR]
[NOT] boolean_operand ]] THEN
NULL;
[ELSE]
NULL;
END IF;
Prof. Arquimedes Lima 48
Exemplo
DECLARE
-- Varivel booleana (comentrio de uma linha)
my_var BOOLEAN;

BEGIN
/* Utilizando a funo NVL
(comentrio de mais de uma linha)*/
IF NOT NVL(my_var,FALSE) THEN
dbms_output.put_line('Valor no inicializado');
ELSE
dbms_output.put_line('Valor inicializado');
END IF;
END;
Prof. Arquimedes Lima 49
IF THEN ELSIF THEN - ELSE
Prottipo bsico

IF [NOT] left_operand1 > right_operand2 [AND|OR]
NULL;
ELSIF [NOT] left_operand1 = right_operand1 [[AND|OR]
[NOT] left_operand2 = right_operand2 [[AND|OR]
[NOT] boolean_operand ]] THEN
NULL;
[ELSE]
NULL;
END IF;

Prof. Arquimedes Lima 50
Sentena CASE
Funciona de forma anloga a sentena IF THEN ELSIF
THEN ELSE
Existem dois tipos de sentena CASE
Case simples (SIMPLE CASE)
Neste caso, uma varivel escalar (seletora ou selector)
utilizada para avaliao da expresso
Case com pesquisa (SEARCHED CASE)
Nesta segunda alternativa, utilizada uma expresso
condicional para avaliao
Veremos os exemplos a seguir ...

Prof. Arquimedes Lima 51
Sentena CASE
Prottipo genrico da sentena CASE:

CASE [ TRUE | [selector_variable]]
WHEN [criterion1 | expression1] THEN
criterion1_statements;
WHEN [criterion2 | expression2] THEN
criterion2_statements;
WHEN [criterion(n+1) | expression(n+1)] THEN
criterion(n+1)_statements;
ELSE
block_statements;
END CASE;


Prof. Arquimedes Lima 52
SIMPLE CASE
DECLARE
selector NUMBER := 0;
BEGIN
CASE selector
WHEN 0 THEN
dbms_output.put_line('Case 0!');
WHEN 1 THEN
dbms_output.put_line('Case 1!');
ELSE
dbms_output.put_line('No localizado!');
END CASE;
END;
Prof. Arquimedes Lima 53
SEARCHED CASE - Exemplo
BEGIN
CASE
WHEN (1 > 3) THEN
dbms_output.put_line('Um maior do que trs');
WHEN (3 < 5) THEN
dbms_output.put_line('Trs menor do que cinco');
WHEN (1 = 2) THEN
dbms_output.put_line('Um igual a dois');
ELSE
dbms_output.put_line('Nenhuma das anteriores');
END CASE;
END;
Prof. Arquimedes Lima 54
Interao com SQL
declare
v_nome cursos_teste.nom_curso%type;
v_qtd cursos_teste.qtd_cred%type;
v_cod_curso number(5);
begin
v_cod_curso := 4;

select nom_curso, qtd_cred into v_nome, v_qtd
from cursos_teste
where cod_curso >= v_cod_curso;

dbms_output.put_line( v_nome||' - '|| v_qtd );
exception
when no_data_found then
raise_application_error( -20000, 'Curso informado no existe');
when too_many_rows then
raise_application_error( -20000, Vrias linhas selecionadas');
end;
Prof. Arquimedes Lima 55
Interao com SQL
Este exemplo demonstra a utilizao de um cursor implcito de uma
linha
Excees que eventualmente devem ser tratadas:
NO_DATA_FOUND: Nenhuma linha retornada
TOO_MANY_ROWS: Vrias linhas encontradas
Algumas variveis podem auxiliar o desenvolvedor:

Prof. Arquimedes Lima 56
Exemplo
declare
i integer;
begin
select 1 into i from dual;

if sql%notfound then
dbms_output.put_line( 'Nehuma informao encontrada' );
elsif sql%found then
dbms_output.put_line( 'Informao encontrada' );
end if;

dbms_output.put_line( 'Linhas retornadas = '||
sql%rowcount );
end;

Prof. Arquimedes Lima 57
Exemplo Cursor Implcito Vrias Linhas
SET SERVEROUTPUT ON;
BEGIN
UPDATE cursos
SET tot_cred = tot_cred + 20
WHERE tot_cred between 100 and 450;
IF SQL%FOUND THEN
dbms_output.put_line('Updated ['||
SQL%ROWCOUNT||']');
ELSE
dbms_output.put_line('Nothing updated!');
END IF;
END;
Prof. Arquimedes Lima 58
Estruturas Iterativas
(FOR, SIMPLE, WHILE)
Prof. Arquimedes Lima 59
Sentena FOR
O PL/SQL suporta dois tipos de laos FOR:
Laos numricos: A iterao feita sob determinado range
Laos com cursores: A iterao feita a depender do
nmero de linhas retornados por uma sentena SQL no
cursor

Nesta construo, podemos utilizar de forma combinada as
sentenas CONTINUE ou EXIT, para respectivamente, pular e
forar uma sada prematura do lao

Prof. Arquimedes Lima 60
Exemplo Lao Numrico (FOR)

BEGIN
FOR i IN 1 .. 15 LOOP
dbms_output.put_line( 'Valor indexado --> '||i );
END LOOP;
END;


BEGIN
FOR i IN REVERSE 1 .. 15 LOOP
dbms_output.put_line( 'Valor indexado --> '||i );
END LOOP;
END;

Prof. Arquimedes Lima 61
Lao com CURSOR (FOR)
Prottipo


FOR i IN {cursor_name[(parameter1,
parameter(n+1))] |
(sql_statement)} LOOP
-- Sentena
END LOOP;

Prof. Arquimedes Lima 62
Exemplo Lao com CURSOR (FOR)
DECLARE
CURSOR c IS
SELECT u.cod_curso, u.nom_curso
FROM academico.cursos u ORDER BY 1;
v_comp varchar2(50);

BEGIN
FOR i IN c LOOP
v_comp := '';
IF i.cod_curso = 35 THEN
v_comp := 'CURSO INTEGRAL --------->';
END IF;
dbms_output.put_line( v_comp ||
lpad( i.cod_curso,3, '0' ) ||
'-' || i.nom_curso );
END LOOP;
END;
Prof. Arquimedes Lima 63
Cursor Implcito
BEGIN
FOR i IN ( SELECT cod_curso, nom_curso
FROM academico.cursos
ORDER BY nom_curso ) LOOP
dbms_output.put_line('['||i.cod_curso||'-'||
i.nom_curso||']');
END LOOP;
END;
Prof. Arquimedes Lima 64
Operaes com Cursores
DECLARE
CURSOR c IS
SELECT cod_curso, nom_curso
FROM academico.cursos
ORDER BY 1;
v_linha c%rowtype;
BEGIN
OPEN c;
LOOP
FETCH c INTO v_linha;
EXIT WHEN c%NOTFOUND;
dbms_output.put_line('['||v_linha.cod_curso||'-'||
v_linha.nom_curso||']');
END LOOP;
CLOSE c;
END;
Prof. Arquimedes Lima 65
Clusula WHILE com Cursores
DECLARE
CURSOR c IS
SELECT cod_curso, nom_curso
FROM academico.cursos
ORDER BY 1;
v_linha c%rowtype;
BEGIN
OPEN c;
WHILE c%ISOPEN LOOP
FETCH c INTO v_linha;
IF c%NOTFOUND THEN
CLOSE c;
END IF;
dbms_output.put_line('['||v_linha.cod_curso||'-'||
v_linha.nom_curso||']');
END LOOP;
END; Prof. Arquimedes Lima 66
SIMPLE / WHILE Numrico
DECLARE
v_num pls_integer;
BEGIN
v_num := 1;
WHILE v_num<>11 LOOP
dbms_output.put_line('['||v_num||']');
v_num := v_num + 1;
END LOOP;
dbms_output.put_line( '---- x ---- ');
v_num := 1;
loop
dbms_output.put_line( '{'||v_num||'}' );
v_num := v_num + 1;
exit when v_num = 11;
end loop;
END;
Prof. Arquimedes Lima 67
Exerccio 1
1. Faa um bloco annimo que liste todos os nmeros
primos pertencentes ao um intervalo fechado. Este
intervalo deve ser definido por duas constantes inteiras
mod(a,b): resto da diviso inteira de a por b

2. Faa um bloco annimo que, com base em uma string,
separe valores pelo caracter ;, liste estes valores um
por linha (Ex: thiago;10;10/01/1970).
length( string ): retorna a quantidade de
caracteres de uma string

Prof. Arquimedes Lima 68
Tipos de Dados Compostos
Existem dois tipos de dados compostos: Registros e Colees

Os registros tipicamente possuem um conjuntos de elementos
relacionados, assim como tabelas do banco de dados

Uma coleo pode conter um conjunto de tipos de dados escalares,
vetoriais, LOBs ou tipos de dados definidos pelo usurio

Os registros so teis para trabalhar com cursores e colees

A seguir veremos com maiores detalhes esses tipos de dados
compostos
Prof. Arquimedes Lima 69
Registros (Records)
Um registro um tipo estruturado que contm uma lista de variveis
que tipicamente possuem nomes e tipos de dados distintos
Exemplo de registro explcito:
DECLARE
TYPE t_pessoa IS RECORD
( id number(5),
cpf char(11),
nome varchar2(60) );
v_pes t_pessoa;
BEGIN
v_pes.id := 10;
v_pes.cpf := 56947825414;
v_pes.nome := Maria Jos;
dbms_output.put_line( v_pes.id||;||v_pes.cpf||;||
v_pes.nome );
END;
Prof. Arquimedes Lima 70
Registros Implcitos
Atravs de atributo %ROWTYPE possvel declarar um registro de
forma implcita:
DECLARE
v_cur academico.cursos%rowtype;
BEGIN
v_cur.cod_curso := 26;
v_cur.nom_curso := 'Cincia da Computao';
v_cur.tot_cred := 300;
v_cur.idt_prof := 3421;

dbms_output.put_line(v_cur.cod_curso||';'||
v_cur.nom_curso );
END;
Prof. Arquimedes Lima 71
Colees
As colees so compostas pelos vetores e listas

A diferena essencial entre eles que os vetores utilizam indexadores
numricos sequenciais, enquanto as listas podem utilizar indexadores
numricos no sequenciais ou indexadores string

Os vetores so caracterizados por serem populados densamente (j
que so compostos por nmeros sequenciais, enquanto as listas
podem ser esparsadas viabilizando buracos (gaps) na sequncia que
os indexa

A Oracle suporta trs tipos de colees, so eles VARRAY, NESTED
TABLE e ARRAY




Prof. Arquimedes Lima 72
Colees - VARRAY
um vetor tradicional onde os elementos so do mesmo tipo de dados
e utiliza indexadores numricos sequenciais

O desenvolvedor deve utilizar mensurar, em tempo de declarao, o
tamanho do vetor

Nesta coleo, no possvel incrementar o tamanho do vetor em
tempo de execuo

Tambm possvel inicializar o vetor com valores na declarao da
coleo

Deve ser utilizado quando o desenvolvedor sabe a priori exatamente a
quantidade de elementos que ir precisar
Prof. Arquimedes Lima 73
Exemplo VARRAY
DECLARE
TYPE tipo_varray IS VARRAY(10) OF NUMBER;
v_lista tipo_varray := tipo_varray(1,2,3,4,5,6,7,8,null);

BEGIN

FOR i IN 1 .. v_lista.COUNT LOOP
dbms_output.put('['||v_lista(i)||']');
END LOOP;
dbms_output.new_line;

dbms_output.put_line( 'Limite mximo do vetor:'||
v_lista.LIMIT );
dbms_output.put_line( 'Total de elementos: '||
v_lista.COUNT );

END; Prof. Arquimedes Lima 74
Exemplo VARRAY
DECLARE
TYPE tipo_varray IS VARRAY(10) OF NUMBER;
v_lista tipo_varray := tipo_varray();
BEGIN
v_lista.extend( v_lista.LIMIT );

FOR i IN 1 .. 8 LOOP
v_lista(i) := i;
END LOOP;

FOR i IN 1 .. v_lista.COUNT LOOP
dbms_output.put('['||v_lista(i)||']');
END LOOP;
dbms_output.new_line;
END;
Prof. Arquimedes Lima 75
Colees NESTED TABLE
Tambm utiliza como base indexadores sequenciais numricos

A diferena com relao a coleo VARRAY est no fato que no
preciso estabelecer a priori a quantidade de elementos necessria

Desta forma, podendo ser dimensionada por demanda e em tempo de
execuo. So densamente populadas

Deve ser utilizada quando o desenvolvedor no sabe, a princpio, da
quantidade exata de elementos que ir necessitar no programa

O DBA responsvel por definir o tamanho mximo da alocao no
SGBD (rea chamada de PGA). Se o desenvolvedor violar o tamanho
mximo o SGBD ir lanar uma exceo
Prof. Arquimedes Lima 76
Exemplo NESTED TABLE
DECLARE
TYPE number_table IS TABLE OF NUMBER;
list NUMBER_TABLE := number_table(1,2,3,4,5,6,7,8);
BEGIN
list.DELETE(2);
FOR i IN 1..list.COUNT+1 LOOP
IF list.EXISTS(i) THEN
dbms_output.put('['||list(i)||']');
END IF;
END LOOP;
dbms_output.new_line;

dbms_output.put_line( 'N elementos:'||list.COUNT );
END;
Prof. Arquimedes Lima 77
Exemplo NESTED TABLE
DECLARE
TYPE number_table IS TABLE
OF NUMBER;
list NUMBER_TABLE;

procedure incluir( p_valor number )
is
idx pls_integer;
begin
idx := list.COUNT + 1;
list.extend(1);
list(idx) := p_valor;
end;

BEGIN
/* Inicializando a lista */
list := number_table();

incluir( 10 ); incluir( 20 );
incluir( 30 ); incluir( 40 );

list.DELETE(3);

FOR i IN 1..list.COUNT+1 LOOP
IF list.EXISTS(i) THEN

dbms_output.put('['||list(i)||']');
END IF;
END LOOP;
dbms_output.new_line;
dbms_output.put_line( 'N
elementos:'||list.COUNT );
END;
Prof. Arquimedes Lima 78
Vetores associativos (ARRAY)
Tambm chamado de Associative Array

Pode ser utilizados com indexadores numricos e strings

Tambm traz a idia que no preciso estabelecer a princpio a
quantidade de elementos que ser utilizada

Neste tipo de coleo preciso especificar a natureza do indexador
Prof. Arquimedes Lima 79
Exemplo ARRAY
DECLARE
TYPE number_table IS TABLE OF NUMBER
INDEX BY PLS_INTEGER;
list NUMBER_TABLE;
BEGIN
FOR i IN 1..6 LOOP
list(i) := i;
END LOOP;
list.DELETE(2);
FOR i IN 1..list.COUNT+1 LOOP
IF list.EXISTS(i) THEN
dbms_output.put('['||list(i)||']');
END IF;
END LOOP;
dbms_output.new_line;
END;
Prof. Arquimedes Lima 80
Exemplo ARRAY
set serveroutput on;
declare
type tTab is table of varchar2(40)
index by varchar(2);
tab tTab;
begin
tab( 'SE' ) := 'Nordeste';
tab( 'AM' ) := 'Norte';
tab( 'PR' ) := 'Sul';
dbms_output.put_line( 'Sergipe.: ' || tab( 'SE' ) );
dbms_output.put_line( 'Amazonas: ' || tab( 'AM' ) );
dbms_output.put_line( 'Paran..: ' || tab( 'PR' ) );
end;
Prof. Arquimedes Lima 81
Exemplo ARRAY
DECLARE
type tTab is table of varchar2(40)
index by varchar2(2);
tab tTab;
key varchar2(2);
BEGIN
tab( 'SE' ) := 'Nordeste';
tab( 'AM' ) := 'Norte';
tab( 'PR' ) := 'Sul';
key := tab.first;
while key is not null loop
dbms_output.put_line( 'Estado.: '||key||' ->
'||'Regio: ' ||tab( key ) );
key := tab.next( key );
end loop;
END;
Prof. Arquimedes Lima 82
Exemplo ARRAY
DECLARE
type tTab is table of cursos%rowtype
index by pls_integer;
tab tTab;
BEGIN
tab(1).cod_curso := 1; tab(2).cod_curso := 2;
tab(1).nom_curso := 'CC'; tab(2).nom_curso := 'SI';
dbms_output.put_line( 'Curso-1: ' ||tab( 1 ).cod_curso ||
' - ' ||
tab( 1 ).nom_curso );
dbms_output.put_line( 'Curso-2: ' ||tab( 2 ).cod_curso ||
' - ' ||
tab( 2 ).nom_curso );
END;
Prof. Arquimedes Lima 83
Exemplo ARRAY
DECLARE
TYPE t_pessoa IS RECORD
( id number(5),
cpf char(11),
nome varchar2(60) );

type tTab is table of t_pessoa
index by pls_integer;
tab tTab;
BEGIN
tab(1).id := 1;
tab(1).cpf := '45836214578';
tab(1).nome := 'Maria';







...

tab(2).id := 2;
tab(2).cpf := '96325412358';
tab(2).nome := 'Rosa';
for i in 1 .. tab.COUNT loop
dbms_output.put_line(
tab(i).id||'-'||
tab(i).cpf||'-'||
tab(i).nome );
end loop;
END;
Prof. Arquimedes Lima 84
Excees
Mecanismo utilizado na linguagem para reportar advertncias ou erros
de programas em tempo de execuo;

Existem duas modalidades de excees: Excees do sistema ou
excees definidas pelo usurio;

Quando uma exceo ocorre o fluxo normal do programa
interrompido e o controle transferido para o bloco de tratamento de
excees;

As excees geradas devem ser tratadas com o uso de sentenas
WHEN na clusula EXCEPTION
Prof. Arquimedes Lima 85
Excees
Sintaxe bsica:
WHEN <excecoes> THEN

Em uma clusula EXCEPTION podem ser
definidas vrias clusulas WHEN;

A palavra reservada OTHERS pode ser utilizada para iniciar o
tratamento de qualquer exceo gerada;

As vrias excees tratadas so analisadas na clusula EXCEPTION
na ordem em que so definidas na sentena WHEN;

Prof. Arquimedes Lima 86
Excees
No tratamento de excees com a sentena WHEN apenas os
comandos de uma nica sentena so executados (exclusivo);

Os erros so propagados entre os blocos PL/SQL de acordo com a
hierarquia de chamada dos blocos;

Se a exceo no for tratada na hierarquia de blocos a mensagem de
erro ser exibida para o usurio na forma de um erro Oracle;

Os erros so caracterizados por um cdigo e uma mensagem que
podem ser capturados atravs das funes implcitas SQLCODE e
SQLERRM;

Prof. Arquimedes Lima 87
Exemplo Exceo
DECLARE
a NUMBER;
BEGIN
DECLARE
b VARCHAR2(2);
BEGIN
SELECT 1 INTO b
FROM dual
WHERE 1 = 2;
a := b;
EXCEPTION
WHEN VALUE_ERROR THEN
dbms_output.put_line('Voc no pode colocar ['||b||
'] numa string de um caracter');
END;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Exceo geral ['||SQLERRM||'].');
END;
Prof. Arquimedes Lima 88
Exemplo Exceo
DECLARE
a NUMBER;
e EXCEPTION;
BEGIN
DECLARE
b VARCHAR2(2) := 'AB';
BEGIN
RAISE e;
EXCEPTION
WHEN others THEN
a := b; -- Ocorre uma exceo
dbms_output.put_line('Este comando no ser
executado.');
END;
EXCEPTION
WHEN others THEN
dbms_output.put_line('Captura da exceo
['||SQLCODE||'].');
END; Prof. Arquimedes Lima 89
Outro exemplo ...
DECLARE
a varchar2(1) := :valor;
BEGIN
dbms_output.put_line('Esta linha no ser impressa
['||a||']');
EXCEPTION
WHEN others THEN
dbms_output.put_line('Exceo ['|| sqlcode ||']:
'||sqlerrm );
END;
Prof. Arquimedes Lima 90
Excees Pr-Definidas (comuns)
DUP_VAL_ON_INDEX
ORA-00001 (SQLCODE = -1)
retornado quando ocorre violao de chave primria ou chave
nica;
NO_DATA_FOUND
ORA-01403 (SQLCODE = -100)
lanada quando um comando SELECT INTO, por exemplo
deveria recuperar um elemento e no recupera;
TOO_MANY_ROWS
ORA-01422 (SQLCODE = -1422)
gerada quando um comando SELECT INTO em um bloco
PL/SQL recupera mais de uma linha no resultado

Prof. Arquimedes Lima 91
Excees Pr-Definidas (comuns)
INVALID_NUMBER
ORA-01722 (SQLCODE = -1722)
Lanada quando uma converso para um valor numrico
invlida;
VALUE_ERROR
ORA-06502 (SQLCODE = -6502)
Esta associada a operaes aritmticas de converso, atribuio a
variveis de tamanho menor e truncamento;
ZERO_DIVIDE
ORA-01476 (SQLCODE = -1476)
Erro de diviso por zero
SUBSCRIPT_BEYOND_COUNT
ORA-06533 (SQLCODE = -6533)
Acesso a uma posio no alocada de uma NESTED TABLE ou
VARRAY

Prof. Arquimedes Lima 92
Excees Definidas pelo Usurio
Os usurios podem lanar suas prprias excees dentro de um bloco
PL/SQL

O lanamento possvel atravs do comando
RAISE_APPLICATION_ERROR

Sintaxe:
raise_application_error( <cod_erro>, <msg_erro);

A Oracle reserva uma faixa de cdigos de erro para excees
definidas pelo usurio que varia de -20000 a -20999
Prof. Arquimedes Lima 93
Excees
As excees so utilizadas para validao dos dados conforme regras
de negcio

Essas mensagens so implementadas em gatilhos, funes, rotinas
armazenadas e pacotes;

Uma exceo pode ser relanada em uma seo de tratamento
atravs do comando RAISE;
Prof. Arquimedes Lima 94
Packages
So as bibliotecas armazenadas no banco de dados

Podemos afirmar que representa o backbone no desenvolvimento de
aplicaes em bancos de dados Oracle

Os pacote viabilizam agrupar funes e procedimentos em bibliotecas

Dentro dos pacotes possvel implementar variveis compartilhadas,
tipos de dados e componentes que so as funes e procedimentos

Os pacotes so definidos em duas partes distintas:
Especificao (interface): Publica a declarao;
Corpo (implementao): Implementa cada item da especificao;
Prof. Arquimedes Lima 95
Packages
possvel criar uma funo / procedimento no corpo do pacote e no
declar-las na especificao, neste caso podemos afirmar que so
privadas

Um pacote de propriedade do esquema que foi compilada

Caso seja necessrio utilizar em outros esquema ser necessrio o
privilgio de EXECUTE

Os pacotes podem ser executados atravs de blocos annimos,
procedimentos armazenados, funes, gatilhos e atravs das funes
em sentenas SQL




Prof. Arquimedes Lima 96
Packages
A visibilidade e referncia das rotinas, tipos e variveis ocorre da
seguinte forma:

Aquelas que so definidas na especificao so visveis de
qualquer ponto do pacote

Enquanto as que so definidas na implementao so visveis para
rotinas implementadas a partir de sua definio



Prof. Arquimedes Lima 97
Packages
Sintaxe Especificao

CREATE OR REPLACE PACKAGE <nome do pacote> IS
/* Declarao de tipos e variveis pblicos */
/* Assinaturas das funes / procedimentos */
END;

Sintaxe Corpo

CREATE OR REPLACE PACKAGE BODY <nome do pacote> IS
/* Declarao de tipos e variveis privados */
/* Implementao de funes / procedimentos privados */
Prof. Arquimedes Lima 98
Consideraes Packages

Uma especificao de pacote pode existir sem um corpo de pacote,
mas um corpo no pode existir sem uma especificao de pacote


A sintaxe para definio das PROCEDURES e FUNCTIONS no corpo do
pacote deve apenas retirar a clusula CREATE OR REPLACE Segue
o mesma forma de definio em blocos annimos


Para a especificao (interface), a declarao possui apenas a
assinatura da rotina

Prof. Arquimedes Lima 99
Exemplo Especificao
create or replace package pkg_bibl is

/* Tipo registro pblico */
type t_reg_cont is record( data date,
tot number(3) );

/* Funo que obtm a idade a partir de uma data
de nascimento */
function idade( p_dat_nasc date ) return number;

end;
Prof. Arquimedes Lima 100
Exemplo Corpo
create or replace package body pkg_bibl is

---------------------------------------------------
/* Varivel privada do corpo da package */
v_reg_cont t_reg_cont;
---------------------------------------------------
function idade( p_dat_nasc date ) return number
is begin
return trunc( months_between( sysdate,
p_dat_nasc ) / 12 );
end;

end;
Prof. Arquimedes Lima 101
Exemplo Inicializao
create or replace package body pkg_bibl is

---------------------------------------------------
/* Varivel privada do corpo da package */
v_reg_cont t_reg_cont;
---------------------------------------------------
function idade( p_dat_nasc date ) return number
is begin
return trunc( months_between( sysdate,
p_dat_nasc ) / 12 );
end;

begin
v_reg_cont.data := sysdate; v_reg_cont.tot := 0;
end;

Prof. Arquimedes Lima 102
Utilizao Bloco Annimo
set serveroutput on;

declare
v_reg pkg_bibl.t_reg_cont;
begin
v_reg.data := sysdate;
v_reg.tot := 0;
dbms_output.put_line( pkg_bibl.idade(
to_date( '27/04/1976','DD/MM/YYYY' ) ) );
end;

Prof. Arquimedes Lima 103
Utilizao em SQL
select nom_alu as Nome,

dat_nasc as Nascimento,

pkg_bibl.idade( dat_nasc ) Idade

from academico.alunos

where rownum <= 10

order by Idade desc;
Prof. Arquimedes Lima 104
Utilizao em Funes
create or replace
function f_obter_idade( p_dat_nasc date ) return number
is begin
if p_dat_nasc is null then
raise_application_error( -20000, 'A data de nascimento '||
'deve ser informada' );
else
return pkg_bibl.idade( p_dat_nasc );
end if;
end;

select nom_alu, dat_nasc,
f_obter_idade( dat_nasc ) idade
from academico.alunos
where rownum <= 10;
Prof. Arquimedes Lima 105
Parmetro DEFAULT
create or replace package pkg_bibl is
/* Funo que obtm a idade em relao a uma data
especfica passada como parmetro */
function idade( p_dat_nasc date,
p_dat_ref date default sysdate )
return number;
end;

create or replace package body pkg_bibl is
function idade( p_dat_nasc date,
p_dat_ref date default sysdate)
return number
is begin
return trunc( months_between( p_dat_ref,
p_dat_nasc ) / 12 );
end;
end;
Prof. Arquimedes Lima 106
Sobrecarga de Componentes
Permite que o desenvolvedor utilize o mesmo nome para diferentes
rotinas dentro de um pacote

Requer que os parmetros formais das rotinas difiram em nmero
ordem ou famlia de tipos

Permite que haja mais flexibilidade

Somente rotinas locais ou empacotadas podem ser sobrecarregadas
Prof. Arquimedes Lima 107
Sobrecarga de Componentes
create or replace package pkg_bibl is

/* Funo que obtm a idade tomando com base
a data atual */
function idade( p_dat_nasc date ) return number;

/* Funo que obtm a idade em relao a uma data
especfica passada como parmetro */
function idade( p_dat_nasc date,
p_dat_ref date ) return number;

end;
Prof. Arquimedes Lima 108
Sobrecarga de Componentes
create or replace package body pkg_bibl is
---------------------------------------------------
function idade( p_dat_nasc date,
p_dat_ref date ) return number
is begin
return trunc( months_between( p_dat_ref,
p_dat_nasc ) / 12 );
end;
---------------------------------------------------
function idade( p_dat_nasc date ) return number
is begin
return idade( p_dat_nasc, sysdate );
end;
end;
Prof. Arquimedes Lima 109
Exerccios
Crie uma package (pkg_bibgeral) contendo os
procedimento e funes criados nos exerccios
anteriores. (questo 11 da lista de exerccios)

Prof. Arquimedes Lima 110
Packages e Sesses
O estado (variveis) definidos em uma package so persistentes
durante a sesso do usurio

O cdigo da package compartilhado entre as sesses, mas o estado
no

Sobre as sesses podemos afirmar que:
O estado de uma varivel de pacote persiste ao longo das
transaes de uma sesso
O estado no persiste de uma sesso para outra de um mesmo
usurio
O estado no persiste de um usurio para outro;

Prof. Arquimedes Lima 111
Packages e Sesses
A persistncia dos dados durante a sesso pode ser utilizada como
mecanismo para implementao de recursos avanados de segurana
e BD ativos

Os pacotes permitem a definio de rotinas e dados, sendo que a
rea de memria utilizada pelas packages no compartilhada entre
sesses diferentes

Cada sesso tem uma rea privada para os dados de uma package ,
mesmo que o seu cdigo esteja compartilhado
Prof. Arquimedes Lima 112
Exemplo Uso de Sesso

/* Especificao do PACOTE */
create or replace package pkg_teste
is
function obter_nome return varchar2;
procedure setar_nome( p_valor varchar2 );
end;
Prof. Arquimedes Lima 113
Exemplo Uso de Sesso
/* Corpo do pacote */
create or replace package body pkg_teste
is
v_nome varchar2(30);

procedure setar_nome( p_valor varchar2 )
is begin
v_nome := p_valor;
end;

function obter_nome return varchar2
is begin
return v_nome;
end;
end;
Prof. Arquimedes Lima 114
Exemplo Uso de Sesso
Sesso 01
begin
pkg_teste.setar_nome( 'Teste sesso 01' );
end;

select pkg_teste.obter_nome from dual;

Sesso 02
begin
pkg_teste.setar_nome( 'Teste sesso 02' );
end;

select pkg_teste.obter_nome from dual;

Prof. Arquimedes Lima 115
Exemplo PRODUTOS_PKG
Prof. Arquimedes Lima 116
Removendo uma Package
Utilize o comando DROP PACKAGE

Sintaxe:
DROP PACKAGE [BODY] <nome do pacote>;

Se a clusula BODY for especificada, apenas o corpo excludo

Exemplos

DROP PACKAGE PKG_BIBL;
DROP PACKAGE BODY PKG_BIBL;

Prof. Arquimedes Lima 117
Vantagens das Packages
Modularidade

Projeto de aplicaes mais simples de codificar

Informaes ocultas, ou seja, construes relacionadas a
encapsulamento

As construes privadas esto ocultas e inacessveis

Toda a codificao est escondida no corpo
Prof. Arquimedes Lima 118
Vantagens das Packages

Funcionalidade ampliada: persistncia de variveis e cursores


Melhor desempenho:
O pacote inteiro carregado na memria quando feita a primeira
referncia
Somente uma cpia do cdigo na memria para todos os usurios


Sobrecarga de componentes

Prof. Arquimedes Lima 119
Gatilhos (Triggers)
Bloco nomeado orientado a eventos;

Diferentemente dos pacotes, funes e procedimento
armazenados no podem ser chamados diretamente;

Sob determinada evento e condio algumas aes
podem ser tomadas:
Lanamento de uma exceo abortando a operao
de acordo com a situao;
Realizar outras opes relacionadas a manuteno da
base de dados;
Prof. Arquimedes Lima 120
Tipos de Gatilhos
Prof. Arquimedes Lima 121
BEFORE
E
X
E
C
.

D

M

L

AFTER
STATEMENT
(Sentena)
STATEMENT
(Sentena)
ROW
(Linha)
ROW
(Linha)
1
2
3
4
5
Sintaxe Bsica Trigger
CREATE [OR REPLACE] TRIGGER <nome_gatilho>
{BEFORE | AFTER} <eventos>
ON <nome_da_tabela>
[FOR EACH ROW]
<bloco_PLSQL_codificao_gatilho>

<eventos> ::= <evento> ( OR <evento> )*

<evento> ::= INSERT | DELETE |
UPDATE [ OF <lista_colunas> ]



Prof. Arquimedes Lima 122
Clusula BEFORE e AFTER
Definem o momento da execuo do gatilho em relao a
operao DML que a disparou;

Antes da execuo da operao DML (BEFORE), as
restries declarativas e modificaes ainda no foram
efetuados;

As informaes tratadas nos gatilhos de AFTER tm uma
melhor garantia j foram submetidas as restries
declarativas;
Prof. Arquimedes Lima 123
Definies
Podemos definir que uma sentena um comando SQL
submetido ao SGBD;

Uma nica sentena pode modificar uma ou vrias linhas
da tabela;

Exemplo:

INSERT INTO ALUNOS
SELECT * FROM ALUNOS_BKP;
Prof. Arquimedes Lima 124
Clusula FOR EACH ROW

Caso seja definida para a trigger indica que sua execuo
acontecer uma vez para cada linha modificada pela
sentena, ou seja, uma trigger de linha (ROW);

A omisso desta clusula indica que o gatilho (trigger)
de sentena (STATEMENT), sendo executada uma nica
vez para cada comando SQL que acione o evento da
trigger;
Prof. Arquimedes Lima 125
Pseudo Registros OLD/NEW
Nos gatilhos de linha possvel obter os valores da linha
mantida pela operao atravs dos registros implcitos
OLD e NEW;

Sua utilizao semelhante a construo %ROWTYPE;

O registro OLD possui os valores anteriores a mudana e
so visveis somente nas operaes de DELETE e
UPDATE;

Exemplos: :new.mat_alu
:old.status


Prof. Arquimedes Lima 126
Pseudo Registros OLD/NEW
O NEW possui os valores novos provenientes das
operaes de INSERT e UPDATE;

Os dados do registro NEW s podem ser alterados nas
triggers de BEFORE ROW;

Os registos OLD jamais podem ser modificados;


Prof. Arquimedes Lima 127
Tipos de Gatilhos
Prof. Arquimedes Lima 128
BEFORE
E
X
E
C
.

D

M

L

AFTER
STATEMENT
(Sentena)



STATEMENT
(Sentena)
ROW
(Linha)
ROW
(Linha)
1
2
3
4
5
Executada
uma nica
vez;
Executada
uma nica
vez;
Executada p/
cada linha
afetada;
Pode acessar
OLD e NEW;
Permite
modificar o
NEW;
Executada p/
cada linha
afetada;
Acessa OLD
e NEW;
No modifica
NEW;

Exemplo BEFORE Statement
CREATE OR REPLACE TRIGGER PRODUTOS_BIUDS
BEFORE DELETE OR INSERT OR UPDATE
ON PRODUTOS
begin
dbms_output.put_line( '1. PRODUTOS_BIUDS' );
end;
/

Prof. Arquimedes Lima 129
Exemplo BEFORE ROW
CREATE OR REPLACE TRIGGER PRODUTOS_BIUD
BEFORE DELETE OR INSERT OR UPDATE
ON PRODUTOS
FOR EACH ROW
begin
dbms_output.put_line( '2. PRODUTOS_BIUD' );
end;
/

Prof. Arquimedes Lima 130
Exemplo AFTER ROW
CREATE OR REPLACE TRIGGER PRODUTOS_AIUD
AFTER DELETE OR INSERT OR UPDATE
ON PRODUTOS
FOR EACH ROW
begin
dbms_output.put_line( '3. PRODUTOS_AIUD' );
end;
/
Prof. Arquimedes Lima 131
Exemplo AFTER STATEMENT
CREATE OR REPLACE TRIGGER PRODUTOS_AIUDS
AFTER DELETE OR INSERT OR UPDATE
ON PRODUTOS
DECLARE
begin
dbms_output.put_line( '4. PRODUTOS_AIUDS' );
end;
/

Prof. Arquimedes Lima 132
Sequncia dos Eventos
SQL> insert into produtos
values ( 1, 'P1', 'A', null );

1 row inserted

1. PRODUTOS_BIUDS -> Before Statement Trigger
2. PRODUTOS_BIUD -> Before Row Trigger
3. PRODUTOS_AIUD -> After Row Trigger
4. PRODUTOS_AIUDS -> After Statement Trigger

Prof. Arquimedes Lima 133
Eventos x Operaes em Massa
SQL> select count(*) from produtos_temp;

COUNT(*)
----------
4


SQL> insert into produtos
select * from produtos_temp;

4 rows inserted
Prof. Arquimedes Lima 134
Eventos x Operaes em Massa
Prof. Arquimedes Lima 135
SQL> insert into produtos
select * from produtos_temp;

4 rows inserted
1. PRODUTOS_BIUDS
2. PRODUTOS_BIUD
3. PRODUTOS_AIUD
2. PRODUTOS_BIUD
3. PRODUTOS_AIUD
2. PRODUTOS_BIUD
3. PRODUTOS_AIUD
2. PRODUTOS_BIUD
3. PRODUTOS_AIUD
4. PRODUTOS_AIUDS
Before Statement
After Statement
After Row
Before Row
Variveis Implcitas
So variveis booleadas que podem ser utilizadas no
corpo do gatilho e indica qual o evento que est
ocorrendo no banco de dados:

INSERTING: Evento de incluso;

UPDATING: Evento de atualizao;

DELETING: Evento de excluso;


Prof. Arquimedes Lima 136
Trigger Before Statement
CREATE OR REPLACE TRIGGER PRODUTOS_BIUDS
BEFORE DELETE OR INSERT OR UPDATE
ON PRODUTOS
declare
v_tot pls_integer;
begin
select count(*) into v_tot
from produtos;

dbms_output.put_line( 'Total prod. antes sentena: '||v_tot );
end;
/

Prof. Arquimedes Lima 137
Trigger Before Row
CREATE OR REPLACE TRIGGER PRODUTOS_BIUD
BEFORE DELETE OR INSERT OR UPDATE
ON PRODUTOS
FOR EACH ROW
begin
if inserting then

if :new.status is NULL then
:new.status := 'A';
end if;

select seq_produto.nextval into :new.codigo
from dual;
end if;

end;
/

Prof. Arquimedes Lima 138
Trigger After Row

CREATE OR REPLACE TRIGGER PRODUTOS_AIUD
AFTER DELETE OR INSERT OR UPDATE
ON PRODUTOS
FOR EACH ROW
begin
if updating and :old.status<>:new.status then
raise_application_error( -20000, Alterao de status:
||:old.status||;||
:new.status );
end if;
end;
/

Prof. Arquimedes Lima 139
Trigger After Stament
Prof. Arquimedes Lima 140
CREATE OR REPLACE TRIGGER PRODUTOS_AIUDS
AFTER DELETE OR INSERT OR UPDATE
ON PRODUTOS
declare
v_tot pls_integer;
begin
select count(*) into v_tot
from produtos;

dbms_output.put_line( 'Total prod. aps sentena: '||v_tot );
end;
/

Estado dos Dados - Triggers
Os comandos SELECT executados em uma trigger
BEFORE STATEMENT enxergam o banco de dados sem
nenhuma das modificaes geradas pela sentena;

Nos gatilhos de AFTER STATEMENT, os comandos
SELECT j realizam a leitura com as modificaes,
mesmo que estas sejam abortadas por uma exceo
posteriormente;

Para as triggers de linha, no permitido executar uma
consulta sob os dados da tabela para qual a trigger
definida;
Prof. Arquimedes Lima 141
Estado dos Dados - Triggers

Se um comando SELECT for realizado no gatilho de linha,
ou em qualquer rotina chamada por ela diretamente ou
indiretamente, gerada uma exceo chamada de
MUTATING TABLE;

A exceo para regra a trigger de BEFORE INSERT de
linha, cuja seleo no visualiza as modificaes na
base de dados;
Prof. Arquimedes Lima 142
Tipos de Gatilhos
Prof. Arquimedes Lima 143
BEFORE
E
X
E
C
.

D

M

L

AFTER
STATEMENT



STATEMENT
ROW ROW
1 2
3 4
5
Executada
uma nica
vez;
Visualiza o
BD sem
alterao
Executada
uma nica
vez;
Visualiza o
BD j
alterado
Executada p/
cada linha
afetada;
Pode acessar
OLD e NEW;
Permite
modificar o
NEW;
No permite
SELECT na
tab. Base
Before insert
permite
SELECT

Executada p/
cada linha
afetada;
Acessa OLD
e NEW;
No modifica
NEW;
No admite
SELECT na
tabela base

Exemplo de Tabela Mutante
Prof. Arquimedes Lima 144
CREATE TABLE mutante
( mutant_id NUMBER
, mutant_name VARCHAR2(20));

-- Incluso das "tartarugas ninjas"
INSERT INTO mutante VALUES (1,'Donatello');
INSERT INTO mutante VALUES (2,'Leonardo');
INSERT INTO mutante VALUES (3,'Michelangelo');
INSERT INTO mutante VALUES (4,'Raphael');
Exemplo Tabela Mutante
CREATE OR REPLACE TRIGGER mutante_ad
AFTER DELETE ON mutante
FOR EACH ROW
DECLARE
v_tot NUMBER;
BEGIN
SELECT COUNT(*) INTO v_tot
FROM mutante;

dbms_output.put_line('Total mutantes:['||v_tot||']');
END;
/

Prof. Arquimedes Lima 145
Exemplo Tabela Mutante
SQL> delete from mutante where mutant_id = 3;

delete from mutante where mutant_id = 3

ORA-04091: a tabela SYSTEM.MUTANTE mutante;
talvez o gatilho/funo no possa localiz-la
ORA-06512: em "SYSTEM.MUTANTE_AD", line 4
ORA-04088: erro durante a execuo do gatilho
'SYSTEM.MUTANTE_AD'

Prof. Arquimedes Lima 146
Estudo de Caso Exemplo
Verifique a tabela de cursos:

SQL> desc academico.cursos;
Name Type Nullable Default Comments
--------- ------------ -------- ------- --------
COD_CURSO NUMBER(3)
NOM_CURSO VARCHAR2(40)
TOT_CRED NUMBER(3)
IDT_PROF NUMBER(6) Y

Elabore um gatilho que implemente a seguinte regra: Um
professor s pode coordenar no mximo dois cursos;
Prof. Arquimedes Lima 147
Estudo de Caso Exemplo
Essa validao pode ser implementada na trigger de
linha?

Nas triggers de linha possvel saber, atravs das
variveis OLD e NEW, as linhas que esto sendo
modificadas, mas no podemos acessar a tabela em
mutao;

Na trigger de sentena, possvel acessar a tabela, mas
no so conhecidas as linhas que sofreram modificao;

Como solucionar?
Prof. Arquimedes Lima 148
Estudo de Caso Exemplo
Soluo: Utilizar um vetor em memria em que a trigger
de linha informe a trigger de sentena quais os dados que
devem ser validados;

Prof. Arquimedes Lima
149
BEFORE AFTER
STATEMENT
(Sentena)



STATEMENT
(Sentena)
ROW
(Linha)
ROW
(Linha)
1
2 3
4
5
Iniciar vetor
Obtm os
dados do
vetor
Limpa o vetor
Incluso dos
dados
modificados
no vetor

Vetor
S

Q

L

Resoluo Estudo de Caso
create or replace package CURSOS_PKG is
/* ======================================================= */
function obter_total_cursos( p_idt_prof number ) return number;

/* ======================================================= */
procedure iniciar_lista;

/* ======================================================= */
procedure adicionar_curso( p_cod_curso number,
p_idt_prof number );

/* ======================================================= */
procedure obter_dados( p_pos number,
p_cod_curso out number,
p_idt_prof out number );

/* ======================================================= */
function obter_total_itens return number;
end CURSOS_PKG;
Prof. Arquimedes Lima 150
Resoluo Estudo de Caso
create or replace package body CURSOS_PKG is

TYPE t_reg_curso IS RECORD
( cod_curso cursos.cod_curso%type,
idt_prof cursos.idt_prof%type );

type t_lista_cursos
is table of t_reg_curso index by pls_integer;

v_lista_curso t_lista_cursos;

/* ======================================================= */
function obter_total_cursos( p_idt_prof number ) return number
is
v_tot pls_integer;
begin
select count(*) into v_tot
from cursos
where idt_prof = p_idt_prof;

return v_tot;
end;

Prof. Arquimedes Lima 151
Resoluo Estudo de Caso
/* ======================================================= */
function obter_posicao( p_cod_curso number,
p_idt_prof number ) return binary_integer
is
v_pos pls_integer := -1;
begin
for i in 1 .. v_lista_curso.count loop
if v_lista_curso(i).cod_curso = p_cod_curso and
v_lista_curso(i).idt_prof = p_idt_prof then
v_pos := i;
exit;
end if;
end loop;

return v_pos;
end;

/* ======================================================= */
procedure iniciar_lista
is begin
v_lista_curso.delete;
end;
Prof. Arquimedes Lima 152
Resoluo Estudo de Caso
/* ======================================================= */
procedure adicionar_curso( p_cod_curso number,
p_idt_prof number )
is
v_pos pls_integer;
begin

v_pos := obter_posicao( p_cod_curso, p_idt_prof );

if v_pos = -1 then
v_pos := v_lista_curso.COUNT + 1;
v_lista_curso( v_pos ).cod_curso := p_cod_curso;
v_lista_curso( v_pos ).idt_prof := p_idt_prof;
end if;

end;
Prof. Arquimedes Lima 153
Resoluo Estudo de Caso
/* ======================================================= */
procedure obter_dados( p_pos number,
p_cod_curso out number,
p_idt_prof out number )
is begin
if p_pos not between 1 and v_lista_curso.count then
p_cod_curso := null;
p_idt_prof := null;
else
p_cod_curso := v_lista_curso( p_pos ).cod_curso;
p_idt_prof := v_lista_curso( p_pos ).idt_prof;
end if;
end;

/* ======================================================= */
function obter_total_itens return number
is begin
return v_lista_curso.count;
end;

end CURSOS_PKG;
Prof. Arquimedes Lima 154
Resoluo Estudo de Caso
-- Before statement (insert, update)
create or replace trigger cursos_bius
before insert or update
on CURSOS
begin
/* Inicializa o vetor */
cursos_pkg.iniciar_lista();
end;
Prof. Arquimedes Lima 155
Resoluo Estudo de Caso
-- After row (insert, update)
create or replace trigger cursos_aiu
after insert or update
on CURSOS
for each row
begin
if ( ( inserting ) or
( updating and nvl(:old.idt_prof,-1)<>
nvl(:new.idt_prof,-1) ) ) and
( :new.idt_prof is not null ) then
/* Adio dos dados na sesso para validao das
triggers de sentena */
cursos_pkg.adicionar_curso( :new.cod_curso,
:new.idt_prof );
end if;
end;
Prof. Arquimedes Lima 156
Resoluo Estudo de Caso
create or replace trigger cursos_aius
after insert or update on CURSOS
declare
v_cod_curso cursos.cod_curso%type;
v_idt_prof cursos.idt_prof%type;
begin
for v_pos in 1 .. cursos_pkg.obter_total_itens loop
cursos_pkg.obter_dados( v_pos, v_cod_curso, v_idt_prof );

if cursos_pkg.obter_total_cursos( v_idt_prof ) > 2 then
raise_application_error( -20000, 'O coordenador j est '||
'vinculado a quantidade '||
'limite de cursos - '||
'Curso: '||v_cod_curso );
end if;
end loop;

/* Inicializa o vetor */
cursos_pkg.iniciar_lista();
exception
when others then
/* Inicializa o vetor */
cursos_pkg.iniciar_lista();
raise;
end;
Prof. Arquimedes Lima 157
Comandos teis - Gatilhos
Remover
DROP TRIGGER <nome_do_gatilho>;
Desabilitar
ALTER TRIGGER <nome_do_gatilho> DISABLE;
Habilitar
ALTER TRIGGER <nome_do_gatilho> ENABLE;
Recompilar
ALTER TRIGGER <nome_do_gatilho> COMPILE;
Consultar situao do gatilho e cdigo fonte
USER_TRIGGERS e USER_SOURCE

Prof. Arquimedes Lima 158
Gatilhos: Consideraes Finais
A sentena SQL somente ser executada com sucesso
se todas as triggers e validaes envolvidas no gerarem
excees;

Caso seja realizada disparado uma sentena de
atualizao na trigger de sentena, por exemplo, e logo
em seguida for emitida uma exceo todas as operaes
so desfeitas;

Nos gatilhos no so permitidos: Commits e Rollbacks;
Prof. Arquimedes Lima 159
Triggers de Instead Of
Possibilidade de realizar manuteno em vises;
Devemos obedecer as seguintes regras:
Na incluso todos os campos obrigatrios devem ser
projetados;
No permitido para sentenas SQL que utilizam
DISTINCT ou GROUP BY;
Vises que fazem acesso a mais de uma tabela no
podem sofrer alteraes DML;
Vises que possuam operadores de conjunto no
podem ser alteradas;
No poder ser alterada para colunas calculadas;

Prof. Arquimedes Lima 160
Triggers de Instead Of
No so gatilhos de INSERT, UPDATE ou DELETE;

So gatilhos de INSTEAD OF;

Permitem desenvolvimento de um gatilho com objetivo de
escrever toda a lgica de manuteno de vises no
atualizveis;

Quando, por exemplo, um INSERT disparado em uma
viso a lgica que insero dos dados

Prof. Arquimedes Lima 161
Triggers de Instead Of
Uma trigger de Instead Of pode ser considerada como
um gatilho de linha;
Os valores OLD e NEW esto disponveis;
Exemplo:

create or replace view v_pessoas as
select 'A' as "TIPO", mat_alu as "CODIGO", cod_curso,
nom_alu as "NOME"
from alunos
union
select 'P' as "TIPO", cod_prof as "CODIGO", cod_curso,
nom_prof as "NOME"
from professores


Prof. Arquimedes Lima 162
Exemplo Trigger Instead Of
create or replace trigger v_pessoas_iid
instead of insert or delete on v_pessoas
declare
begin
if inserting then
if :new.tipo = 'P' then
insert into professores
( cod_prof, cod_curso, nom_prof )
values
( :new.codigo, :new.cod_curso, :new.nome );
elsif :new.tipo = 'A' then
insert into alunos
( mat_alu, cod_curso, dat_nasc, tot_cred, mgp, nom_alu )
values
( :new.codigo, :new.cod_curso, '01/01/1990', 0, 0, :new.nome );
else
raise_application_error( -20000, 'Tipo de pessoa invlida' );
end if;
else
if :old.tipo = 'P' then
delete from professores
where cod_prof = :old.codigo;
elsif :old.tipo = 'A' then
delete from alunos
where mat_alu = :old.codigo;
end if;
end if;
end;

Prof. Arquimedes Lima 163
Exerccio
1. Crie uma viso V_ALUNOS que possua todos os campos da
tabela alunos e mais o cdigo e nome do curso do aluno
vinculado. Depois de criar a viso, crie uma trigger de Instead
Of de insert, update e delete. Quando for feito um insert
deve-se verificar se o curso j existe, caso no exista deve ser
includo, caso exista deve ter o seu nome atualizado. Depois
da incluso do curso deve-se incluir o aluno, vinculando-o
automaticamente ao curso. No caso do update, deve-se
atualizar a linha da tabela de alunos e a linha da tabela de
cursos conforme os valores passados na viso. No caso do
delete deve-se primeiramente excluir o aluno e depois excluir
o curso. Se algum outro aluno j possuir vnculo com este
curso a excluso no deve ser realizada.

Prof. Arquimedes Lima 164