PL-SQL-Aula-02

7

Click here to load reader

description

oracle plsql

Transcript of PL-SQL-Aula-02

Page 1: 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.

Page 2: PL-SQL-Aula-02

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;

Page 3: PL-SQL-Aula-02

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

Page 4: PL-SQL-Aula-02

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;

Page 5: PL-SQL-Aula-02

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:

Page 6: PL-SQL-Aula-02

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

Page 7: PL-SQL-Aula-02

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: