Capítulo 1: SQL-PSM (Persistent Stored Modules)

Slides:



Advertisements
Apresentações semelhantes
Criando aplicações WEB
Advertisements

Estruturação de Linguagens (Pascal e C++)
O Comando DROP INDEX Para eliminar um índice definido sobre uma tabela, utilize: Drop Index on ; Ex: No Access: Drop Index X on.
Estudo de Caso, modelo Oracle 10g
Gerenciamento de Dados e Informação Estudo de caso – PL/SQL
Banco de Dados Prof. Antonio.
Banco de Dados I Aula 20.
Triggers Renata Viegas.
Prof. Alessandro J. de Souza
Prof.: Bruno Rafael de Oliveira Rodrigues
Banco de Dados SQL TRIGGERS (Gatilhos)
Banco de Dados SQL Stored Procedures
SISTEMAS DE INFORMAÇÃO Sistemas de Bancos de Dados 2º Semestre – 2010 Pedro Antonio Galvão Junior Fone:
SISTEMAS DE INFORMAÇÃO Sistemas de Bancos de Dados 2º Semestre – 2010 Pedro Antonio Galvão Junior Fone:
SISTEMAS DE INFORMAÇÃO Sistemas de Bancos de Dados II 1º Semestre – 2010 Pedro Antonio Galvão Junior Fone:
Visões Marilde Santos.
Maurício Edgar Stivanello
Sistema Gerenciador de Banco de Dados SGBD
Linguagens de Programação Orientadas a Objetos
Sumário 1 Processamento de Consultas 2 Introdução a Transações
SCC Bancos de Dados e Suas Aplicações
SCC Bancos de Dados e Suas Aplicações
SCC Bancos de Dados e Suas Aplicações
Material III-Bimestre Wagner Santos C. de Jesus
9 Controle de fluxo Seqüenciadores. Jumps. Escapes. Exceções.
7 Abstração Genérica Unidades genéricas e instanciação.
Banco de Dados I Capítulo 6: Uso de SQL em Aplicações
Algoritmos e Estruturas de Dados II
Introdução a JDBC Eduardo Martins Guerra Instituto Tecnológico de Aeronáutica Curso de Pós-Graduação em Engenharia de Software Programação Distribuída.
Classes e objetos Arrays e Sobrecarga
Estrutura de Dados em Java
Banco de dados Profª Kelly Medeiros.
Ada.
Variáveis, Tipos de Dados e Constantes
Aula R Prof. Naércio Filho Técnico em Informática
Python: Exceções, Iteradores e Geradores
PL/SQL, Procedures e Funções
Monitoria GDI Aula Prática
Design Patterns / Acesso ao banco de dados (java.sql)
Equipe de monitoria Aula prática 3.  Caso de estudo  Igualando situações  Cursor  Function  Procedure  Trigger  Package  Surpresa...
Primeira aula de PL/SQL Parte II
SEGUNDA FASE / S2B MIC PERNAMBUCO SEGUNDA FASE / S2B MIC PERNAMBUCO
Oracle 9i: SQL e PL/SQL Bruno Celso Cunha de Freitas
III – O Modelo OR Estudo de Caso, modelo Oracle 10g.
Com coleções, cursor não é mais necessário
Monitoria GDI Aula Prática
Desenvolvendo um script SQL
VIEW - VISÕES Professor Esp. Diego André Sant’Ana
JDBC Java Database Connectivity. JDBC Especificação para uso de base de dados em aplicações e applets JAVA; API para uso de drivers JDBC; Compatível com.
Pilhas Profa. Nádia Félix.
Banco de dados.
Capítulo III Modularização Procedimentos e Funções Universidade Federal de São Carlos Departamento de Computação Aluna: Luanna Lopes Lobato
REVISÃO Comandos SQL - DML SELECT * FROM ?.
PostGres: Um Banco de Dados Orientado a Objetos
Conceitos básicos de SQL
Monitoria GDI Aula Prática Aula 2: PL 1. Estudo de caso - continuação Pegar arquivo GDI.zip em Descompactar arquivo: o criacaoTabelas.SQL.
©Silberschatz, Korth and Sudarshan (modificado)4.1.1Database System Concepts Capítulo 4: SQL Estrutura básica Operações com conjuntos Funções de agregação.
Projeto de Sistemas de Informação Prof. Schneider Oracle Object-Relational.
Triggers (Gatilhos) Professor Esp. Diego André Sant’Ana
SCC Bancos de Dados e Suas Aplicações
Java Conexão com Baco de dados Saulo Bazzi Oberderfer Fonte:
Linguagem SQL Prof. Juliano.
©Silberschatz, Korth and Sudarshan (modificado)9.2.1Database System Concepts Capítulo 9: BDs Objecto-Relacional Relações imbricadas Tipos complexos e objectos.
7P/SI – 2010/01 Prof. Carlos Alberto Seixas. Agenda Visão Geral sobre os Conceitos e Implementação sobre SGBs MySQL Revisão das Práticas Práticas 1 e.
Banco de Dados -Aprendendo conceitos -Usando o SQL Conf para:
Aula 13 - Triggers. Triggers no SGBD Postgres  Os Triggers (Gatilhos) são funções preparadas para serem disparadas no caso de alguma alteração ocorrer.
Banco de Dados II Prof: Márcio Soussa Curso de Sistemas de Informação Faculdades Jorge Amado.
2/6/2016 José Antônio da Cunha - CEFET - RN1 Programação de Banco de Dados Funções.
Programação para Internet Aula 11 SQL (Introdução a linguagem, comandos de modificação: Create, Drop, Alter, Insert, Delete, Update)
Cursores 9/6/2016CEFET-RN1 José Antônio da Cunha George Azevedo da Silva.
Transcrição da apresentação:

Capítulo 1: SQL-PSM (Persistent Stored Modules) Banco de Dados II Prof. Carlos Eduardo Pires cesp@dsc.ufcg.edu.br

Uma consulta é executada a cada iteração: 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 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

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

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

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

Cursor Sintaxe para especificação de um cursor EXEC 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

OPEN FETCH CLOSE SELECT ename FROM employee Banco de Dados Cursor KING SMITH JOHN ... Cursor KING SMITH JOHN ... KING SMITH JOHN ... Cursor Capítulo 1: SQL-PSM

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 Capítulo 1: SQL-PSM

Um Exemplo de Uso de Cursor em C EXEC SQL BEGIN DECLARE SECTION; char SQLSTATE[6]; char titulo[101]; char ano[5]; EXEC SQL DECLARE filme_cursor CURSOR FOR SELECT titulo FROM filmes WHERE 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_cursor INTO :titulo; printf(“%s\n”, titulo); }; EXEC SQL CLOSE filme_cursor; return; erro: printf(“Um Erro ocorreu!\n”); Capítulo 1: SQL-PSM

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 tuplas if (strcmp(SQLSTATE, “02000”)) break; if (salario > 10000) EXEC SQL DELETE FROM Empregado WHERE CURRENT OF salCursor; else EXEC SQL UPDATE Empregado SET salario = salario - salario * 0.2; } EXEC SQL CLOSE salCursor; } Capítulo 1: SQL-PSM

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

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

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

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

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

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

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

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

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

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 locais corpo 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

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

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

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

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

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 BOOLEAN IF NOT EXISTS (SELECT * FROM Filme WHERE ano = p_ano AND nomeStudio = studio) THEN RETURN TRUE; ELSEIF 1 = (SELECT COUNT(*) WHERE ano = p_ano AND nomeStudio = studio AND NOT emcores) THEN ELSE RETURN FALSE; END IF; Capítulo 1: SQL-PSM

Stored Procedures: SQL/PSM Exemplo: 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 duracao from Filme where 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 filmeLOOP END IF; SET contaFilmes = contaFilmes + 1; SET mean = mean + novaDuracao; END LOOP; SET mean = mean / contaFilmes; CLOSE filmeCursor; END; Capítulo 1: SQL-PSM

Laços em PSM Laços FOR Exemplo FOR <nome laço> AS <nome cursor> CURSOR FOR <query> DO <comandos> END FOR; Exemplo FOR alunoLOOP AS alunoCursor CURSOR FOR SELECT nome, idade FROM Aluno WHERE periodo = ‘2010.2’; ... Capítulo 1: SQL-PSM

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

Outros Tipos de Laços em PSM Laço WHILE WHILE <condição> DO <comandos> END WHILE; REPEAT UNTIL <condição> END REPEAT; Capítulo 1: SQL-PSM

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 tratadas 2) Código a ser executado quando exceção ocorrer 3) 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

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, TooMany RETURN 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

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 DECLARE declarações (optativo) BEGIN comandos executáveis; (obrigatórios) EXCEPTION comandos para manipular erros (optativo) END; Capítulo 1: SQL-PSM

Oracle Stored Procedures Código PL/SQL é feito de blocos com uma única estrutura Existem dois tipos de blocos em PL/SQL: 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) Blocos Nomeados: são armazenados no banco de dados Procedures Functions Pacotes Capítulo 1: SQL-PSM

Blocos Anônimos DECLARE (opcional) BEGIN (obrigatório) /* 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

DECLARE Sintaxe Exemplos identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr]; Note que PL/SQL inclui todos tipos SQL, e outros mais… DECLARE birthday DATE; age NUMBER(2) NOT NULL := 27; name VARCHAR2(13) := 'Levi'; magic CONSTANT NUMBER := 77; valid BOOLEAN NOT NULL := TRUE; Capítulo 1: SQL-PSM

Declarando Variáveis com %TYPE Exemplos Acessando coluna sname na tabela Sailors DECLARE sname sailors.sname%TYPE; fav_boat VARCHAR2(30); my_fav_boat fav_boat%TYPE := ‘GrafSpee'; ... Acessando outra variável Capítulo 1: SQL-PSM

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; … Capítulo 1: SQL-PSM

Oracle Stored Procedures São objetos armazenados no BD que usam comandos PL/SQL e SQL em seus corpos Sintaxe CREATE 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

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%TYPE para capturar o tipo corretamente Capítulo 1: SQL-PSM

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) AS BEGIN INSERT INTO Vende VALUES(‘AlviRubro’, p_cerva, p_preco); COMMIT; END; / Capítulo 1: SQL-PSM

Executando Stored Procedures Uma chamada a uma procedure pode aparecer no corpo de um comando PL/SQL BEGIN 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

Um Segundo Exemplo Atenção: CREATE OR REPLACE PROCEDURE p1 (p_empid IN NUMBER, p_sal OUT NUMBER) IS BEGIN SELECT salary INTO p_sal FROM employees WHERE employee_id = p_empid; END; / CREATE OR REPLACE PROCEDURE p2 v_sal NUMBER; v_empid NUMBER := 101; p1(v_empid,v_sal); DBMS_OUTPUT.PUT_LINE('O empregado '||TO_CHAR(v_empid)||' recebe '||TO_CHAR(v_sal)); SQL> SET SERVEROUTPUT ON SQL> EXECUTE p2 O empregado 101 recebe 17000 Atenção: Não é necessário informar o tamanho dos parâmetros Capítulo 1: SQL-PSM

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 END IF; Laço LOOP . . . EXIT WHEN <condição> END LOOP; Capítulo 1: SQL-PSM

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

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

Cursores Declaração CURSOR <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> INTO lista_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

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

Exemplo O código completo do exemplo está disponível no Google Groups RAD_VALS 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 AREAS Radius Area 3 28.27 6 113.1 8 201.06 Capítulo 1: SQL-PSM

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

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

Exemplo CREATE PROCEDURE Aumento AS aCerveja Vende.cerveja%TYPE; oPreço Vende.preço%TYPE; CURSOR c IS SELECT cerveja, preço FROM Vende WHERE bar =`AlviRubro´; BEGIN OPEN c; LOOP FETCH c INTO aCerveja, oPreço; EXIT WHEN c%NOTFOUND; IF oPreço < 3.00 THEN UDPATE Vende SET preço = oPreço + 1.00 WHERE bar = `AlviRubro´ AND cerveja = aCerveja; END IF; END LOOP; CLOSE c; END; Capítulo 1: SQL-PSM

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

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? Tabela Reserves reserves_record Reserves%ROWTYPE; reserves_record.sid:=9; Reserves_record.bid:=877; Capítulo 1: SQL-PSM

Exemplo A mesma procedure com a variável tupla cp. CREATE PROCEDURE Aumento AS CURSOR c IS SELECT cerveja, preço FROM Vende WHERE 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 Vende SET preço= cp.preço + 1.00 WHERE bar = `AlviRubro´ AND cerveja = cp.cerveja; END IF; END LOOP; CLOSE c; END; Capítulo 1: SQL-PSM

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

Exemplo CREATE OR REPLACE FUNCTION func01 (valor IN NUMBER) RETURN VARCHAR2 AS BEGIN 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

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

Removendo Procedures e Funções Para remover uma stored procedure/function: DROP PROCEDURE <procedure_name>; DROP FUNCTION <function_name>; Capítulo 1: SQL-PSM

Outras Formas de Laços Comando FOR Sintaxe Permite que uma determinada sequência de comandos seja executada n vezes Sintaxe FOR contador IN [REVERSE] valorInicial..valorFinal LOOP sequência de comandos END LOOP Capítulo 1: SQL-PSM

Exemplo de Comando FOR Pergunta: CREATE OR REPLACE PROCEDURE VerificaEstoque AS codInicial Produto.codProduto%Type; codFinal CodInicial%Type; v_estoque Produto.estoque%Type; BEGIN SELECT Min(CodProduto), Max(codProduto) INTO codInicial, codFinal FROM Produto; FOR contador IN codInicial..codFinal LOOP SELECT estoque INTO v_estoque FROM 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

Exemplo de Cursor FOR CREATE OR REPLACE PROCEDURE p10 IS BEGIN END; / FOR emp_rec IN ( SELECT last_name, salary FROM employees WHERE 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 ON EXEC p10 Capítulo 1: SQL-PSM

Outras Formas de Laços Comando WHILE WHILE condição LOOP Comandos END LOOP; Exemplo DECLARE TEN number:=10; i number_table.num%TYPE:=1; BEGIN WHILE i <= TEN LOOP INSERT INTO number_table VALUES (i); i := i + 1; END; Capítulo 1: SQL-PSM

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

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

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

Exemplo de Pacote CREATE OR REPLACE PACKAGE BODY 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) BEGIN 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

Exemplo de Pacote DECLARE aEmployee_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

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

Exemplo de Trigger Capítulo 1: SQL-PSM

Criando Triggers Instante de Execução Evento: INSERT, UPDATE ou DELETE 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

Sequência de Disparo Sequência de disparo de um trigger em uma tabela quando apenas uma linha é manipulada Comando DML SQL> INSERT INTO dept (deptno, dname, loc) 2 VALUES (50, 'EDUCATION', 'NEW YORK'); Ação do Trigger DEPTNO 10 20 30 40 DNAME ACCOUNTING RESEARCH SALES OPERATIONS LOC NEW YORK DALLAS CHICAGO BOSTON BEFORE statement trigger BEFORE row trigger AFTER row trigger AFTER statement trigger Capítulo 1: SQL-PSM

Sequência de Disparo Sequência de disparo de um trigger em uma tabela quando muitas linhas são manipuladas SQL> UPDATE emp 2 SET sal = sal * 1.1 3 WHERE deptno = 30; BEFORE statement trigger EMPNO 7839 7698 7788 ENAME KING BLAKE SMITH DEPTNO 30 BEFORE row trigger AFTER row trigger BEFORE row trigger AFTER row trigger BEFORE row trigger AFTER row trigger AFTER statement trigger Capítulo 1: SQL-PSM

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 / Capítulo 1: SQL-PSM

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' Capítulo 1: SQL-PSM

Usando Predicados de Condição CREATE OR REPLACE TRIGGER secure_emp BEFORE INSERT OR UPDATE OR DELETE ON emp BEGIN 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; Capítulo 1: SQL-PSM

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

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

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 UPDATE INSERT Continuação OLD_TITLE NULL CLERK NEW_TITLE ANALYST SALESMAN OLD_SALARY NULL 1100 NEW_SALARY 3500 1100 Capítulo 1: SQL-PSM

Trigger INSTEAD OF Aplicação INSERT TABLE1 INSTEAD OF Trigger SQL> INSERT INTO my_view 2 . . .; INSERT TABLE1 INSTEAD OF Trigger UPDATE TABLE2 MY_VIEW Capítulo 1: SQL-PSM

Trigger INSTEAD OF INSERT INTO EMP_DETAILS (EMPNO, ENAME, SAL, DEPTNO) VALUES (9001,'ABBOTT',1000,10) EMPNO 7836 7782 7934 7566 ENAME KING CLARK MILLER JONES SAL 5000 2450 1300 2975 DEPTNO 10 20 DNAME NEW YORK DALLAS TOT_DEPT_SAL 8750 10875 INSTEAD OF INSERT into EMP_DETAILS INSERT into EMPLOYEES UPDATE DEPARTMENTS EMPNO 7939 7698 7782 9001 ENAME KING BLAKE CLARK ABBOTT SAL 5000 2850 2450 1000 DEPTNO 10 20 30 DNAME ACCOUNTING RESEARCH SALES TOT_DEPT_SAL 9750 10875 9400 Capítulo 1: SQL-PSM

Exemplo CREATE VIEW myview AS SELECT e.EMPLOYEE_ID, e.LAST_NAME, e.EMAIL, e.HIRE_DATE, e.JOB_ID, d.DEPARTMENT_ID, d.DEPARTMENT_NAME FROM employees e, departments d WHERE e.department_id = d.department_id / CREATE OR REPLACE TRIGGER myview_trig INSTEAD OF INSERT ON myview FOR 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

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

Manipulando Exceções Sintaxe EXCEPTION WHEN nomeExceção1 THEN Comandos; WHEN nomeExceção2 THEN WHEN others THEN Capítulo 1: SQL-PSM

Manipulando Exceções Exemplo CREATE TABLE pais (id NUMBER PRIMARY KEY, nome VARCHAR2(20)); SET SERVEROUTPUT ON BEGIN INSERT INTO pais VALUES (100, 'Brasil'); COMMIT; DBMS_OUTPUT.PUT_LINE('Inserção realizada com sucesso'); EXCEPTION WHEN 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

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

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 comandos If … then RAISE nomeExceção; End If; Comandos Exception When NomeExceção then Comandos End Capítulo 1: SQL-PSM

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; EXCEPTION WHEN out_of_stock THEN -- handle the error END; Capítulo 1: SQL-PSM

Visualizando Erros na Criação de uma Procedure/Function 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 Capítulo 1: SQL-PSM

Exemplo SQL> sho err procedure proc10 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

Oracle Database user03 user01 user02 user03’s schema user01’s schema table1 index1 view1 proc1 func1 seq1 table1 index1 view1 proc1 func1 seq1 user03 user03’s schema table1 index1 view1 proc1 func1 seq1 user01 user01’s schema user02 user02’s schema Capítulo 1: SQL-PSM

Exemplo de Stored Procedure no SGBD SQL Server Capítulo 1: SQL-PSM

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

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 java Name 'BookDML.insertBook(java.lang.String, java.lang.String)'; Executando do SQL*Plus: CALL insertBookJava('Meulivro', 'LMV'); Usuário do BD Oracle Capítulo 1: SQL-PSM