You are on page 1of 7

1

Aula 2 de PL/SQL Anotaes (28/07/12)


Cursor Explcito
Cursor uma rea de memria onde as linhas so produzidas e armazenadas. Um ponteiro diz qual linha tem que ser extrada em determinado momento.

Para usar cursor preciso: Declarar Abrir Ler Fechar

Exemplo: Faa um bloco annimo pl sql que insira na tabela relatorio o id do produto e o nome dos produtos cujo preo sugerido seja maior que o preo sugerido mdio 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 variveis. insert into relatorio values (v_id, v_nome); close c_prod; -- encerra o cursor e libera a memria. end;

Aqui acima h um erro, pois s est retornando uma linha para a tabela relatrio.

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 resoluo 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 variveis. exit when c_prod%notfound; -- sai do lao 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 memria. end;

necessrio o lao, pois o comando fetch s retorna uma linha. necessrio o exit ... , pois se o resultado for menor que o tamanho do lao, 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 cdigo 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 varivel no for tipo primrio.

Exemplos de uso de cursor explcito:


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 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; (select avg(preco_atacado_sugerido) from c_produto);

--Soluo com parmetro 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 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;

p_media;

--Soluo com comparao 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;

Funes
Uma funo um bloco nomeado que funciona como qualquer outra funo de linguagens de programao. S possui um valor de sada. Mas pode ter diversos de entrada. Quando criar funes, mude o layout do PL/SQL developer:

6 Criando uma funo:


create or replace function par_impar (or replace pode ser utilizado ou no)

Uma funo no pode ter o mesmo nome de uma tabela. No recomendvel que se d o PRIMEIRO COMANDO incluindo o termo OR REPLACE, pois se j existir uma funo de mesmo nome, a anterior ser sobrescrita.

No existe ALTER FUNCTION.

Para apagar a funo, utiliza-se DROP FUNCTION.

Se houver interesse em alterar uma funo, ou apaga-se a funo e cria-se uma nova, ou utiliza-se CREATE OR REPLACE FUNCTION. Dentro de uma funo, se um comando return for executado, nada aps este comando ser lido. Exemplo de uma funo:
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 funo (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 execuo da funo par_impar:


select id, par_impar(id) from c_empr;

Faa uma funo denominada calc_sal_anual que receba o salrio de um empregado e devolva o seu salario anual. O Salario anual calculado pela formula: Salario_anual = Salario_mensal * 40 /3

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 (clculo, 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 funo acima e a funo par_impar ao mesmo tempo:
select id, par_impar(id) as tipo, salario, sal_anual(salario) as "salario anual" from c_empr

As funes ficam salvas no BD: