PL-SQL-Aula-02
Click here to load reader
-
Upload
jairson-monteiro -
Category
Documents
-
view
14 -
download
0
description
Transcript of PL-SQL-Aula-02
1
Aula 2 de PL/SQL – Anotações (28/07/12)
Cursor Explícito
Cursor é uma área de memória onde as linhas são produzidas e armazenadas. Um ponteiro diz qual linha tem que
ser extraída em determinado momento.
Para usar cursor é preciso:
Declarar
Abrir
Ler
Fechar
Exemplo:
Faça um bloco anônimo pl sql que insira na tabela relatorio o id do produto e o nome dos produtos cujo preço
sugerido seja maior que o preço sugerido médio de todos os produtos.
declare
v_id c_produto.id%type;
v_nome c_produto.nome%type;
cursor c_prod is
select id, nome
from c_produto
where preco_atacado_sugerido > (select avg(preco_atacado_sugerido)
from c_produto);
begin
delete from relatorio;
open c_prod; -- aqui o select do cursor (lá no declare) é executado.
fetch c_prod into v_id, v_nome; -- transfere os valores do cursor para as variáveis.
insert into relatorio values (v_id, v_nome);
close c_prod; -- encerra o cursor e libera a memória.
end;
Aqui acima há um erro, pois só está retornando uma linha para a tabela relatório.
2 Atributos do cursor:
%isopen (verdadeiro se o cursor está aberto, falso se o cursor está fechado).
%rowcount (contagem de quantas linhas foram tiradas do cursor (quantos fetch já foram executados)).
%found e %notfound (ambos podem ser só true ou false, mas sempre inversos entre si. Se o fetch
encontrar uma linha , found fica true e not found fica false).
Segue a resolução CORRETA do exemplo anterior:
declare
v_id c_produto.id%type;
v_nome c_produto.nome%type;
cursor c_prod is
select id, nome
from c_produto
where preco_atacado_sugerido > (select avg(preco_atacado_sugerido)
from c_produto);
begin
delete from relatorio;
open c_prod; -- aqui o select do cursor (lá no declare) é executado.
for v_i in 1..10 loop
fetch c_prod into v_id, v_nome; -- transfere os valores do cursor para as variáveis.
exit when c_prod%notfound; -- sai do laço quando o notfound for true, ou seja, quando o último fetch dá
linha em branco.
insert into relatorio values (v_id, v_nome);
end loop;
close c_prod; -- encerra o cursor e libera a memória.
end;
É necessário o laço, pois o comando fetch só retorna uma linha.
É necessário o exit ... , pois se o resultado for menor que o tamanho do laço, gera linhas repetidas como
resposta.
declare
cursor c_reg is
select * from c_regiao;
r_reg c_regiao%rowtype;
begin
delete mensagem;
open c_reg;
3
loop
fetch c_reg into r_reg;
exit when c_reg%notfound;
insert into mensagem
values (r_reg.nome);
end loop;
close c_reg;
commit;
end;
CURSOR FOR
O mesmo código acima, pelo CURSOR FOR:
-- Cursor FOR
declare
cursor c_reg is
select * from c_regiao;
r_reg c_regiao%rowtype;
begin
delete mensagem;
for r_reg in c_reg loop -- declara, dá o fetch, testa o not found e dá o close
insert into mensagem
values (r_reg.nome);
end loop;
commit;
end;
Mas o cursor for pode dar erro se o tipo de variável não for tipo primário.
Exemplos de uso de cursor explícito:
declare
v_id c_produto.id%type;
v_nome c_produto.nome%type;
cursor c_prod is
select id, nome
4 from c_produto
where preco_atacado_sugerido (select avg(preco_atacado_sugerido) from c_produto);
begin
Open c_prod;
loop
fetch c_prod into v_id, v_nome;
exit when c_prod%notfound;
insert into mensagem values (v_id, v_nome);
end loop;
close c_prod;
end;
--Solução com parâmetro no cursor
declare
v_id c_produto.id%type;
v_nome c_produto.nome%type;
v_media float;
cursor c_prod (p_media number) is
select id, nome
from c_produto
where preco_atacado_sugerido p_media;
begin
select avg(preco_atacado_sugerido) into v_media from c_produto;
Open c_prod(v_media);
loop
fetch c_prod into v_id, v_nome;
exit when c_prod%notfound;
insert into mensagem values (v_id, v_nome);
end loop;
close c_prod;
end;
--Solução com comparação no loop
declare
r_prod c_produto%rowtype;
v_media float;
cursor c_prod is
select *
from c_produto;
5
begin
select avg(preco_atacado_sugerido) into v_media from c_produto;
open c_prod;
loop
fetch c_prod into r_prod;
exit when c_prod%notfound;
if r_prod.preco_atacado_sugerido v_media then
insert into mensagem values (r_prod.id, r_prod.nome);
end if;
end loop;
close c_prod;
end;
Funções
Uma função é um bloco nomeado que funciona como qualquer outra função de linguagens de programação.
Só possui um valor de saída. Mas pode ter diversos de entrada.
Quando criar funções, mude o layout do PL/SQL developer:
6 Criando uma função:
create or replace function par_impar (or replace pode ser utilizado ou não)
Uma função não pode ter o mesmo nome de uma tabela.
Não é recomendável que se dê o PRIMEIRO COMANDO incluindo o termo OR REPLACE, pois se já existir uma função
de mesmo nome, a anterior será sobrescrita.
Não existe ALTER FUNCTION.
Para apagar a função, utiliza-se DROP FUNCTION.
Se houver interesse em alterar uma função, ou apaga-se a função e cria-se uma nova, ou utiliza-se CREATE OR
REPLACE FUNCTION.
Dentro de uma função, se um comando return for executado, nada após este comando será lido.
Exemplo de uma função:
CREATE OR REPLACE FUNCTION PAR_IMPAR(P_NR NUMBER) RETURN VARCHAR IS
BEGIN
IF MOD(P_NR, 2) = 0 THEN
RETURN 'numero par';
ELSE
RETURN 'numero ímpar';
END IF;
END;
Para testar a função (dar um select, por exemplo),mude de janela em Windows/ SQL Window.
Exemplo:
select par_impar(3) from dual;
Dual é uma tabela de sistema do Oracle, que possui apenas uma linha com valor X, numa coluna chamada DUMMY.
Outro exemplo de execução da função par_impar:
select id, par_impar(id) from c_empr;
Faça uma função denominada calc_sal_anual que receba o salário de um empregado e devolva o seu salario anual.
O Salario anual é calculado pela formula:
Salario_anual = Salario_mensal * 40 /3
7
CREATE OR REPLACE FUNCTION SAL_ANUAL(P_SAL NUMBER) RETURN VARCHAR2 IS
V_SAL_ANUAL REAL;
V_RESULT VARCHAR2(100);
BEGIN
V_SAL_ANUAL := ROUND(P_SAL * 40 / 3, 2); -- round (cálculo, arredondamento da resp. em 2 casas decimais)
IF TRUNC(V_SAL_ANUAL) = ROUND(P_SAL * 40 / 3, 2) THEN -- se for inteiro, inclui ',00'
V_RESULT := 'R$ ' || V_SAL_ANUAL || ',00';
ELSE
V_RESULT := 'R$ ' || V_SAL_ANUAL;
END IF;
RETURN V_RESULT;
END;
Agora exemplo de select utilizando esta função acima e a função par_impar ao mesmo tempo:
select id, par_impar(id) as tipo, salario, sal_anual(salario) as "salario anual" from c_empr
As funções ficam salvas no BD: