capítulo 1: sql-psm (persistent stored modules) banco de dados ii prof. carlos eduardo pires...
Post on 16-Apr-2015
108 Views
Preview:
TRANSCRIPT
Capítulo 1: SQL-PSM (Persistent Stored Modules)
Banco de Dados IIBanco de Dados IIProf. Carlos Eduardo PiresProf. Carlos Eduardo Pires
cesp@dsc.ufcg.edu.brcesp@dsc.ufcg.edu.br
Capítulo 1: SQL-PSM 2
Motivação
Ex.: Escreva um programa Pascal que leia a matricula de um empregado e imprima as informações sobre este empregado.program Imprima;
var loop: char; matricula: integer; E: record of
nome: string[15];endereco: string[30];funcao: string[10];salario: real; end;
begin loop := ‘S’; while (loop = ‘S’) do begin writeln(‘Entre com a matricula:’); readln(matricula); $ select nome, endereço, função, salario
into :E.nome, E.endereco, :E.funcao, :E.salario where matricula = :matricula;
writeln(E.nome, :E.endereco, E.funcao, E.salario);writeln(‘Deseja ler mais empregados(S/N)?’);readln(loop);
end;end.
Uma consulta é executada a cada iteração:
E o desempenho?
Capítulo 1: SQL-PSM 3
Cursor
No programa anterior uma única tupla (ou linha) é selecionada pelo SQL embutido
Em geral, uma consulta resulta em várias tuplas Problema
SQL processa um conjunto de tuplas, enquanto que C e Pascal (ou outra linguagem host) processam uma tupla por vez
Solução Introduziu-se o conceito de cursor para permitir
processar uma tupla por vez nas linguagens hospedeiras
Capítulo 1: SQL-PSM 4
Cursor
Problema: “Impedance Mismatch” SQL trabalha com relações Linguagens de programação trabalham de forma
orientada a registro Como fazer para ler os dados de um conjunto
retornado pelo SQL em uma linguagem de programação?
Precisamos ter um mecanismos para associar os valores retornados pelo SGBD em variáveis da aplicação
Faz-se isso usando variáveis hospedeiras
Capítulo 1: SQL-PSM 5
Cursor
Ponteiro para uma única tupla do resultado da consulta (result set)
Cada cursor possui uma consulta associada, especificada como parte da operação que define o cursor
A consulta é executada quando o cursor for aberto
Em uma mesma transação, um cursor pode ser aberto ou fechado qualquer número de vezes
Pode-se ter vários cursores abertos ao mesmo tempo
Capítulo 1: SQL-PSM 6
Cursor
Sintaxe para especificação de um cursorEXEC SQL DECLARE nome-cursor
CURSOR FOR cláusula-select
Um cursor possui as seguintes operações: OPEN
Executa a consulta especificada e põe o cursor para apontar para uma posição anterior à primeira tupla do resultado da consulta
FETCH Move o cursor para apontar para próxima linha no resultado da
consulta, tornando-a a tupla corrente e copiando todos os valores dos atributos para as variáveis da linguagem hospedeira usada
CLOSE Fecha o cursor
Capítulo 1: SQL-PSM 7
OPEN
FETCH
CLOSE
SELECT ename
FROM employee
Banco de DadosKINGSMITHJOHN...
Cursor
KINGSMITHJOHN...
Cursor
KINGSMITHJOHN...
Cursor
Capítulo 1: SQL-PSM 8
Cursor
UPDATE … CURRENT OF: realiza a atualização dos atributos da tupla que está sendo apontada pelo cursor (linha corrente). Sintaxe:UPDATE tabela
SET lista de atribuições
WHERE CURRENT OF cursor
DELETE ... CURRENT OF: elimina a tupla que está sendo apontada pelo cursor (linha corrente). Sintaxe:DELETE
FROM tabela
WHERE CURRENT OF cursor
Capítulo 1: SQL-PSM 9
Um Exemplo de Uso de Cursor em CEXEC SQL BEGIN DECLARE SECTION;
char SQLSTATE[6];char titulo[101];char ano[5];
EXEC SQL DECLARE filme_cursor CURSOR FORSELECT tituloFROM filmesWHERE ano = :ano;
void main () {EXEC SQL WHENEVER SQLERROR GOTO erro;strcpy(ano,”1998”);EXEC SQL OPEN filme_cursor;while (strcmp(SQLSTATE, “02000”) != 0) {
EXEC SQL FETCH filme_cursorINTO :titulo;
printf(“%s\n”, titulo);};EXEC SQL CLOSE filme_cursor;return;erro:
printf(“Um Erro ocorreu!\n”);};
Capítulo 1: SQL-PSM 10
Exemplo Usando DELETE e UPDATE// Se empregado ganha mais de 10000 é demitido; senão tem seu // salário reduzido em 20%
void reducaodeFolhadePagamento() {
EXEC SQL BEGIN DECLARE SECTION;char SQLSTATE[6];float salario;
EXEC SQL END DECLARE SECTION;EXEC SQL DECLARE salCursor CURSOR FOR
SELECT salario FROM Empregado ;EXEC SQL OPEN salCursor;while(1) {
EXEC SQL FETCH FROM salCursor INTO :salario;
// Verifica se não há mais tuplasif (strcmp(SQLSTATE, “02000”)) break;if (salario > 10000)
EXEC SQL DELETE FROM EmpregadoWHERE CURRENT OF salCursor;
else EXEC SQL UPDATE EmpregadoSET salario = salario - salario * 0.2;WHERE CURRENT OF salCursor;
} EXEC SQL CLOSE salCursor;}
Capítulo 1: SQL-PSM 11
Scrolling Cursors
Por default, cursores movem-se do início do result set para frente (forward)
Podemos movê-los também para trás e/ou para qualquer posição no result set
Devemos acrescentar SCROLL na definição do cursor
Exemplo EXEC DECLARE meuCursor SCROLL CURSOR
FOR Empregado;
Capítulo 1: SQL-PSM 12
Scrolling Cursors
Num FETCH, podemos adicionar as seguintes opções: NEXT ou PRIOR: pega o próximo ou anterior FIRST ou LAST: obtém o primeiro ou último RELATIVE seguido de um inteiro: indica quantas
tuplas mover para frente (se positivo) ou para trás (se negativo)
ABSOLUTE seguido de um inteiro: indica a posição da tupla contando do início (se positivo) ou do final (se negativo)
Capítulo 1: SQL-PSM 13
Exercício de Sala
Sem usar a sintaxe de uma linguagem de programação (ou seja, usando o bom e velho português) escrever um código fictício para recuperar e imprimir o nome dos alunos matriculados na turma de BD2, período 2010.2
Capítulo 1: SQL-PSM 14
Motivação
Vimos anteriormente que código SQL pode ser “misturado” com o código de uma linguagem de programação
Porém, é perfeitamente possível separar Código da LP na aplicação Código SQL no BD, nesse caso precisamos dar um
“nome” ao código SQL
O código da LP faz chamadas ao código SQL através desses nomes
Capítulo 1: SQL-PSM 15
Integração Estreita com SGBDs
O uso de SQL/PSM (Stored Procedures) como PL/SQL, SQLJ, TransactSQL,…, são extensões de SQL Processadas no lado servidor da arquitetura cliente-
servidor: muito bom para o desempenho
Capítulo 1: SQL-PSM 16
Stored Procedures (SP)
Em português, procedimentos armazenados Conjuntos de comandos SQL definidos pelo
usuário que ficam armazenados num BD como um procedimento/função para eventuais processamentos
São processamentos de tarefas da aplicação que residem no SGBD ao invés de no código da aplicação (cliente)
Capítulo 1: SQL-PSM 17
Vantagens das Stored Procedures
Desempenho Ex.: Seja a consulta
SELECT codigop, nome FROM Projeto p, Alocacao a WHERE p.codproj = a.codigop
Se vários usuários realizarem esta consulta o tráfego de rede (dados e texto SQL) será alto
Se criarmos uma SP para executar a consulta, os usuários necessitarão apenas de um comando para executar a consulta anterior: EXEC nomeProcedimento;
A consulta anterior seria compilada a cada chamada, enquanto o SP contendo a consulta seria compilado uma única vez
Capítulo 1: SQL-PSM 18
Vantagens das Stored Procedures
Manutenção Facilita o gerenciamento do BD, pois a consulta é
escrita em um único lugar A manutenção torna-se mais eficaz e segura
Segurança Podemos usar SPs para limitar o acesso de alguns
usuários ao BD A maneira em que o BD pode ser modificado é
estritamente definida
Capítulo 1: SQL-PSM 19
Stored Procedures: SQL/PSM
SQL/PSM (Persistent Stored Modules) Parte do padrão SQL relativo às Stored Procedures
Cada SGBD oferece sua própria linguagem (PL/SQL, Transact/SQL, PL/pgSQL, etc.)
Em PSM, definimos módulos que são coleções de definições de funções ou procedimentos, declarações de tabelas temporárias, dentre outros
Capítulo 1: SQL-PSM 20
Stored Procedures: SQL/PSM
Criando Funções e Procedimentos
CREATE PROCEDURE <NOME> (<parâmetros>)declarações locais
corpo do procedimento;
CREATE FUNCTION <NOME> (<parâmetros>) RETURNS <tipo>
declarações locaiscorpo da função;
obs.: parâmetros são do tipo modo-nome-tipo, onde modo indica IN, OUT ou INOUT
Parâmetros em funções devem ter modo IN
Capítulo 1: SQL-PSM 21
Stored Procedures: SQL/PSM
Exemplo
CREATE PROCEDURE MudaEndereco (
IN endAntigo VARCHAR(255),
IN endNovo VARCHAR(255)
)
UPDATE Empregado
SET endereco = endNovo
WHERE endereco = endAntigo;
Capítulo 1: SQL-PSM 22
Stored Procedures: SQL/PSM
Alguns comandos 1) Chamada a um procedimento:
CALL <nome procedure> (<lista argumentos>); Obs.: CALL é aplicado apenas a Procedures (não a
Function) Esta chamada pode ser realizada de vários lugares:
Programa com SQL embutido EXEC SQL CALL calcula(:x, 3);
Como comando em outro procedimento ou função PSM: CALL calcula (10);
2) Comando de Retorno (usado apenas em funções) RETURN <expressão>; Obs.: este comando não encerra a função
Capítulo 1: SQL-PSM 23
Stored Procedures: SQL/PSM
3) Declaração de variáveis locais:
DECLARE <nome> <tipo>; 4) Comando de atribuição
SET <variável> = <expressão>; 5) Grupo de comandos:
delimitados por BEGIN e END 6) Label
Colocamos labels em comandos precedendo estes pelo nome do label e dois pontos
Capítulo 1: SQL-PSM 24
Stored Procedures: SQL/PSM
7) Comandos condicionais
IF <condição> THEN
<comandos>
ELSEIF <condição> THEN
<comandos> …
ELSE <comandos>
END IF; 8) Laços
LOOP
<Comandos>
END;
Capítulo 1: SQL-PSM 25
Stored Procedures: SQL/PSM Exemplo: função que recebe um ano e nome de estúdio
e retorna TRUE se não produziu nenhum filme naquele ano ou se aquele estúdio produziu apenas um filme preto e branco
CREATE FUNCTION PretoeBranco (p_ano int, studio char[15]) RETURNS BOOLEANIF NOT EXISTS (SELECT *
FROM Filme WHERE ano = p_ano AND nomeStudio = studio) THENRETURN TRUE;
ELSEIF 1 = (SELECT COUNT(*) FROM Filme
WHERE ano = p_ano AND nomeStudio = studio AND NOT emcores) THENRETURN TRUE;
ELSERETURN FALSE;
END IF;
Capítulo 1: SQL-PSM 26
Stored Procedures: SQL/PSMExemplo: Procedimento que calcula a duração média dos filmes de um estúdio
CREATE PROCEDURE MeanVar (IN s char[15], OUT mean REAL)DECLARE NotFound FOR SQLSTATE ‘02000’;DECLARE filmeCursor CURSOR FOR
select duracaofrom Filmewhere nomeStudio = s;
DECLARE novaDuracao INTEGER;DECLARE contaFilmes INTEGER;BEGIN
SET mean = 0.0;SET contaFilmes = 0;OPEN filmeCursor;filmeLOOP: LOOP
FETCH filmeCursor INTO novaDuracao;IF NotFound THEN
LEAVE filmeLOOPEND IF;SET contaFilmes = contaFilmes + 1;SET mean = mean + novaDuracao;
END LOOP;SET mean = mean / contaFilmes;CLOSE filmeCursor;
END;
Capítulo 1: SQL-PSM 27
Laços em PSM
Laços FORFOR <nome laço> AS <nome cursor> CURSOR FOR
<query>
DO<comandos>
END FOR;
ExemploFOR alunoLOOP AS alunoCursor CURSOR FOR
SELECT nome, idade FROM Aluno WHERE periodo = ‘2010.2’;
DO
...
END FOR;
Capítulo 1: SQL-PSM 28
Exemplo do Laço FOR
Exemplo: Mesmo procedimento anterior, usando Laço FOR
CREATE PROCEDURE MeanVar (IN s char[15], OUT mean REAL)
DECLARE contaFilmes INTEGER;
BEGIN
SET mean = 0.0;
SET contaFilmes = 0;
FOR filmeLOOP AS filmeCursor CURSOR FOR
SELECT duracao FROM Filme WHERE nomeStudio = s;
DO
SET contaFilmes = contaFilmes + 1;
SET mean = mean + duracao;
END FOR;
SET mean = mean / contaFilmes;
END;
Obs.: veja que não precisa de OPEN, FETCH e CLOSE do cursor
Capítulo 1: SQL-PSM 29
Outros Tipos de Laços em PSM
Laço WHILEWHILE <condição> DO
<comandos>
END WHILE;
REPEATREPEAT
<comandos>
UNTIL <condição>
END REPEAT;
Capítulo 1: SQL-PSM 30
Exceções em PSM
É possível testar o SQLSTATE para verificar a ocorrência de erros e tomar uma decisão, quando erros ocorram
Isto é feito através do EXCEPTION HANDLER que é associado a blocos BEGIN END (o handler aparece dentro do bloco)
Os componentes do handler são:1) Lista de exceções a serem tratadas2) Código a ser executado quando exceção ocorrer3) Indicação para onde ir depois que o handler concluir
SINTAXE: DECLARE <onde ir> HANDLER FOR <condições><comando>
As escolhas de <onde ir> são: CONTINUE EXIT (sai do bloco BEGIN .. END) UNDO
Capítulo 1: SQL-PSM 31
Exemplo de Exceções em PSM
CREATE FUNCTION getSalario (mat integer) RETURNS FLOAT
DECLARE NotFound CONDITION FOR SQLSTATE ‘02000’; DECLARE TooMany CONDITION FOR SQLSTATE ‘21000’;BEGIN
DECLARE EXIT HANDLER FOR NotFound, TooManyRETURN NULL;
RETURN (SELECT salario FROM Empregado WHERE matricula = mat);
END;
TooMany muitas linhas retornadas pelo SELECT NotFound nenhuma linha retornada pelo SELECT
Capítulo 1: SQL-PSM 32
PL/SQL – Oracle Stored Procedures
Linguagem de desenvolvimento do SGBD Oracle que “implementa” SQL/PSM (não é fiel ao padrão)
Significa “Procedural Language extensions to SQL” Permite variáveis locais, laços, condições, procedures,
consulta à relações “one tuple at a time”, etc Forma geral
DECLAREdeclarações (optativo)
BEGINcomandos executáveis; (obrigatórios)
EXCEPTIONcomandos para manipular erros (optativo)
END;
Capítulo 1: SQL-PSM 33
Oracle Stored Procedures
Código PL/SQL é feito de blocos com uma única estrutura
Existem dois tipos de blocos em PL/SQL:1. Blocos Anônimos: não possuem nomes (são como
scripts) Podem ser escritos e executados imediatamente no iSQL*Plus Podem ser usados em um trigger (gatilho)
2. Blocos Nomeados: são armazenados no banco de dados Procedures Functions Pacotes
Capítulo 1: SQL-PSM 34
Blocos Anônimos
DECLARE (opcional)/* aqui se declaram as variáveis que serão usadas no bloco */
BEGIN (obrigatório)/* define-se os comandos que dizem o que o bloco faz*/
EXCEPTION (opcional)/* define-se as ações que acontecem se uma exceção for lançado
durante a execução deste bloco */
END; (obrigatório)/
Capítulo 1: SQL-PSM 35
DECLARE
Sintaxe
Exemplos
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
DECLARE birthday DATE; age NUMBER(2) NOT NULL := 27; name VARCHAR2(13) := 'Levi'; magic CONSTANT NUMBER := 77; valid BOOLEAN NOT NULL := TRUE;
DECLARE birthday DATE; age NUMBER(2) NOT NULL := 27; name VARCHAR2(13) := 'Levi'; magic CONSTANT NUMBER := 77; valid BOOLEAN NOT NULL := TRUE;
Note que PL/SQL inclui todos tipos SQL, e outros mais…
Capítulo 1: SQL-PSM 36
Declarando Variáveis com %TYPE
Exemplos
DECLARE sname sailors.sname%TYPE; fav_boat VARCHAR2(30); my_fav_boat fav_boat%TYPE := ‘GrafSpee';...
Acessando coluna sname na tabela Sailors
Acessando outra variável
Capítulo 1: SQL-PSM 37
Criando um PL/SQL Record (Registro)
Um record é um tipo de variável que podemos definir (como ‘struct’ em C ou ‘object’ em Java)
DECLARE TYPE sailor_record_type IS RECORD (sname VARCHAR2(10), sid VARCHAR2(9), age NUMBER(3),
rating NUMBER(3)); sailor_record sailor_record_type;...BEGIN sailor_record.sname:=‘peter’; sailor_record.age:=45;…
DECLARE TYPE sailor_record_type IS RECORD (sname VARCHAR2(10), sid VARCHAR2(9), age NUMBER(3),
rating NUMBER(3)); sailor_record sailor_record_type;...BEGIN sailor_record.sname:=‘peter’; sailor_record.age:=45;…
Capítulo 1: SQL-PSM 38
Oracle Stored Procedures
São objetos armazenados no BD que usam comandos PL/SQL e SQL em seus corpos
SintaxeCREATE OR REPLACE PROCEDURE
<nome> (<lista_argumentos>)
AS / IS
<declarações>
BEGIN
<comandos PL/SQL e SQL>
END;
Atenção:
AS ou IS substituem o DECLARE
Capítulo 1: SQL-PSM 39
Oracle Stored Procedures
<Lista_argumentos> tem triplas nome-modo-tipo. Modo: IN, OUT ou IN OUT para read-only, write-only,
read/write, respectivamente. Tipos de Dados
Padrão SQL + tipos genéricos como NUMBER = qualquer tipo inteiro ou real
Como tipos nas procedures devem casar com tipos no esquema do BD, pode-se usar uma expressão da forma
tabela.campo%TYPEpara capturar o tipo corretamente
Capítulo 1: SQL-PSM 40
Exemplo de Oracle Stored Procedure
Uma procedure que inclui uma nova cerveja e seu preço no menu do bar AlviRubro
Vende (bar, cerveja, preço)
CREATE OR REPLACE PROCEDURE MenuAlviRubro (p_cerva IN Vende.cerveja%TYPE,p_preco IN Vende.preço%TYPE)
ASBEGIN
INSERT INTO Vende VALUES(‘AlviRubro’, p_cerva, p_preco);COMMIT;
END;/
Capítulo 1: SQL-PSM 41
Executando Stored Procedures
Uma chamada a uma procedure pode aparecer no corpo de um comando PL/SQLBEGIN
MenuAlviRubro('AlviRubro','Bud', 2.50);
MenuAlviRubro('AlviRubro','Carlsberg', 5.00);
END;
Uma chamada a uma procedure pode aparecer no prompt da ferramenta (iSQL*Plus) EXEC(UTE) MenuAlviRubro ('AlviRubro','Sol', 1.15);
Capítulo 1: SQL-PSM 42
Um Segundo ExemploCREATE OR REPLACE PROCEDURE p1 (p_empid IN NUMBER, p_sal OUT NUMBER)ISBEGIN SELECT salary INTO p_sal FROM employees WHERE employee_id = p_empid;END;/
CREATE OR REPLACE PROCEDURE p2IS v_sal NUMBER; v_empid NUMBER := 101;BEGIN p1(v_empid,v_sal); DBMS_OUTPUT.PUT_LINE('O empregado '||TO_CHAR(v_empid)||' recebe '||TO_CHAR(v_sal));END;/
SQL> SET SERVEROUTPUT ONSQL> EXECUTE p2O empregado 101 recebe 17000
Atenção:
Não é necessário informar o tamanho dos parâmetros
Capítulo 1: SQL-PSM 43
Oracle Stored Procedure
Atribuição de valores a variáveis é denotada por := Desvio
IF <condição> THEN <comando(s)>
ELSIF <condição> THEN<comandos(s)>
ELSE <comando(s)>
END IF; Laço
LOOP. . .
EXIT WHEN <condição>. . .
END LOOP;
Capítulo 1: SQL-PSM 44
Consultas em PL/SQL
Single-row selects permitem atribuir a uma variável o resultado de uma consulta que produz uma única tupla
Um select-from-where em PL/SQL deve ter uma cláusula INTO listando as variáveis que recebem os resultados da consulta
Ocorre erro se o select-from-where retornar mais de uma tupla; neste caso, é preciso usar um cursor
Ocorre erro também se o select-from-where retornar zero tupla
Capítulo 1: SQL-PSM 45
Single-Row SELECT
Exemplo: Encontrar o preço da cerveja Schincariol no bar AlviRubro Vende(bar, cerveja, preço)
DECLARE
p Vende.preço %TYPE;
BEGIN
SELECT preço
INTO p
FROM Vende
WHERE bar = ‘AlviRubro’
AND cerveja = ‘Schincariol’;
END;
Capítulo 1: SQL-PSM 46
Cursores
DeclaraçãoCURSOR <nome> IS
comando select-from-where O cursor aponta para cada tupla por vez da relação-
resultado da consulta select-from-where, usando um fetch statement dentro de um laço. Fetch statement:
FETCH <nome_cursor> INTOlista_variáveis;
Um laço é interrompido por: EXIT WHEN <nome_cursor>%NOTFOUND; O valor é TRUE se não houver mais tupla a apontar
OPEN e CLOSE abrem e fecham um cursor
Capítulo 1: SQL-PSM 47
Criando um Cursor
Exemplo
DECLARE
CURSOR c IS SELECT name, salary FROM customer;
v_name customer.name%TYPE;
v_salary customer.salary%TYPE;
BEGIN
open c;
fetch c into v_name, v_salary;
…
Capítulo 1: SQL-PSM 48
Exemplo
DECLARE pi constant NUMBER(8,7) := 3.1415926; area NUMBER(14,2); CURSOR rad_cursor IS SELECT * FROM rad_vals; rad_value rad_cursor%ROWTYPE;
BEGIN OPEN rad_cursor; LOOP
FETCH rad_cursor INTO rad_value; EXIT WHEN rad_cursor%NOTFOUND; area := pi * power(rad_value.radius,2); INSERT INTO areas VALUES
(rad_value.radius, area); END LOOP; CLOSE rad_cursor; COMMIT;END;
DECLARE pi constant NUMBER(8,7) := 3.1415926; area NUMBER(14,2); CURSOR rad_cursor IS SELECT * FROM rad_vals; rad_value rad_cursor%ROWTYPE;
BEGIN OPEN rad_cursor; LOOP
FETCH rad_cursor INTO rad_value; EXIT WHEN rad_cursor%NOTFOUND; area := pi * power(rad_value.radius,2); INSERT INTO areas VALUES
(rad_value.radius, area); END LOOP; CLOSE rad_cursor; COMMIT;END;
radius
3
6
8
Rad_cursor
Fetch
Rad_val
Radius AreaAREAS
3 28.27
RAD_VALS
68
113.1201.06
O código completo do exemplo está disponível no Google Groups
Capítulo 1: SQL-PSM 49
Atributos Explícitos de Cursor
Obtém informação de status sobre um cursor
Atributo Tipo Descrição
%ISOPEN Boolean Retorna TRUE se o cursor estiver aberto
%NOTFOUND Boolean Retorna TRUE se o fetch mais recente não retorna uma tupla
%FOUND Boolean Retorna TRUE se o fetch mais recente retorna uma tupla (complemento de %NOTFOUND)
%ROWCOUNT Number Retorna o total de tuplas acessadas até o momento
Capítulo 1: SQL-PSM 50
Exemplo
Uma procedure que examina o menu do bar AlviRubro e aumenta em 1.00 todos os preços que são menores que 3.00 Vende(bar, cerveja, preço)
Um simples UPDATE poderia resolver esse problema, mas mudanças mais complicadas podiam exigir uma procedure
Capítulo 1: SQL-PSM 51
ExemploCREATE PROCEDURE Aumento AS
aCerveja Vende.cerveja%TYPE;oPreço Vende.preço%TYPE;CURSOR c IS
SELECT cerveja, preçoFROM VendeWHERE bar =`AlviRubro´;
BEGINOPEN c;LOOP
FETCH c INTO aCerveja, oPreço;EXIT WHEN c%NOTFOUND;IF oPreço < 3.00 THEN
UDPATE VendeSET preço = oPreço + 1.00WHERE bar = `AlviRubro´AND cerveja = aCerveja;
END IF;END LOOP;CLOSE c;
END;
Capítulo 1: SQL-PSM 52
Tipo %ROWTYPE
Qualquer estrutura (e.g. cursores e nomes de tabela) que tem um tipo tupla pode ter seu tipo capturado com %ROWTYPE
Pode-se criar variáveis temporárias tipo tupla e acessar seus componentes como variável.componente (“dot notation”)
Muito útil, principalmente se a tupla tem muitos componentes
Capítulo 1: SQL-PSM 53
Declarando Variáveis com %ROWTYPE
Declare uma variável (registro) com o tipo de uma linha de uma tabela.
E como acessar os campos de reserves_record?
reserves_record Reserves%ROWTYPE;
reserves_record.sid:=9;
Reserves_record.bid:=877;
Tabela Reserves
Capítulo 1: SQL-PSM 54
ExemploA mesma procedure com a variável tupla cp.
CREATE PROCEDURE Aumento ASCURSOR c IS
SELECT cerveja, preçoFROM VendeWHERE bar = `AlviRubro´;
cp c%ROWTYPE;BEGIN
OPEN c;LOOP
FETCH c INTO cp;EXIT WHEN c%NOTFOUND;IF cp.preço < 3.00 THEN
UDPATE VendeSET preço= cp.preço + 1.00WHERE bar = `AlviRubro´AND cerveja = cp.cerveja;
END IF;END LOOP;CLOSE c;
END;
Capítulo 1: SQL-PSM 55
Funções
Podemos definir uma função:
CREATE FUNCTION <name> (<param_list>)
RETURN <return_type>
AS ... No corpo da função, "RETURN <expression>;"
sai (retorna) da função e retorna o valor de <expression>
Capítulo 1: SQL-PSM 56
ExemploCREATE OR REPLACE FUNCTION func01 (valor IN NUMBER)RETURN VARCHAR2ASBEGIN IF valor IN (0,1) THEN RETURN('if'); ELSIF valor IN (1,2,3) THEN RETURN('elsif'); ELSE RETURN('else'); END IF; DBMS_OUTPUT.PUT_LINE('Fui até o fim'); RETURN('Fim');END;/
SET SERVEROUTPUT ON/* Para testar com outros valores, basta substituir o parâmetro passado na função func01 */
DECLARE texto VARCHAR2(1000);BEGIN texto := func01(2); DBMS_OUTPUT.PUT_LINE(texto);END;/
Capítulo 1: SQL-PSM 57
Dica
Para descobrir quais procedures e functions você já criou:
SELECT object_type, object_name, status
FROM user_objects
WHERE object_type IN ('PROCEDURE','FUNCTION');
Capítulo 1: SQL-PSM 58
Removendo Procedures e Funções
Para remover uma stored procedure/function:
DROP PROCEDURE <procedure_name>;
DROP FUNCTION <function_name>;
Capítulo 1: SQL-PSM 59
Outras Formas de Laços
Comando FOR Permite que uma determinada sequência de
comandos seja executada n vezes
SintaxeFOR contador IN [REVERSE] valorInicial..valorFinal
LOOP
sequência de comandos
END LOOP
Capítulo 1: SQL-PSM 60
Exemplo de Comando FORCREATE OR REPLACE PROCEDURE VerificaEstoqueAS
codInicial Produto.codProduto%Type;codFinal CodInicial%Type;v_estoque Produto.estoque%Type;
BEGINSELECT Min(CodProduto), Max(codProduto)INTO codInicial, codFinalFROM Produto;
FOR contador IN codInicial..codFinal LOOPSELECT estoqueINTO v_estoqueFROM produto WHERE codProduto = contador AND estoque > 0;
DBMS_OUTPUT.PUT_LINE ('O código '|| contador || ' tem em estoque' ||
v_estoque);END LOOP;
END;
Pergunta:
E se houverem “brechas” em codProduto?
Exemplo: 1, 2, 4...
Capítulo 1: SQL-PSM 61
Exemplo de Cursor FOR
CREATE OR REPLACE PROCEDURE p10 ISBEGIN
FOR emp_rec IN (SELECT last_name, salaryFROM employeesWHERE salary >= 10000)
LOOP
DBMS_OUTPUT.PUT_LINE ('O empregado '||emp_rec.last_name||' ganha '||emp_rec.salary||' dólares por mês');
END LOOP;
END;/
SET SERVEROUTPUT ONEXEC p10
Capítulo 1: SQL-PSM 62
Outras Formas de Laços
Comando WHILEWHILE condição LOOP
ComandosEND LOOP;
ExemploDECLARE
TEN number:=10;i number_table.num%TYPE:=1;
BEGIN WHILE i <= TEN LOOP INSERT INTO number_table VALUES (i); i := i + 1; END LOOP;END;
Capítulo 1: SQL-PSM 63
Exercício
Criar uma função (calc_sal_total) que calcule o salário total de um empregado (salário fixo + comissão). A função deve receber dois valores numéricos e devolver um valor numérico.
Criar uma procedure (update_sal) que atualize o salário total de todos os empregados usando a função calc_sal_total. Um cursor deve ser usado dentro da procedure
Tabela Empregado (id, nome, salário, comissão, sal_total)
Capítulo 1: SQL-PSM 64
Pacotes
São objetos que agrupam logicamente elementos de programação PL/SQL Tipos definidos pelo usuário, variáveis, exceções
PL/SQL, cursores, procedures e funções
Um pacote possui duas partes: Especificação Corpo
Capítulo 1: SQL-PSM 65
Exemplo de Pacote
CREATE OR REPLACE PACKAGE pck_emp
IS
PROCEDURE query_emp
(in_employee_id employees.employee_id%TYPE,
out_name OUT employees.first_name%TYPE,
out_salary OUT employees.salary%TYPE,
out_phone_number OUT employees.phone_number%TYPE);
END pck_emp;
/
Capítulo 1: SQL-PSM 66
Exemplo de Pacote
CREATE OR REPLACE PACKAGE BODY pck_empIS
PROCEDURE query_emp(in_employee_id employees.employee_id%TYPE,out_name OUT employees.first_name%TYPE,out_salary OUT employees.salary%TYPE,out_phone_number OUT employees.phone_number%TYPE)ISBEGIN SELECT first_name, salary , phone_number INTO out_name, out_salary, out_phone_number FROM employees WHERE employee_id = in_employee_id; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('Empregado '||in_employee_id||' não existe'); END query_emp;
END pck_emp;/
Capítulo 1: SQL-PSM 67
Exemplo de Pacote
DECLAREaEmployee_id employees.employee_id%TYPE:=206;aFirst_name employees.first_name%TYPE;aSalary employees.salary%TYPE;aPhone_number employees.phone_number%TYPE;
BEGIN
pck_emp.query_emp(aEmployee_id,aFirst_name,aSalary,aPhone_number);DBMS_OUTPUT.PUT_LINE('aFirst_name --> '||aFirst_name);DBMS_OUTPUT.PUT_LINE('aSalary --> '||aSalary);DBMS_OUTPUT.PUT_LINE('aPhone_number --> '||aPhone_number);
END;/
Capítulo 1: SQL-PSM 68
Trigger (Gatilho)
Trecho de código armazenado executado implicitamente quando ocorre um certo evento
Criados para executar operações relacionadas
Não devem ser criados quando já existirem funcionalidades que já façam o trabalho
Capítulo 1: SQL-PSM 69
Exemplo de Trigger
Capítulo 1: SQL-PSM 70
Criando Triggers
Instante de Execução Tabela: BEFORE, AFTER Visão: INSTEAD OF
Evento: INSERT, UPDATE ou DELETE Objeto associado: tabela ou visão Tipo: linha ou sentença Cláusula WHEN: condição de restrição Corpo do trigger: bloco contendo comandos
Capítulo 1: SQL-PSM 71
Sequência de Disparo
DEPTNO10203040
DNAMEACCOUNTINGRESEARCHSALESOPERATIONS
LOCNEW YORKDALLASCHICAGOBOSTON
• Ação do TriggerAção do TriggerBEFORE statement triggerBEFORE statement trigger
BEFORE row triggerBEFORE row triggerAFTER row triggerAFTER row trigger
AFTER statement triggerAFTER statement trigger
SQL> INSERT INTO dept (deptno, dname, loc) 2 VALUES (50, 'EDUCATION', 'NEW YORK');
SQL> INSERT INTO dept (deptno, dname, loc) 2 VALUES (50, 'EDUCATION', 'NEW YORK');
• Comando DMLComando DML
Sequência de disparo de um trigger em uma tabela quando apenas uma linha é manipulada
Capítulo 1: SQL-PSM 72
Sequência de Disparo
EMPNO
7839
7698
7788
ENAME
KING
BLAKE
SMITH
DEPTNO
30
30
30
BEFORE statement triggerBEFORE statement trigger
BEFORE row triggerBEFORE row triggerAFTER row triggerAFTER row triggerBEFORE row triggerBEFORE row triggerAFTER row triggerAFTER row triggerBEFORE row triggerBEFORE row triggerAFTER row triggerAFTER row trigger
AFTER statement triggerAFTER statement trigger
SQL> UPDATE emp 2 SET sal = sal * 1.1 3 WHERE deptno = 30;
SQL> UPDATE emp 2 SET sal = sal * 1.1 3 WHERE deptno = 30;
Sequência de disparo de um trigger em uma tabela quando muitas linhas são manipuladas
Capítulo 1: SQL-PSM 73
Criando um Statement Trigger
SQL> CREATE OR REPLACE TRIGGER secure_emp
2 BEFORE INSERT ON emp
3 BEGIN
4 IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN')) OR
5 (TO_CHAR(sysdate,'HH24') NOT BETWEEN
6 '08' AND '18')
7 THEN RAISE_APPLICATION_ERROR (-20500,
8 'You may only insert into EMP during normal hours.');
9 END IF;
10 END;
11 /
SQL> CREATE OR REPLACE TRIGGER secure_emp
2 BEFORE INSERT ON emp
3 BEGIN
4 IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN')) OR
5 (TO_CHAR(sysdate,'HH24') NOT BETWEEN
6 '08' AND '18')
7 THEN RAISE_APPLICATION_ERROR (-20500,
8 'You may only insert into EMP during normal hours.');
9 END IF;
10 END;
11 /
Capítulo 1: SQL-PSM 74
Testando o Trigger secure_emp
SQL> INSERT INTO emp (empno, ename, deptno)
2 VALUES (7777, 'BAUWENS', 40);
INSERT INTO emp (empno, ename, deptno)
*
ERROR at line 1:
ORA-20500: You may only insert into EMP during normal hours.
ORA-06512: at "A_USER.SECURE_EMP", line 4
ORA-04088: error during execution of trigger
'A_USER.SECURE_EMP'
SQL> INSERT INTO emp (empno, ename, deptno)
2 VALUES (7777, 'BAUWENS', 40);
INSERT INTO emp (empno, ename, deptno)
*
ERROR at line 1:
ORA-20500: You may only insert into EMP during normal hours.
ORA-06512: at "A_USER.SECURE_EMP", line 4
ORA-04088: error during execution of trigger
'A_USER.SECURE_EMP'
Capítulo 1: SQL-PSM 75
Usando Predicados de Condição
CREATE OR REPLACE TRIGGER secure_empBEFORE INSERT OR UPDATE OR DELETE ON empBEGIN IF (TO_CHAR (sysdate,'DY') IN ('SAT','SUN')) OR (TO_CHAR (sysdate, 'HH24') NOT BETWEEN '08' AND '18') THEN IF DELETING THEN RAISE_APPLICATION_ERROR (-20502, 'You may only delete from EMP during normal hours.'); ELSIF INSERTING THEN RAISE_APPLICATION_ERROR (-20500, 'You may only insert into EMP during normal hours.'); ELSIF UPDATING ('SAL') THEN RAISE_APPLICATION_ERROR (-20503, 'You may only update SAL during normal hours.'); ELSE RAISE_APPLICATION_ERROR (-20504, 'You may only update EMP during normal hours.'); END IF; END IF;END;
Capítulo 1: SQL-PSM 76
Criando Row Triggers
SQL> CREATE OR REPLACE TRIGGER DERIVE_COMMISSION_PCT
2 BEFORE INSERT OR UPDATE OF sal ON emp
3 FOR EACH ROW
4 BEGIN
5 IF NOT (:NEW.JOB IN ('MANAGER' , 'PRESIDENT'))
6 AND :NEW.SAL > 5000
7 THEN
8 RAISE_APPLICATION_ERROR
9 (-20202, 'EMPLOYEE CANNOT EARN THIS AMOUNT');
10 END IF;
11 END;
Capítulo 1: SQL-PSM 77
Usando Qualificadores OLD e NEW
SQL>CREATE OR REPLACE TRIGGER audit_emp_values
2 AFTER DELETE OR INSERT OR UPDATE ON emp
3 FOR EACH ROW
4 BEGIN
5 INSERT INTO audit_emp_table (user_name,
6 timestamp, id, old_last_name, new_last_name,
7 old_title, new_title, old_salary, new_salary)
8 VALUES (USER, SYSDATE, :OLD.empno, :OLD.ename,
9 :NEW.ename, :OLD.job, :NEW.job,
10 :OLD.sal, :NEW.sal );
11 END;
12 /
Capítulo 1: SQL-PSM 78
Tabela audit_emp_values
USER_NAME
EGRAVINA
NGREENBE
TIMESTAMP
12-NOV-97
10-DEC-97
ID
NULL
7844
OLD_LAST_NAME
NULL
MAGEE
NEW_LAST_NAME
HUTTON
TURNER
OLD_TITLE
NULL
CLERK
NEW_TITLE
ANALYST
SALESMAN
NEW_SALARY
3500
1100
Continuação
OLD_SALARY
NULL
1100
INSERTUPDATE
Capítulo 1: SQL-PSM 79
Trigger INSTEAD OF
AplicaçãoAplicação
SQL> INSERT INTO my_view 2 . . .;
SQL> INSERT INTO my_view 2 . . .;
MY_VIEWMY_VIEW
INSTEAD OF INSTEAD OF TriggerTrigger
INSERT INSERT TABLE1TABLE1
UPDATE UPDATE TABLE2TABLE2
Capítulo 1: SQL-PSM 80
Trigger INSTEAD OF
EMPNO7836778279347566
ENAMEKINGCLARKMILLERJONES
SAL5000245013002975
DEPTNO10101020
DNAMENEW YORKNEW YORKNEW YORKDALLAS
TOT_DEPT_SAL87508750875010875
INSERT INTO EMP_DETAILS (EMPNO, ENAME, SAL, DEPTNO)VALUES (9001,'ABBOTT',1000,10)
INSERT INTO EMP_DETAILS (EMPNO, ENAME, SAL, DEPTNO)VALUES (9001,'ABBOTT',1000,10)
INSTEAD OFINSTEAD OFINSERT into INSERT into EMP_DETAILSEMP_DETAILS
INSERT intoINSERT intoEMPLOYEESEMPLOYEES
EMPNO7939769877829001
ENAMEKINGBLAKECLARKABBOTT
SAL5000285024501000
DEPTNO102030
DNAMEACCOUNTINGRESEARCHSALES
TOT_DEPT_SAL9750108759400
UPDATEUPDATEDEPARTMENTSDEPARTMENTS
Capítulo 1: SQL-PSM 81
Exemplo
CREATE VIEW myview ASSELECT e.EMPLOYEE_ID, e.LAST_NAME, e.EMAIL,
e.HIRE_DATE, e.JOB_ID, d.DEPARTMENT_ID, d.DEPARTMENT_NAMEFROM employees e, departments dWHERE e.department_id = d.department_id/
CREATE OR REPLACE TRIGGER myview_trig INSTEAD OF INSERT ON myviewFOR EACH ROW BEGIN
INSERT INTO departments (department_id, department_name) VALUES(:NEW.department_id, :NEW.department_name);
INSERT INTO employees (EMPLOYEE_ID, LAST_NAME, EMAIL, HIRE_DATE, JOB_ID) VALUES(:new.EMPLOYEE_ID, :new.LAST_NAME, :new.EMAIL, :new.HIRE_DATE, :new.JOB_ID);
END;/
INSERT INTO myview VALUES (11,'SILVA','silva@...',sysdate,'AD_PRES',55,'FAZNADA');
select * from departments where department_id = 55; select * from employees where employee_id = 11;
Capítulo 1: SQL-PSM 82
Manipulando Exceções
Exceções são todos os erros e imprevistos que podem ocorrer durante a execução de um bloco PL/SQL
Quando uma exceção ocorre, o SGBD Oracle aborta a execução e procura a área de exceções (EXCEPTION) para tratar a falha
As exceções podem ser Pré-definidas Definidas pelo usuário
Capítulo 1: SQL-PSM 83
Manipulando Exceções
Sintaxe
EXCEPTION
WHEN nomeExceção1 THEN
Comandos;
WHEN nomeExceção2 THEN
Comandos;
WHEN others THEN
Comandos;
Capítulo 1: SQL-PSM 84
Manipulando Exceções
Exemplo
CREATE TABLE pais (id NUMBER PRIMARY KEY, nome VARCHAR2(20));
SET SERVEROUTPUT ON
BEGININSERT INTO pais VALUES (100, 'Brasil');COMMIT;DBMS_OUTPUT.PUT_LINE('Inserção realizada com sucesso');
EXCEPTIONWHEN dup_val_on_index THEN DBMS_OUTPUT.PUT_LINE('País já cadastrado! ');WHEN others THEN DBMS_OUTPUT.PUT_LINE('Erro ao cadastrar país');
END;
Capítulo 1: SQL-PSM 85
Exceções Pré-definidas
Cursor_Already_Open DUP_Val_On_INDEX INVALID_CURSOR Invalid_Number Login_Denied No_Data_Found Not_Logged_On RowType_Mismatch Storage_Error Too_Many_Rows Value_Error Zero_Divide Others
Capítulo 1: SQL-PSM 86
Exceção Definida pelo Usuário
Devem ser declaradas na área de declarações de um bloco ou procedure/function ou package
Comando:Declare
nomeExceção EXCEPTION;Begin
Seqüência de comandosIf … then
RAISE nomeExceção;End If;Comandos
ExceptionWhen NomeExceção then Comandos
End
Capítulo 1: SQL-PSM 87
Exceção Definida pelo Usuário
Exemplo
DECLARE out_of_stock EXCEPTION;number_on_hand NUMBER(4);
BEGIN...IF number_on_hand < 1 THEN
RAISE out_of_stock;END IF;
EXCEPTIONWHEN out_of_stock THEN
-- handle the errorEND;
Capítulo 1: SQL-PSM 88
Quando se cria uma procedure, se houver erros na sua definição, estes não serão mostrados
Para ver os erros de procedure chamada myProcedure, digite: SHOW ERRORS PROCEDURE myProcedure
no iSQLPLUS prompt Para funções, digite:
SHOW ERRORS FUNCTION myFunction
Visualizando Erros na Criação de uma Procedure/Function
Capítulo 1: SQL-PSM 89
Exemplo
CREATE OR REPLACE PROCEDURE proc10
IS
DECLARE
contador NUMBER;
BEGIN
contador := 10
END;
/
SQL> sho err procedure proc10
Falta ponto-e-vírgula
Capítulo 1: SQL-PSM 90
table1index1
view1proc1
func1
seq1
user01table1index1
view1proc1
func1
seq1
user02table1index1
view1proc1
func1
seq1
user03
Oracle Database
user01’s schema
user03’s schema
user02’s schema
Capítulo 1: SQL-PSM 91
Exemplo de Stored Procedure no SGBD SQL Server
1. CREATE PROCEDURE DBO.MostraEmpregadosDep @nomeDep varchar(50) = ‘Pessoal’ - - Dep Default AS SELECT e.mat, e.nome, e.endereco, e.salario FROM Empregados e, Departamento d WHERE d.nomeD = @nomeDep
Uma chamada a este procedimento seria:
USE Empresa -- BB Empresa EXEC MostraEmpregadosDep ‘Informatica’
Capítulo 1: SQL-PSM 92
Java Stored Procedure no SGBD Oracle
import java.sql.*;import java.io.*;import oracle.jdbc.*;public class BookDML { public static void insertBook (String title, String publisher)
throws SQLException {String sql = “INSERT INTO Livros VALUES (?, ?)”;try { Connection con =
DriverManager.getConnection(“jdbc:default:connection:”); PreparedStatement pstmt = con.prepareStatement(sql); pstmt.setString(1, title); pstmt.setString(2, publisher); pstmt.close();} catch (SQLException e) { system.err.println(e.getMessage());}
}
Capítulo 1: SQL-PSM 93
Java Stored Procedure no SGBD Oracle
Carregando a Classe no Banco de dados:
> loadjava –user baptista BookDML.java
Acessando a classe:
CREATE OR REPLACE PROCEDURE InsertBookJava (title VARCHAR, publisher VARCHAR) AS
Language javaName 'BookDML.insertBook(java.lang.String, java.lang.String)';
Executando do SQL*Plus:
CALL insertBookJava('Meulivro', 'LMV');
Usuário do BD Oracle
top related