Oracle Resumo

43
Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente 1 Material de Apoio Oracle

Transcript of Oracle Resumo

Page 1: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

1

Material de Apoio

Oracle

Page 2: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

2

ÍNDICE

1. Introdução............................................................................................................................... 3 2. Objetivo.................................................................................................................................. 3 3. Tabelas e colunas (Tables and columns)................................................................................ 3 4. Sequences (sequências) .......................................................................................................... 6 5. Tabela DUAL......................................................................................................................... 8 6. Funções e Operadores de linhas simples................................................................................ 8 7. SQL e PL/SQL ..................................................................................................................... 11 8. Estrutura de um Bloco PL/SQL ........................................................................................... 15 9. Views.................................................................................................................................... 17 10. Index (índice) ..................................................................................................................... 18 11. Procedures, Functions e Triggers ....................................................................................... 19 12. Tratamento de Erros (Exceções) ........................................................................................ 29 13. Cursor ................................................................................................................................. 34

Page 3: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

3

1. Introdução

O Oracle é um sistema gerenciador de banco de dados (SGBD) relacional utilizado por muitas empresas hoje em dia. Sua aplicação vem aumentando consideravelmente por oferecer confiabilidade (segurança/suporte) e alto desempenho com grandes volumes de dados e transações.

2. Objetivo Esta apostila tem como objetivo oferecer aos alunos informações para a compreensão de funcionalidades básicas do Oracle.

3. Tabelas e colunas (Tables and columns)

Tabelas são mecanismos de armazenamento para dados de um banco de dados Oracle. Sua função é armazenar uma série de colunas fixas. As colunas de uma tabela descrevem os atributos da entidade que esta sendo estipulado pela tabela. Cada coluna tem um nome e características específicas. As características de uma coluna são divididas em duas partes: seu tipo de dado e seu tamanho. CREATE TABLE [schema].tabela (coluna tipo_de_dado [DEFAULT expressão])

o schema é o mesmo que o nome do dono. Na parte prática veremos com mais atenção a criação de tabelas.

ALTER TABLE tabela ADD (coluna tipo_de_dado [DEFAULT expressão])

acrescenta colunas em uma tabela

ALTER TABLE tabela MODIFY (coluna tipo_de_dado [DEFAULT expressão])

altera colunas em uma tabela

DROP TABLE tabela apaga a tabela (Não é possível fazer rollback desta classe de comandos - DDL).

TRUNCATE TABLE tabela remove todas as linhas de uma tabela preservando a sua estrutura.

RENAME tabela TO novonome renomeia uma tabela. COMMENT ON TABLE tabela IS ‘comentário’

adiciona comentário em tabela (dicionário de dados: USER_TAB_COMMENTS).

Exemplos. Criar uma tabela: CREATE TABLE CLIENTE (CLI_COD NUMBER(6) NOT NULL PRIMARY KEY, CLI_NOME VARCHAR2(70) NOT NULL, CLI_SEXO CHAR(1) CHECK (CLI_SEXO IN ('M', 'F')), CLI_DTNASCTO DATE NOT NULL,

Page 4: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

4

CID_COD NUMBER(3), CONSTRAINT FK_CLI_CIDADE FOREIGN KEY (CID_COD)

REFERENCES CIDADE(CID_COD)); DROP TABLE CLIENTE; Alterar uma tabela: ALTER TABLE CLIENTE ADD (CLI_CPF VARCHAR2(11)); ALTER TABLE CLIENTE RENAME

COLUMN CLI_DTNASCTO TO CLI_DTNASC; ALTER TABLE CLIENTE DROP COLUMN CLI_CPF; Apagar uma tabela: DROP TABLE CLIENTE;

Os tipos de dados (Data Types) básicos de dados no Oracle são: size = tamanho

Tipo Descrição CHAR(size) Aceita dados alfanuméricos. Tamanho (size) fixo, podendo ser

utilizado de 1 a 2000 caracteres. VARCHAR2(size) Aceita dados alfanuméricos. Tamanho variável pelo estipulado em

(size), podendo variar de 1 a 4000 caracteres. VARCHAR(size) Mesmo que o tipo Varchar2 (não é recomendado). Existe para

manter compatibilidade com versões anteriores. DATE Valor de data e hora abrangendo 01/01/4712 a.C. até 31/12/4712

d.C. LONG Similar ao Varchar2, porém o tamanho máximo é de 2 GB. A

documentação da Oracle não recomenda seu uso. Existe para manter compatibilidade com versões anteriores. Sugere como alternativa a utilização de CLOB.

NUMBER(I,D) Valor numérico, onde: I = quantidade total de dígitos (inteiros+decimais) e D = quantidade de dígitos decimais

RAW Usado para dados binários ou dados não interpretados pelo Oracle, como uma seqüência de caracteres gráficos, arquivos executáveis, arquivos PDF, etc. Tem tamanho máximo de 2000 bytes

LONG RAW Similar ao Raw, mas com tamanho de até 2 GB BLOB Binary Large Object – suporta dados binários com tamanho até 4 GB CLOB Large Object – suporta dados caracteres com tamanho até 4 GB BFILE Utilizado como apontador para um arquivo binário em um servidor de

arquivos – tamanho até 4 GB Existem diversos outros tipos aceitos pelo Oracle, mas que não foram abordados aqui por não fazerem parte do escopo da disciplina.

As tabelas do usuário SYS são chamadas de tabelas de dicionário de dados. Elas provêem um catálogo do sistema que o banco de dados usa para sua própria administração. Tabelas se relacionam umas com as outras através das colunas que as mesmas têm em comum. O banco de dados pode reforçar esta relação via integridade referencial. O Oracle denomina esta ligação de constraint (constrangimento).

Page 5: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

5

3.1. Table Constraint (restrição de tabelas) O Oracle usa constaints para prevenir entrada de dados inválidos em tabelas.

Podemos usar constraints para fazer as seguintes operações: • reforçar regras no nível de tabela sempre que uma linha é inserida, atualizada ou

apagada. • prevenir a deleção de uma tabela se existem dependentes em outras tabelas. • prover regras para as ferramentas do Oracle, como o SQL Developer. Podem ser: NOT NULL impede que um valor nulo seja inserido nesta coluna. UNIQUE KEY especifica uma coluna ou uma série de colunas que não podem ter

valores repetidos ao longo da tabela. PRIMARY KEY identificador único de cada linha em uma tabela. FOREIGN KEY estabelece e reforça uma chave estrangeira entre uma coluna e a

tabela relacionada. CHECK estabelece uma condição que deve ser verdadeira. Exemplos CREATE TABLE EMPREGADOS( EMP_COD NUMBER(6) PRIMARY KEY, DEP_COD NUMBER(2) NOT NULL, EMP_NOME VARCHAR2(60), EMP_SALARIO NUMBER(10,2), CONSTRAINT CONST_EMPREGADO UNIQUE(NOME)); Adicionando uma constraint ALTER TABLE EMPREGADOS ADD CONSTRAINT CONST_DEPARTAMENTO_FK FOREIGN KEY (DEP_COD) REFERENCES DEPARTAMENTOS(DEP_COD); Deletando uma constraint ALTER TABLE EMPREGADOS DROP CONSTRAINT CONST_DEPARTAMENTO_FK; Desabilitando uma constraint ALTER TABLE EMPREGADOS DISABLE CONSTRAINT CONST_DEPARTAMENTO_FK; Habilitando uma constraint ALTER TABLE EMPREGADOS ENABLE CONSTRAINT CONST_DEPARTAMENTO_FK; OBS: As constraints são armazenadas na tabela USER_CONSTRAINTS do dicionário de dados. Outros exemplos:

“nome da constraint”

Page 6: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

6

CREATE TABLE EMPREGADOS (CODIGO NUMBER(10) PRIMARY KEY,

NOME CHAR(40) NOT NULL, DEP_COD NUMBER(2) DEFAULT 10, SALARIO NUMBER(7,2) CHECK (SALARIO < 180), NASC DATE, RG CHAR(9) UNIQUE, FOREIGN KEY (DEP_COD) REFERENCES DEPARTAMENTOS(DEP_COD) ) TABLEPACE USERS;

Note que cada coluna tem o seu tamanho e o tipo de dados associado, bem como

algumas colunas possuem as seguintes constraints

PRIMARY KEY NOT NULL, DEFAULT 10 CHECK (SALÁRIO < 180) UNIQUE

A constraint FOREIGN KEY nos obriga a ter uma tabela DEPTO, cuja coluna DEP_COD tenha o valor que estamos inserindo nesta linha neste momento.

Outros exemplos: ALTER TABLE CLIENTE DROP CONSTRAINT FK_CLI_CIDADE;

ALTER TABLE CLIENTE ADD CONSTRAINT FK_CLI_CIDADE FOREIGN KEY

(CID_COD) REFERENCES CIDADE; ALTER TABLE CLIENTE ADD CONSTRAINT NN_CLI_CPF CLI_CPF

VARCHAR2(11) NOT NULL; ALTER TABLE CLIENTE ADD CONSTRANIT PK_CLIENTE

PRIMARY KEY (CLI_COD);

4. Sequences (sequências)

Uma seqüência ou sequence é usada para gerar uma lista de números seqüências para as colunas numéricas das tabelas de um banco de dados, recomendada principalmente para chaves primárias. As seqüências simplificam a programação de aplicações pois geram automaticamente e sem degradação de performance, valores seqüências para linhas de uma ou mais tabelas, portanto não acessam o disco, não ocorrem locks implícitos ou explícitos em suas estruturas e, assim a serialização é reduzida, pois dois ou mais comandos podem utilizá-las ao mesmo tempo.

Os números seqüências gerados pelo Oracle são inteiros de 38 dígitos e são definidos em um banco de dados. A definição de uma seqüência mostra diversas informações como o nome da seqüência, se a geração dos números é ascendente ou descendente, o intervalo entre os números gerados, e outras informações. As definições de todas as seqüências de um banco são armazenadas em uma tabela do dicionário de dados.

Os números seqüências são usados pelos comandos SQL para gerar um novo número seqüencial ou usar o número atual. Os números seqüências são gerados independentemente das tabelas mas podemos usar um gerador de números seqüências para mais de uma tabela.

Page 7: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

7

Resumindo: • automaticamente gera números únicos; • é um objeto compartilhável; • é tipicamente usada para criar um valor para uma chave primaria; • substitui código em aplicações • aumenta a velocidade para acessar valores seqüenciais armazenados na

memória (“cacheados”). Sintaxe:

CREATE SEQUENCE sequence [INCREMENT BY n] [START WITH n] [(MAXVALUE n|NOMAXVALUE)] [(MINVALUE n|NOMINVALUE)] [(CYCLE|NOCYCLE)] [(CACHE n|NOCACHE)];

INCREMENT BY especifica o intervalo entre os números da sequence - padrão 1 START WITH n especifica o primeiro valor da sequence - padrão 1 MAXVALUE n especifica o valor máximo para a sequence atingir NOMAXVALUE sem valor máximo MINVALUE n especifica o valor mínimo da sequence NOMINVALUE sem valor mínimo CYCLE começa a gerar do começo quando o limite for alcançado NOCYCLE não começa a gerar do começo quando o limite for alcançado CACHE n especifica quantos valores o Oracle Server irá pré-alocar na memória

para disponibilidade imediata - padrão 20 valores. NOCACHE não pré-aloca nada, fazendo consultas ao dicionário de dados a cada

incremento da sequence. Usando uma sequence:

CURRVAL Retorna o valor corrente de uma sequence. Considera somente o valor da sessão/conexão ativa. Somente acessível após o primeiro NEXTVAL da sessão/conexão.

NEXTVAL Retorna o próximo valor de uma sequence e faz o seu incremento. Considera a instância do banco para que o incremento nunca se repita para diferentes ssões/conexões.

Exemplo - gravando dados em uma tabela com chave primária:

CREATE SEQUENCE SEQ_CLIENTE START WITH 1 INCREMENT BY 1 NOMAXVALUE NOMINVALUE NOCYCLE NOCACHE;

Page 8: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

8

Situação 1: INSERT INTO CLIENTE (CLI_COD,CLI_NOME) VALUES (SEQ_CLIENTE.NEXTVAL,'TESTE'); INSERT INTO CLIENTE_FONE (CLI_COD, FONE_COD, FONE_NUMERO) VALUES (SEQ_CLIENTE.CURRVAL, 1, '(18) 3333-4567'); INSERT INTO CLIENTE_FONE (CLI_COD, FONE_COD, FONE_NUMERO) VALUES (SEQ_CLIENTE.CURRVAL, 2, '(18) 4444-5566');

Situação 2: CREATE OR REPLACE PROCEDURE INSERE_CLIENTE (P_CLI_COD OUT CLIENTE.CLI_COD%TYPE, P_CLI_NOME IN CLIENTE.CLI_NOME%TYPE) IS BEGIN SELECT SEQ_CLIENTE.NEXTVAL INTO P_CLI_COD FROM DUAL; INSERT INTO CLIENTE(CLI_COD,CLI_NOME) VALUES(P_CLI_COD,P_CLI_NOME); END;

5. Tabela DUAL

Tabela do usuário SYS com acesso público para ser utilizado em instruções “select” que necessitam retornar uma única linha, sem necessidade de acesso a atributos de outras tabelas. Exemplo: -- retorna a data do sistema SELECT SYSDATE FROM DUAL;

-- realiza a operação matemática SELECT (145.6*85.1/4) AS CONTA FROM DUAL; -- exibir o usuário conectado no banco SELECT USER FROM DUAL;

6. Funções e Operadores de linhas simples No Oracle, como em todos os outros SGBD’s, há uma série de funções pré-definidas para serem utilizadas no intuito de transformar dados a serem recuperados ou manipulados com comandos SQL. Essas funções podem:

• manipular itens de dados; • aceitar argumentos e retornar um valor; • agir sobre cada linha retornada; • retornar um resultado por linha; • modificar o tipo de dado • podem ser aninhados

Page 9: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

9

Algumas das funções mais utilizadas:

Funções Gerais LOWER converte uma string em minúscula UPPER converte uma string em maiúscula INITCAP Retorna a string com o primeiro caractere de cada

palavra em maiúsculo e os caracteres restantes em minúsculo

CONCAT Concatenação de strings - equivalente a || SUBSTR(coluna/expressão,m[,n]) retorna caracteres especificados a partir da

posição m até a posição n da coluna/expressão. LENGTH(coluna/expressão) retorna o número de caracteres (tamanho) da

coluna/expressão INSTR (str1,str2,p_ini,ocorrencia,’string’)

retorna a posição em que a string2 está contida de string1. p_ini: posição de string1 a partir da qual será iniciada a busca – opcional – default 1 ocorrência: indica o número da ocorrência – se retorna na 1a. ocorrência encontrada, na 2a., e assim por diante – opcional – default 1.

LPAD(string1,n,string2)

Retorna string1 preenchida à esquerda até o comprimento de n com os caracteres de string2.

RPAD(string1,n,string2)

Retorna string1 preenchida à direita até o comprimento de n com os caracteres de string2.

ROUND(coluna/expressão,n) arredonda a coluna/expressão para n casas decimais.

TRUNC(coluna/expressão,n) trunca a coluna/expressão em n casas decimais e se n for omitido, pega somente a parte inteira da expressão

NVL(coluna/expressão,n) converte um valor nulo na expressão n Ex: NVL(salário,’não estipulado’)

DECODE(coluna/expressão, pesquisa1, resultado1[, pesquisa2, resultado2,...,][default])

decifra a coluna/expressão e compara com pesquisaN, devolvendo como resultado o resultadoN, se nenhum for encontrado segue o default

MOD(m,n) retorna o resto da divisão Funções de data e hora SYSDATE retorna a data e a hora do sistema data + numero resulta em data + numero dias (data) date - numero resulta em data - numero (data) date - date número de dias (inteiro) date + numero/24 adiciona um número de horas a uma data (data) MONTHS_BETWEEN(data1,data2) Retorna o número de meses entre data1 e data2 ADD_MONTHS(d,x) Retorna a data d mais x meses NEXT_DAY(data,dia_semana) A partir da data informada, retorna a data do

próximo dia da semana especificado. Onde dia_semana; 1–domingo, 2-segunda,.....,6-sábado

LAST_DAY(data) Retorna a data do último dia do mês ROUND(data,formato) arredonda a data para o formato especificado

(opcional) ou para o menor valor possível. TRUNC trunca a data, para o formato especificado

Page 10: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

10

(opcional) ou para o menor valor possível. Funções de conversão TO_CHAR(x,formato) converte x em um tipo de caractere, formato

opcional TO_DATE(y,formato) converte y para data TO_NUMBER(x) converte x para tipo numérico O tratamento e manipulação do tipo DATE no Oracle exige alguns cuidados especiais, pois este tipo armazena sempre data e hora simultaneamente num mesmo atributo ou variável. Para isso, é indispensável a utilização das funções TO_CHAR e TO_DATE, em ambas pode ser especificado uma máscara de formatação de data e hora. Na tabela abaixo são apresentados os mais comuns: DD Dia: 01, 02…31 MM Mês: 01...12 YY Ano de 2 dígitos: 07,08 YYYY Ano de 4 dígitos: 2007, 2008 HH24 Hora no padrão 24 hs: de 00 a 23 MI Minutos: 00 a 59 SS Segundos: 00 a 59 d Dia da semana (1-domingo a 6-sábado) Existem vários outros formatos que podem ser verificados nos arquivos de referência no diretório público. Algumas situações serão apresentadas para melhor entendimento. SELECT NOT_NUM,

TO_CHAR(NOT_DATA,'DD/MM/YYYY HH24:MI:SS') AS DATA FROM NOTA WHERE NOT_DATA BETWEEN TO_DATE('01/01/2000 00:00:00','DD/MM/YYYY HH24:MI:SS') AND TO_DATE('091231235959', 'YYMMDDHH24MISS');

Neste caso note que para exibir o atributo NOT_DATA (definido como “date” na tabela) foi utilizada a função TO_CHAR para formatar o modo de exibição. Caso não tivesse sido usada a função, seria exibida a data no formato padrão do “client” do Oracle.

Outro detalhe está presente na cláusula WHERE quando há a comparação do atributo NOT_DATA. Tem-se que comparar DATE com DATE, por isso transformar a string entre aspas em DATE com a função TO_DATE. -- SOMAR 3 HORAS EM UMA DATA SELECT TO_CHAR(SYSDATE+(1/24)*3,’DD/MM/YYYY HH24:MI’) AS DATA

FROM DUAL; -- QUANTOS DIAS HÁ ENTRE 2 DATAS SELECT TO_DATE('01/01/08','DD/MM/YY')-TO_DATE('01/05/05','DD/MM/YY')

FROM DUAL; -- INSERT EM UMA TABELA COM ATRIBUTO DATE INSERT INTO NOTA(NOT_NUM, CLI_COD, NOT_DATA, NOT_TOTAL) VALUE(150,1,TO_DATE('01/01/08 HH24:MI','DD/MM/YY 10:30'),5230); Mais referências podem ser encontradas no diretório public.

Page 11: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

11

7. SQL e PL/SQL

Structured Query Language (Linguagem estruturada de consulta) a SQL permite que você se comunique com o banco de dados com as seguintes vantagens:

1.Eficiência; 2.Facilidade de aprendizado e uso; 3.Funcionalidade total - permite definir, manipular e recuperar dados em tabelas.

PL/SQL - Procedural Language que estende os recursos da SQL através do uso de lógica de aplicação.

7.1. Declarações SQL Select Recuperação de dados (DRS) Insert Update Delete

Linguagem de manipulação de dados (DML)

Create Alter Drop Rename Truncate

Linguagem de definição de dados (DDL)

Commit Rollback Savepoint

Controles de Transações

Grant Revoke

Linguagem de controle de dados (DCL)

7.2. Benefícios da PL/SQL Com a PL/SQL podemos realizar toda a camada de aplicação lógica internamente no banco de dados, ficando a cargo da estação somente a camada de interface com o usuário.

1. Aumento de performance através da redução de tráfico de rede; 2. Agrupamento de lógicas relacionadas em blocos; 3. Aninhar blocos menores em maiores para construir programas mais poderosos; 4. Quebrar um problema complexo em blocos menores para facilitar a

administração; 5. Colocar código reusável em bibliotecas; 6. Alta portabilidade (pode migrar para qualquer host); 7. Posso declarar identificadores; 8. Estrutura de controle procedural (pascal, c); 9. Pode manipular erros; Qualquer rotina de um programa PL/SQL é baseada em blocos. Um programa

PL/SQL pode ser composto por um ou mais blocos, os quais podem ocorrer seqüencialmente (um depois do outro) ou aninhados (um dentro do outro). Serão apresentados mais detalhes mais à frente.

Page 12: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

12

7.3. Sintaxe

7.3.1. Select SELECT * FROM tabela; seleciona todos os elementos da tabela SELECT coluna1,coluna2,...,colunan FROM tabela;

seleciona as colunas mencionadas da tabela

SELECT (coluna1+300)+100, coluna2* 2 FROM tabela;

seleciona as colunas mencionadas com operadores matemáticos que têm a seguinte precedência: * / + - para mudar a preferência tenho que usar parênteses.

SELECT coluna1*1.08 AS “Novo salário” FROM tabela;

posso dar um apelido as colunas associando um alias ao mesmo. As aspas duplas preservam a formatação interna dos caracteres.

SELECT nome||’ ‘||sobrenome FROM tabela;

|| é o operador de concatenação.

SELECT DISTINCT salário FROM tabela;

a clausula distinct elimina as linhas duplicadas na consulta.

7.3.2. Restringindo e ordenando dados SELECT * FROM tabela WHERE nome= ‘JOÃO’;

seleciona todos os elementos da tabela cujo nome seja exatamente ‘JOÃO’.

Operadores de comparação = (igual) > (maior) >= (maior ou igual) < (menor) <= (menor ou igual) <> (diferente)

SELECT nome,salário FROM tabela WHERE cargo<>‘diretor’ and salário > 10000;

posso colocar tantas cláusulas restritivas quantas eu quiser adicionando AND, OR ou NOT - operadores lógicos.Têm a seguinte precedência: NOT AND OR

Outros operadores de comparação BETWEEN ... AND... - entre dois valores (muito usado para datas) IN(lista) - coloco todos os elementos que quero comparar LIKE – como associado ao % - que substitui qualquer expressão - e ao _ (underline) - que substitui qualquer caractere - faz buscas por expressões parciais. IS NULL - compara com valores nulos dos campos.

SELECT nome||’ ‘||sobrenome a cláusula order by ordena a consulta,

Page 13: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

13

FROM tabela ORDER BY nome [DESC][ASC];

trazendo os dados de forma ordenada em forma descendente DESC - ou ascendente ASC (padrão). Podem ser usadas múltiplas colunas na ordenação

7.4. Mostrando dados de várias tabelas SELECT tabela1.coluna1,tabela2.coluna2 FROM tabela1,tabela2 WHERE tabela1.chave1 = tabela2.chave2

Quando dados de mais de uma tabela no banco de dados são requeridos, podem ser juntados com a cláusula WHERE ao lado. Geralmente isto se dá com chaves primárias e chaves estrangeiras.

SELECT tabela1.coluna1,tabela2.coluna2 FROM tabela1,tabela2

A SQL ao lado devolve um produto cartesiano das duas tabelas (mostra para cada registro da 1a todos os registros da 2a )

Equijoin Envolve duas colunas iguais/correlatas em ambas as tabelas - geralmente chave primária e chave estrangeira

Non-equijoin Duas colunas diferentes compõem a consulta, como mostrar os salários da tabela A que estão entre dois valores da tabela B.

Outer join SELECT tabela1.coluna1, tabela2.coluna2 FROM tabela1 , tabela2 WHERE tabela1.codigo(+) = tabela2.codigo;

Retorna registros que não necessariamente encontraram correspondência. No Exemplo ao lado pegamos os dados da tabela1 que não têm correspondente na tabela2 e os exibimos mesmo assim com valor nulo.

Self join SELECT unique e1.cargo, e1.nome FROM empregados e1, empregados e2 WHERE e1.chefe = e2.emp_codigo;

Podemos ter uma tabela relacionada com ela mesmo e extrair os dados baseados nesta informação. EMPREGADOS EMP_COD, NOME, CHEFE

7.5. Agregando dados usando funções de agrupamento As funções de grupo buscam resumos de operações, tais como total da folha, saldo, média, etc... AVG Média (ignora valores nulos) COUNT Conta o número de registros que

satisfazem o critério especificado. MAX pega o maior valor (ignora valores nulos) MIN pega o menor valor (ignora valores nulos) STDDEV desvio padrão (ignora valores nulos) SUM soma os valores (ignora valores nulos) VARIANCE calcula a variância (ignora valores nulos). GROUP BY

agrupa os valores de uma consulta por esta condição. Todos os itens da consulta

Page 14: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

14

SELECT departamento,AVG(salário) FROM empregados GROUP BY departamento

têm que estar agrupados ou usando funções de agrupamento.

HAVING SELECT departamento,AVG(salário) FROM empregados GROUP BY departamento HAVING AVG(salário) > 1000 ORDER BY departamento

Esta cláusula é usada para especificar quais grupos serão mostrados.

7.6. Subqueries

Podemos nos deparar com a seguinte ordem: Mostre todos os salários que sejam maiores que o do empregado ‘Jose’. A SQL que recupera os dados do banco de dados tem que passar como condição de busca o salário do ‘Jose’ para a SQL que recupera os dados dos outros funcionários. SELECT departamento,nome,salario FROM empregados WHERE salario > (SELECT salario FROM empregados WHERE nome = ‘Jose’); Para usar a subqueries temos algumas regras básicas:

• Encapsule as subqueries entre parênteses; • coloque as subqueries do lado direito da comparação; • não coloque ORDER BY em uma subquerie (Oracle 8 ou inferior); • use operadores de linha única (=,>,<) com consultas de linha única; • use operadores de múltiplas linhas (in, exists) com subqueries de múltiplas

linhas.

7.7 Controlando Transações O servidor Oracle assegura a consistência dos dados baseado em transações. Transações nos proporcionam mais flexibilidade e controle quando estamos mudando dados. As chaves de transações são os comandos: COMMIT finaliza a transação corrente, fazendo

todas as atualizações pendentes e transformando-as em permanentes.

ROLLBACK finaliza a transação corrente descartando todas as mudanças realizadas.

SAVEPOINT marca um ponto de inicio para uma dada transação, nomeando-a: SAVEPOINT a;

Page 15: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

15

8. Estrutura de um Bloco PL/SQL PL/SQL é uma linguagem estruturada em blocos significando que programas podem ser divididos em blocos lógicos. Constitui-se de três sessões: Declarativa contém todas as variáveis, constantes,

exceções definidas pelo usuário que estão referenciadas nas sessões de execução

Opcional

Executável contém as declarações SQL para manipulação de dados no banco de dados e instruções PL/SQL para manipulação de dados no bloco.

Obrigatória

Exception Handling (manipulação de exceções)

Especifica a ação a tomar quando erros e condições anormais ocorrem na sessão executável.

Opcional

Tipos de blocos Anonymous Procedure Function [DECLARE] BEGIN -- comandos [EXCEPTION] END;

PROCEDURE nome IS BEGIN -- comandos [EXCEPTION] END;

FUNCTION nome RETURN tipo_de_dado IS BEGIN -- comandos RETURN valor; [EXCEPTION] END;

8.1. Estruturas de Controle Podemos controlar o fluxo de um bloco PL/SQL com algumas estruturas de controles que existem na maioria das linguagens que conhecemos.

Nota: Toda instrução PL/SQL é finalizada com ponto-e-vírgula (;). Atribuição ( := )

( := ) - dois pontos igual variável := expressão;

vnome := ‘jose’;

IF THEN ELSE

IF condição THEN sequencia_de_intruções;

ELSIF condição THEN sequencia_de_intruções;

Page 16: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

16

ELSE sequencia_de_intruções;

END IF; A única observação é que a sintaxe precisa ser exata e não temos ferramentas de interação para analisar onde está o erro precisamente, ainda mais se o mesmo ocorrer dentro desta estrutura.

LOOP PL/SQL nos fornece um número de facilidades para estrutura de loop para repetir uma seqüência de três maneiras básicas: Loop Básico, Loop FOR e Loop WHILE.

LooP Básico:

DECLARE VAR_COD EMPREGADO.COD_EMPREGADO%TYPE := 100; VAR_CONTADOR NUMBER(2) :=1; BEGIN LOOP

INSERT INTO ITEM(COD_EMPREGADO,ORDEM) VALUES(VAR_COD,VAR_CONTADOR);

VAR_CONTADOR := VAR_CONTADOR+1; EXIT WHEN VAR_CONTADOR > 10; END LOOP; END;

Loop FOR:

DECLARE

VAR_COD EMPREGADO.COD_EMPREGADO%TYPE := 100; VAR_CONTADOR NUMBER(2);

BEGIN FOR VAR_CONTADOR IN 1..10 LOOP INSERT INTO ITEM(COD_EMPREGADO,ORDEM)

VALUES(VAR_COD,VAR_CONTADOR); END LOOP;

END;

Loop WHILE:

DECLARE VAR_COD EMPREGADO.COD_EMPREGADO%TYPE := 100; VAR_CONTADOR NUMBER(2) :=1;

BEGIN WHILE VAR_CONTADOR < 10 LOOP INSERT INTO ITEM(COD_EMPREGADO,ORDEM) VALUES(VAR_COD,VAR_CONTADOR); VAR_CONTADOR := VAR_CONTADOR+1; END LOOP;

END; Posso aninhar os loops à vontade e há ainda um diferencial importante que é o fato de podermos nomear um loop e sair dele com “EXIT nome“.

Adrielle
Marcador de texto
Page 17: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

17

CASE Sintaxe 1: CASE VAR_TESTE WHEN VALOR1 THEN ...INSTRUÇÕES...; WHEN VALOR2 THEN ...INSTRUÇÕES...; ELSE ...INSTRUÇÕES...; END CASE; Sintaxe 2: CASE WHEN VAR_TESTE_1 = VALOR1 THEN

...INSTRUÇÕES...; WHEN VAR_TESTE_1 < VALOR2 THEN

...INSTRUÇÕES...; ELSE

...INSTRUÇÕES...; END CASE; Sintaxe 3 (case com “select”):

SELECT CASE

WHEN CLI_COD='01' THEN 'CODIGO 1' WHEN CLI_COD = '02' THEN 'CODIGO 2' ELSE 'OUTRO CODIGO' END AS LOCAL FROM CLIENTE;

9. Views Devemos usar uma view para: • restringir o acesso a dados; • fazer queries complexas ficarem simples; • permitir a independência de dados; • para apresentar diferentes visões do mesmo dado. Criando uma view:

CREATE [OR REPLACE] [FORCE] [NOFORCE] VIEW visão AS subquerie [WITH CHECK OPTION [CONSTRAINT constriant]] [WITH READ ONLY]

OR REPLACE se já houver substitua; FORCE cria independente da existência das tabelas;

Page 18: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

18

NO FORCE cria se a tabela existir (default); WITH CHECK OPTION especifica que somente linhas acessíveis à view

podem ser atualizadas ou inseridas; WITH READ ONLY assegura que nenhuma operação DML pode ser

feita sobre esta view. Exemplo:

CREATE OR REPLACE VIEW V_CLIENTES (CODIGO, NOME, TOTAL) AS SELECT C.CLI_COD, C.CLI_NOME, SUM(N.NOT_TOTAL) AS TOTAL FROM CLIENTE C, NOTA N WHERE C.CLI_COD = N.CLI_COD GROUP BY C.CLI_COD, C.CLI_NOME;

10. Index (índice) Este tópico somente aborda sintaxe e algumas particularidades para a criação de índices que, sucintamente, são estruturas auxiliares que contém a chave do índice (composta de um ou mais atributos da tabela) de forma ordenada e o endereço do registro correspondente na tabela e é utilizado para otimizar consultas ao banco de dados. Exemplo: se utilizamos muito buscas por data da nota fiscal, então aconselha-se a termos um índice pela data da nota fiscal referente à tabela de nota fiscal; ou então para consultas por nome do cliente. SELECT * FROM NOTA N WHERE N.NOT_DATA BETWEEN (SYSDATE-30) AND SYSDATE; Chave do índice: NOT_DATA SELECT * FROM CLIENTE C WHERE CL.CLI_NOME LIKE ‘MARIA%’; Chave do índice: CLI_NOME Enfim, é preciso um aprofundamento maior no assunto para que questões fundamentais sejam assimiladas e tenha-se a compreensão exata da necessidade dos índices.

Sintaxe: CREATE INDEX NOME_INDICE ON TABELA (COLUNA_1,COLUNA_2,...,COLUNA_N) TABLESPACE X;

Cria o índice da tabela nas colunas, sendo que a ordem é a que foi digitada.

Guia para criar índices: • se a coluna é usada freqüentemente em clausulas WHERE; • se a coluna contém uma grande faixa de valores; • se a coluna contém uma grande quantidade de valores nulos; • se duas ou mais colunas são usadas freqüentemente juntas em clausulas

WHERE;

Chave do índice

Page 19: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

19

• se a tabela for grande e a maioria das consultas recuperar de 2 a 4% das linhas.

Guia para não criar um índice: • se a tabela for pequena; • se a coluna não for freqüentemente usada como condição em consultas; • se a maioria das consultas recuperar mais de 4% das linhas; • se a tabela for atualizada constantemente ( o banco vai sofrer para fazer a

manutenção).

Removendo índices:

DROP INDEX índice;

11. Procedures, Functions e Triggers

Procedures e functions são coleções de comandos SQL e PL/SQL. São objetos do banco de dados que nos permitem armazenar blocos de instruções

para executar determinadas tarefas. Atenção: não confundir objeto de banco de dados (procedure,

tables,indexes,sequences, etc...) com objeto de Orientação a Objetos. O Oracle também suporta a criação de classes e objetos e todos os recursos da Orientação a Objetos; mas para isto são necessários comandos e instruções específicos. Características

1. Armazenados de forma compilada no banco de dados (todo o texto ou fonte das procedures e functions)

2. Podem chamar outras procedures e functions ou serem chamadas 3. Podem ser chamadas por usuários em ambiente Cliente/Servidor (Delphi, VB) ou Web (asp, php)

Procedures e functions são semelhantes, a única diferença é que as functions podem retornar valores por elas próprias. Já nas procedures a única forma de termos retorno de valor é definindo uma variável de saída, o que pode inviabilizar sua utilização em alguns casos. Utilização 1. Definir uma central de funções de negócios exemplo: criar pedidos / eliminar cliente 2. Armazenar atividades em lotes (Job Batch) no banco de dados exemplo: fechamento mensal 3. Encapsular uma transação exemplo: reprocessar custo médio ou estoque de produtos 4. Canalizar as alterações de uma tabela em um único local.

exemplo: todas as alterações de salário e departamento do

Page 20: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

20

empregado é feita por uma única transação.

5. Criar códigos genéricos (comuns ou compartilhados) exemplo: manter as aplicações em um único banco de dados

6. Implementar restrições de segurança para dados protegidos diretamente pelo próprio gerenciador.

exemplo: somente determinados usuários terão direito de executar um determinado procedimento/função.

Comandos válidos 1. SQL DML ou PL/SQL

2. Chamada de outros procedimentos e funções armazenados no banco (remotos ou não)

Comandos inválidos

1. DDL (exceto em SQL dinânico) 2. SQL Dinâmico (em versões anteriores à 8 e sem a utilização de execute immediate) 3. COMMIT, ROLLBACK e SAVEPOINT para procedimentos e funções que serão chamados por uma Database Trigger e por procedures remotas

11.1. Erros de Compilação A compilação de PL/SQL é realizada pelo mecanismo Oracle PL/SQL. Erros de sintaxe ocorridos durante a compilação são armazenados no banco de dados. Para ver os erros: 1. Use no SQL * Plus, o comando SHOW ERRORS; 2. Selecione os erros através das visões (views): . USER_ERRORS . ALL_ERRORS . DBA_ERRORS Para ter acesso às visões ALL_ERRORS e DBA_ERRORS é necessário que os usuários tenham permissão para tanto. Já a visão USER_ERRORS é acessível aos usuários que tem permissão de acesso de visão ao catálogo (dicionário de dados). O SHOW ERRORS exibirá: . NAME nome do objeto . TYPE tipo do objeto (procedure,function,package,etc) . LINE número da linha em que ocorreu o erro . POSITION coluna da linha em que ocorreu o erro . TEXT descrição do erro

Page 21: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

21

11.2. Armazenamento no banco de dados O Oracle armazena em seu dicionário de dados o código fonte e o compilado de cada procedure, function, trigger ou package: 1. Compila os comandos PL/SQL do código fonte 2. Armazena os dados do procedimento:

a) Nome do objeto b) Código fonte c) Caminho de acesso (parse tree) d) Código compilado e) Informações sobre dependência (referência cruzada)

Nota: comandos SQL em procedimentos não são armazenados de forma compilada (parsed). Visões do dicionário de dados sobre procedimentos, funções, etc: . USER_SOURCE . ALL_SOURCE . DBA_SOURCE Colunas relevantes: . OWNER (não tem em USER_SOURCE) . NAME . TYPE . LINE . TEXT Exemplo:

SELECT TEXT FROM USER_SOURCE WHERE NAME = 'NOME_DO_OBJETO';

11.3. Descrição (describe) Podemos visualizar as informações de estrutura de procedures, functions e packages através do comando DESCRIBE. Sintaxe:

DESCRIBE NOME_DO_OBJETO; ou

DESC NOME_DO_OBJETO;

11.4. Dependências

Quando criamos procedures, functions ou triggers que em seu bloco de instruções é feito uso ou chamada de outras procedures ou functions, estes objetos que chamaram estes outros ficam dependentes deles. Ou seja, se numa procedure A chamo uma function B, temos que a procedure A é dependente a function B, de tal forma que se forem feitas

Page 22: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

22

modificações na function B e estas modificações resultarem em erro que a invalidem, então a procedure A também é invalidada. Para que a procedure A seja revalidada, tem-se que revalidar primeiro a function B e depois a procedure A. Isto é possível através da recompilação destes objetos. Um procedimento é dependente de:

1. Objetos de banco de dados que tem referência (dependência direta), como procedures, functions, tables, views, synonyms e sequences

2. Objetos que outros objetos dependem dele (dependência indireta). Exemplo: uma

procedure utiliza uma view de uma table, assim esta procedure tem dependência indireta desta table.

O Oracle verifica as dependências automaticamente. Quando um objeto do

banco de dados é modificado e o mesmo possui objetos dependentes, estes são marcados para serem recompilados na coluna STATUS da tabela USER_OBJECTS.

Objeto dependente deve ser recompilado se o objeto por ele referenciado for alterado. A recompilação dos dependentes é feita automaticamente em rempo de execução. Podemos obter informações das dependências através das views: . USER_DEPENDENCIES . ALL_DEPENDENCIES . DBA_DEPENDENCIES

11.5. Recompilação Procedures e functions podem ser recompilados manualmente pelo desenvolvedor ou automaticamente pelo RDBMS. Recompilação manual, sintaxe:

ALTER PROCEDURE [FUNCTION] [SCHEMA] NOME_DO_OBJETO COMPILE;

11.6. Procedures Sintaxe de criação CREATE [OR REPLACE] PROCEDURE [SCHEMA.] NOME_DA_PROCEDURE ( ARGUMENTO_1 [IN/OUT/IN OUT] TIPO_DO_DADO, ARQUMENTO_2 [IN/OUT/IN OUT] TIPO_DO_DADO, ... ) IS [AS] ...DECLARAÇÃO DE VARIÁVEIS... VARIAVEL_1 TIPO_DO_DADO; BEGIN INSTRUÇÕES PL/SQL... ... END; / SHOW ERRORS;

Page 23: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

23

Opção Descrição OR REPLACE Depois de criada uma procedure, se esta opção não for especificada

numa nova compilação, dará uma mensagem de erro mostrando que a esta procedure já existe. O comando REPLACE troca a procedure especificada e suas instruções internas pela que está sendo compilada.

SCHEMA Ou usuário dono do objeto procedure, se nada for epecificado será criado com o usuário corrente como dono.

IN Identifica se o parâmetro é de entrada – é a especificação default se nada for informado. Os parâmetros IN não podem ser seu conteúdo alterado dentro da procedure.

OUT Identifica se o parâmetro é de saída. Os parâmetros de saída podem ser alterados dentro da procedure, não sendo possível receber passagem de valores externos.

IN OUT Identifica que o parâmetro é de entrada e de saída. Isto significa que além de uma variável com esta especificação poder receber valores externos por parâmetro, esta também pode ser modificada dentro da procedure e ter seu valor recuperado no meio externo (aplicação/programa).

SHOW ERRORS Exibe os erros da procedure, se houver.

Exemplo 1: Criar uma procedure que receba como parâmetro de entrada o código de um funcionário e retorne em uma parâmetro/variável de saída o valor total dos vales retirados por este funcionário. CREATE OR REPLACE PROCEDURE CALCULA_VALES (P_FUN_COD IN FUNCIONARIO.FUN_COD%TYPE, P_TOTAL OUT NUMBER) IS BEGIN SELECT SUM(VALOR) INTO P_TOTAL FROM VALES_FUNC WHERE FUN_COD = P_FUN_COD; END; / SHOW ERRORS;

Testando a procedure no SQL*PLUS: -- declarando uma variável para receber o parâmetro de saída SQL> VARIABLE V_TOTAL NUMBER; -- executando a procedure SQL> EXECUTE CALCULA_VALES(387,:V_TOTAL); -- exibindo o conteúdo da variável que armazenou o retorno da ---- -- procedure SQL> PRINT V_TOTAL;

Page 24: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

24

Sintaxe para apagar uma procedure: SQL> DROP PROCEDURE NOME_DA_PROCEDURE;

11.7. Functions Sintaxe de criação: CREATE [OR REPLACE] FUNCTION [SCHEMA.] NOME_DA_FUNCTION ( ARGUMENTO_1 [IN/OUT/IN OUT] TIPO_DO_DADO, ARQUMENTO_2 [IN/OUT/IN OUT] TIPO_DO_DADO, ... ) RETURN TIPO_DE_DADO IS [AS] ...DECLARAÇÃO DE VARIÁVEIS... VARIAVEL_1 TIPO_DO_DADO; BEGIN INSTRUÇÕES PL/SQL... ... RETURN(...); END; / SHOW ERRORS; Opção Descrição OR REPLACE Depois de criada uma function, se esta opção não for especificada

numa nova compilação, dará uma mensagem de erro mostrando que a esta function já existe. O comando REPLACE troca a function especificada e suas instruções internas pela que está sendo compilada.

SCHEMA Ou usuário dono do objeto function, se nada for epecificado será criado com o usuário corrente como dono.

IN Identifica se o parâmetro é de entrada – é a especificação default se nada for informado. Os parâmetros IN não podem ser seu conteúdo alterado dentro da function.

OUT Identifica se o parâmetro é de saída. Os parâmetros de saída podem ser alterados dentro da function, não sendo possível receber passagem de valores externos.

IN OUT Identifica que o parâmetro é de entrada e de saída. Isto significa que além de uma variável com esta especificação poder receber valores externos por parâmetro, esta também pode ser modificada dentro da function e ter seu valor recuperado no meio externo (aplicação/programa).

SHOW ERRORS

Exibe os erros da procedure, se houver.

Page 25: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

25

Exemplo 1: Criar uma function que receba como parâmetro de entrada o número de uma nota fiscal e retorne o valor total dos produtos desta nota. CREATE OR REPLACE FUNCTION RET_TOTAL_PROD (P_NF_NUM IN NOTA.NF_NUM%TYPE) RETURN NUMBER IS V_TOTAL NUMBER; BEGIN SELECT SUM(VALOR_UNIT*QUANT) INTO V_TOTAL FROM ITENS_NOTA WHERE NF_NUM = P_NF_NUM; RETURN(V_TOTAL); END; / SHOW ERRORS;

Testando a function no SQL*PLUS: SQL> SELECT RET_TOTAL_PROD(5421) FROM DUAL; Sintaxe para apagar uma function: SQL> DROP FUNCTION NOME_DA_FUNCTION; 11.8. Triggers Um Database Trigger é um bloco PS/SQL associado a uma tabela específica. Ele é executado implicitamente quando é disparado um comando que altera o conteúdo de uma tabela. Um Trigger é composto por quatro partes: Trigger type BEFORE, AFTER – statment (comando) ou row (linha) Triggering event INSERT, UPDATE ou DELETE Trigger restriction WHEN cláusula (opcional) Trigger action Bloco PL/SQL Cada tabela (table) pode ter um Trigger de cada tipo, totalizando então 12 Triggers por tabela: . INSERT – UPDATE - DELETE . BEFORE – AFTER . FOR STATMENT – FOR EACH ROW (mais utilizado - recomendado)

Page 26: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

26

Sintaxe: CREATE [OR REPLACE] TRIGGER [SCHEMA.] NOME_DO_TRIGGER [BEFORE/AFTER][INSERT <OR> UPDATE <OF COLUMNS> <OR> DELETE] ON NOME_DA_TABELA REFERENCING [OLD AS NOME_OLD][NEW AS NOME_NEW] FOR [EACH ROW / STATEMENT] [WHEN CONDIÇÃO] DECLARE VARIAVEL_1 TIPO_DO_DADOS; ...DECLARAÇÃO DE VARIÁVEIS... BEGIN ... INSTRUÇÕES PL/SQL ... END; / SHOW ERRORS; Opção Descrição OR REPLACE Depois de criada uma trigger, se esta opção não for especificada

numa nova compilação, dará uma mensagem de erro mostrando que a esta trigger já existe. O comando REPLACE troca a trigger especificada e suas instruções internas pela que está sendo compilada.

SCHEMA Ou usuário dono do objeto trigger, se nada for epecificado será criado com o usuário corrente como dono.

BEFORE/AFTER Especifica se o trigger vai disparado antes ou depois do evento INSERT/UPDATE/DELETE

Indica em quais eventos o trigger será disparado. No caso de update ainda há a opção de especificar qual a coluna que deverá haver mudança para disparar o trigger.

ON NOME_TABELA Indica sobre qual tabela o trigger estará vinculado REFERENCING Geralmente é omitido, utilizado para nomear as referências OLD e

NEW disponíveis no trigger FOR EACH ROW Indica se o trigger será disparado após a alteração de cada linha

da tabela FOR EACH STATEMENT

Indica se o trigger será disparado após o término do comando de alteração da tabela (pouco utilizado)

WHEN CONDIÇÃO Pode-se nesta opção especificar uma condição para o disparo do trigger

SHOW ERRORS Exibe os erros da procedure, se houver.

Page 27: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

27

Exemplo 1: CREATE OR REPLACE TRIGGER TG_FUNC_SAL BEFORE INSERT OR UPDATE OF FUN_SAL ON FUNCIONARIOS FOR EACH ROW DECLARE V_MINSAL NUMBER; V_MAXSAL NUMBER; BEGIN SELECT MINSAL, MAXSAL INTO V_MINSAL, V_MAXSAL FROM FUNC_SALARIOS WHERE DEPTO = :NEW.DEPTO; IF :NEW.FUN_SAL < V_MINSAL OR :NEW.FUN_SAL > V_MAXSAL THEN RAISE_APPLICATION_ERROR(-20500,’Salário fora da

faixa’); END IF; END; Um Database Trigger e uma Procedure têm muitas coisas em comum. Similaridades:

1. Feitos através de comandos SQL e PL/SQL 2. Usam área SQL compartilhadas 3. O SGBD verifica automaticamente as dependências

Diferenças:

1. Um trigger está associado a uma tabela 2. Um trigger é chamado implicitamente, a procedure não 3. COMMIT, ROOLBACK e SAVEPOINT não são permitidos em triggers e em

procedures chamadas por eles. 4. Não há GRANT (privilégio) para executar um trigger

A execução de um trigger segue a seguinte sequência: 1. INSERT, UPDATE, DELETE são passados para o SGBD 2. Executa o Trigger Before em nível de comando (statement) 3. Para cada linha afetada com comando:

3.1. Executa o trigger Before em nível de linha (row) 3.2. Altera a linha, verifica a integridade referencial 3.3. Executa o trigger After em nível de linha (row)

4. Completa a verificação da integridade referencial 5. Executa o trigger After em nível de comando (statement) 6. Retorna para a aplicação

Expressões Para referenciar os valores novos e velhos das colunas no trigger, usa-se os prefixos OLD e NEW. Exemplo: IF :NEW.FUN_SAL < :OLD.FUN_SAL THEN ...

Page 28: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

28

Nota: 1. NEW e OLD são variáveis válidas somente para triggers 2. NEW e OLD - ambas disponíveis no comando UPDATE 3. OLD vale NULL no comando INSERT 4. NEW vale NULL no comando DELETE 5. Pode-se mudar NEW para NOVO (ou qualquer outro nome) e OLD para VELHO

(ou qualquer outro nome) utilizando a opção REFERENCING Predicados Condicionais Para identificar qual o tipo de operação (insert,update,delete) que disparou a trigger, utilizamos:

1. IF INSERTING... 2. IF UPDATING... 3. IF DELETING…

11.9. Atenção Um erro muito comum em stored procedures e triggers é a ocorrência, no bloco executável, de instruções “select” sem a cláusula “into”. Todo “select” nestes casos tem que possuir a cláusula “into”, atribuindo os valores das colunas de uma tabela para variáveis; e este “select...into” pode retornar somente 1 linha. Se retornar 0 linha ou mais de 1 linha, ocorre um erro.

Exemplo:

CREATE OR REPLACE FUNCTION RET_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE) RETURN VARCHAR2 IS V_CID_NOME CIDADE.CID_NOME%TYPE; BEGIN SELECT CID_NOME INTO V_CID_NOME FROM CIDADE WHERE CID_COD = P_CID_COD; RETURN(V_CID_NOME); END; No exemplo exposto, a restrição na chave primária não permite o erro de múltiplas linhas retornadas para dentro de uma variável, fica somente sujeito ao erro de nenhum dado encontrado se o código passado como parâmetro não existir. É apresentado a seguir recursos para o tratamento destes erros.

Page 29: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

29

12. Tratamento de Erros (Exceções) O tratamento de erros em PL/SQL ocorre em tempo de execução. Os erros em tempo de compilação são detectados pelo mecanismo da PL/SQL e informados ao usuário. Erros de sintaxes ou referências a objetos inexistentes são exemplos de exceções de compilação. DECLARE A NUMBER:=1; B NUMBER:=0; X NUMBER; BEGIN X := A/B; EXCEPTION WHEN OTHERS THEN -- qualquer erro ... tratamento/instruções END; Neste exemplo o erro será: ORA-01476: o divisor é igual a zero 12.1 Exceções definidas pelo usuário Os desenvolvedores de rotinas PL/SQL têm a possibilidade de criar erros personalizados que não se referenciam aos erros próprios do Oracle. Exemplo: CREATE OR REPLACE PROCEDURE ALTERA_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE, P_CID_NOME CIDADE.CID_NOME%TYPE, P_CID_UF CIDADE.CID_UF%TYPE) IS V_CONT NUMBER; V_MEU_ERRO EXCEPTION; BEGIN SELECT COUNT(*) INTO V_CONT FROM CIDADE WHERE CID_COD = P_CID_COD; IF VCONT=0 THEN RAISE V_MEU_ERRO; ELSE UPDATE CIDADE SET CID_NOME = P_CID_NOME, CID_UF = P_CID_UF WHERE CID_COD = P_CID_COD; END IF; EXCEPTION WHEN V_MEU_ERRO THEN RAISE_APPLICATION_ERROR(-20001,'CIDADE NÃO ENCONTRADA...'); END;

Bloco de tratamento de

erros

Declara uma variável do tipo exception

RAISE – desvia a execução para o bloco de tratamento de erros, para a variável correspondente.

Page 30: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

30

12.2 Exceções predefinidas O Oracle possui várias exceções predefinidas que correspondem aos erros mais comuns. Na tabela abaixo são apresentados alguns deles. Erro Oracle Exceções Descrição

ORA-0001 DUP_VAL_ON_INDEX Violação de restrição exclusiva

ORA-0051 TIMEOUT_ON_RESOURCE Tempo de espera esgotado

ORA-1403 NO_DATE_FOUND Não foram encontrados dados

ORA-1001 INVALID_CURSOR Operação de cursor ilegal

ORA-1722 INVALID_NUMBER Número inválido

ORA-1017 LOGIN_DENIED Nome do usuário/senha inválido

ORA-6501 PROGRAM_ERROR Erro interno do PL/SQL

ORA-1476 ZERO_DIVIDE Divisão por zero

ORA-6511 CURSOR_ALREADY_OPEN Tentativa de abertura de um cursor que já está aberto

ORA-1422 TOO_MANY_ROWS Uma instrução SELECT..INTO corresponde mais que uma linha

RAISE_APPLICATION_ERROR (número_erro,mensagem) Função pré-definida para o programador criar suas próprias mensagens de erros. Esta função aborta a execução do bloco/rotina correspondente. Número_erro: valor entre –20000 e –20999 Mensagem: texto de até 512 caracteres.

Page 31: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

31

Exemplo:

CREATE OR REPLACE FUNCTION RET_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE) RETURN VARCHAR2 IS V_CID_NOME CIDADE.CID_NOME%TYPE; BEGIN BEGIN SELECT CID_NOME INTO V_CID_NOME FROM CIDADE WHERE CID_COD = P_CID_COD; EXCEPTION WHEN NO_DATA_FOUND THEN V_NOME:= '**NÃO ENCONTRADO**'; WHEN TOO_MANY_ROWS THEN V_NOME:= '**MUITAS LINHAS ENCONTRADAS**'; WHEN OTHERS THEN V_NOME:= '**ALGUM ERRO OCORREU**'; END; RETURN(V_CID_NOME); END; 12.3 When Others Esta cláusula é executada em todas as exceções levantadas nas rotinas PL/SQL e deve ser sempre a última cláusula (handler) do bloco. Exemplo: CREATE OR REPLACE FUNCTION RET_SALARIO (P_FUN_CODIGO FUNCIONARIO.FUN_CODIGO%TYPE) RETURN NUMBER IS V_FUN_SAL FUNCIONARIO.FUN_SAL%TYPE; BEGIN SELECT FUN_SAL INTO V_FUN_SAL FROM FUNCIONARIO WHERE FUN_CODIGO = P_FUN_CODIGO; RETURN(V_FUN_SAL); EXCEPTION WHEN NO_DATA_FOUND THEN RAISE_APPLICATION_ERROR(-20001,’CODIGO DE FUNCIONARIO NÃO ENCONTRADO’); WHEN OTHERS THEN RAISE_APPLICATION_ERROR(-20002,’ALGUM OUTRO ERRO OCORREU...’); END; Pode-se construir blocos dentro de outros blocos e assim por diante, para que se tenha o funcionamento esperado.

Se neste “select” não encontrar nenhuma linha, então dá um erro de NO_DATA_FOUND, se houver qualquer outro erro, é capturado pelo WHEN OTHERS.

Page 32: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

32

Exemplo:

BEGIN BEGIN EXCEPTION WHEN . . . THEN INSERT...; IF . . . THEN. . . END IF; WHEN . . . THEN BEGIN EXCEPTION END; END; EXCEPTION END; 12.4 SqlCode e SqlErrm São funções predifinidas que retornam o código do erro atual e o texto da mensagem do erro atual, consecutivamente. São muito utilizados no tratamento de exceções “WHEN OTHERS” para informar o erro ocorrido. Exemplo: CREATE OR REPLACE PROCEDURE INCLUI_CLIENTE (P_CLI_COD CLIENTE.CLI_COD%TYPE, P_CLI_NOME CLIENTE.CLI_NOME%TYPE, P_MSG OUT VARCHAR2) IS BEGIN BEGIN P_MSG := ‘OK’; INSERT INTO CLIENTE (CLI_COD, CLI_NOME) VALUES(P_CLI_COD, P_CLI_NOME); EXCEPTION WHEN OTHERS THEN P_MSG := ‘ERRO..CODIGO: ’||TO_CHAR(SQLCODE)||’ MENSAGEM:’ ||SQLERRM; END; END; 12.5 Exception_Init Existe a possibilidade de associar um erro do Oracle a uma exceção nomeada (nome), ou seja, podemos associar um código de erro do Oracle a um nome.

Sintaxe:

PRAGMA_EXCEPTION_INIT(nome_do_erro,número_do_erro_oracle)

Page 33: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

33

Exemplo: CREATE OR REPLACE PROCEDURE EXCLUI_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE, P_ERRO OUT VARCHAR2, P_MSG OUT VARCHAR2) IS V_CONT NUMBER; V_ERRO1 EXCEPTION; V_ERRO2 EXCEPTION; -- EXCEPTION_INIT pragma PRAGMA EXCEPTION_INIT(V_ERRO2,-2292); -- integrity constraint violated - child record found BEGIN BEGIN P_ERRO := 'N'; P_MSG := 'OK'; SELECT COUNT(*) INTO V_CONT FROM CIDADE WHERE CID_COD = P_CID_COD; IF V_CONT = 0 THEN RAISE V_ERRO1; END IF; DELETE FROM CIDADE WHERE CID_COD = P_CID_COD; COMMIT; EXCEPTION WHEN V_ERRO1 THEN P_ERRO := 'S'; P_MSG := 'CÓDIGO NÃO ENCONTRADO....'; WHEN V_ERRO2 THEN P_ERRO := 'S'; P_MSG := 'NÃO FOI POSSÍVEL APAGAR. HÁ REGISTRO RELACIONADOS COM ESTE CODIGO...'; END; END;

Se durante o delete ocorrer o erro -2292, a exceção é capturada em V_ERRO2

Page 34: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

34

13. Cursor

Cursor é um artifício utilizado em PL/SQL para ter acesso a um conjunto de linhas resultantes de uma operação de banco de dados.

O Oracle sempre executa uma declaração SQL associando um cursor individual, ou nome, para ele; o cursor controla todas as fases do processo. Realiza intimamente todas as questões do banco de dados sem considerar o processamento da declaração SQL, o Oracle adquire antes a necessidade do cursor implícito e manuseia-os automaticamente. No entanto, para processar consultas explicitamente em ordem, declara cursores explicitamente e controla-os manualmente no bloco PL/SQL. A seleção de linhas que satisfaz o critério de procura de uma consulta consiste de zero, uma ou mais linhas. Quando uma consulta retornar mais de uma linha, declare e utilize um cursor explícito. 13.1 Cursor Explícito Cursores explícitos podem processar mais de uma linha retornada pela consulta, linha a linha. São criados e utilizados pelos programadores, desenvolvedores e DBA’s, geralmente em stored procedures e triggers, para realizar operações que necessitem de uma estrutura que assuma o resultado de uma instrução “select”. Para utilizar um cursor explícito deve-se:

a. declarar o cursor (declare) DECLARE CURSOR NOME_DO_CURSOR IS DECLARAÇÃO_SELECT; Onde: NOME_DO_CURSOR é uma declaração PS/SQL

DECLARAÇÃO_SELECT é uma declaração “SELECT” sem a cláusula “INTO”

Nota: Não inclua a cláusula “INTO” dentro da declaração do cursor, pois ele

aparece depois dentro da declaração “FETCH”, implicitamente. Se a declaração “SELECT” utiliza qualquer variável, é correto declará-la(s) antes da declaração do cursor.

b. abrir o cursor (open) OPEN NOME_DO_CURSOR; Onde: NOME_DO_CURSOR é o nome de um cursor declarado previamente.

c. buscar dados do cursor (fetch) FETCH NOME_DO_CURSOR INTO VARIAVEL1, VARIAVEL2,... Onde: NOME_DO_CURSOR é o nome do cursor declarado previamente. VARIAVEL é uma variável de saída para armazenar resultados.

Page 35: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

35

Nota: Inclua o mesmo número de variáveis dentro da cláusula “INTO” da declaração “FETCH” como colunas de saída na declaração “SELECT”, assim como a compatibilidade dos seus tipos.

As variáveis correspondem ao posicionamento das colunas. d. fechar o cursor (close) CLOSE NOME_DO_CURSOR;

Onde: NOME_DO_CURSOR é o cursor previamente declarado. Nota: Não tente buscar dados de um cursor uma vez que ele esteja fechado.

Para buscar linha a linha de um cursor, é necessário determinar quando entrar e sair de um “LOOP” pela inspeção de um atributo do cursor. Atributos de Cursor Descrição %ISOPEN atributo booleano que avalia se o cursor está aberto %NOTFOUND Atributo booleano que avalia se o mais recente “fetch” não

retornou nenhuma linha %FOUND Atributo booleano que avalia se o mais recente “fetch” retornou

alguma linha %ROWCOUNT Atributo numérico que retorna o número total de linhas que foram

processadas pelo “fetch” e não o total que será retornado pelo cursor explícito.

Nota: • não use atributos de cursor diretamente dentro de uma declaração SQL • busque linhas somente quando o cursor estiver aberto.

Exemplo 1:

DECLARE CURSOR C_ALUNOS IS

SELECT ALU_COD, DT_TRANCOU FROM ALUNOS WHERE DT_TRANCOU < TO_DATE('01/01/2000', 'DD/MM/YYYY');

V_ALU_COD ALUNOS.ALU_COD%TYPE; V_DT_TRANCOU ALUNOS.DT_TRANCOU%TYPE;

BEGIN OPEN C_ALUNOS; LOOP FETCH C_ALUNOS INTO V_ALU_COD, V_DT_TRANCOU; EXIT WHEN C_ALUNOS%NOTFOUND OR C_ALUNOS%ROWCOUNT=5; INSERT INTO TRANCADOS (ALU_COD, DT_TRANCOU) VALUES (V_ALU_COD, V_DT_TRANCOU); END LOOP; CLOSE C_ALUNOS; COMMIT;

END;

Page 36: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

36

Existe um caminho mais curto para buscar linhas de um cursor utilizando a estrutura “FOR LOOP”:

FOR NOME_DO_REGISTRO IN NOME_DO_CURSOR LOOP DECLARAÇÃO 1;

DECLARAÇÃO 2; ...

END LOOP;

Onde: NOME_DO_REGISTRO é o nome de um registro declarado implicitamente. NOME_CO_CURSOR é o nome do cursor previamente declarado.

Exemplo 2:

DECLARE V_NUM_PEDIDO PEDIDO_ITEM.NUM_PEDIDO%TYPE; CURSOR C_ITEM IS SELECT PROD_COD, SUM(QUANT*VALOR) AS TOTAL FROM PEDIDO_ITEM WHERE NUM_PEDIDO = V_NUM_PEDIDO GROUP BY PROD_COD; BEGIN V_NUM_PEDIDO := 10; FOR VREG IN C_ITEM LOOP -- open, fetch e declaração de VREG -- implícito INSERT INTO ACUMULADO (PROD_COD, TOTAL) VALUES (VREG.PROD_COD, VREG.TOTAL); END LOOP; /*close implícito*/ COMMIT; END;

Neste exemplo poderia ter sido declarada a variável VREG como VREG.C_ITEM%ROWTYPE, passando assim a assumir a estrutura de registro (linha) do cursor. Outro recurso interessante para ser usado em um cursores é a cláusula “FOR UPDATE” e “CURRENT OF”. Exemplo 3:

CREATE OR REPLACE PROCEDURE ATRIBUI_DESCONTOS (P_CUR_COD CURSOS.CUR_COD%TYPE)

IS CURSOR C_ALUNOS(P_CUR_COD) IS SELECT ALU_CPF, ALU_DESCTO FROM ALUNOS WHERE CUR_COD = P_CUR_COD

FOR UPDATE OF ALU_DESCTO; V_CONT NUMBER;

Page 37: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

37

BEGIN FOR VREG IN C_ALUNOS LOOP IF V_REG.ALU_DESCTO = 0 THEN

SELECT COUNT(*) INTO V_CONT FROM FUNCIONARIOS WHERE FUN_CPF = V_REG.ALU_CPF;

IF V_CONT <> 0 THEN UPDATE ALUNOS SET ALU_DESCTO = 50 WHERE CURRENT OF C_ALUNOS;

END IF; END IF; END LOOP; COMMIT; END;

Nota: é importante destacar que a cláusula “FOR UPDATE” faz com que os registros (linhas) da tabela que o cursor envolve sejam “locados/bloqueados” quando o cursor é aberto; e permanecem assim até que o mesmo seja fechado e após um “commit” ou “rollback” se foram feitas modificações nestas linhas da tabela. Exemplo 4:

No SQL/PLUS: SET SERVEROUTPUT ON; DECLARE CURSOR C_CLIENTE IS SELECT C.CLI_NOME, D.CID_NOME FROM CLIENTE C, CIDADE D WHERE C.CID_COD = D.CID_COD; VNOME CLIENTE.CLI_NOME%TYPE; VCIDADE CIDADE.CID_NOME%TYPE; BEGIN OPEN C_CLIENTE; LOOP FETCH C_CLIENTE INTO VNOME, VCIDADE; EXIT WHEN C_CLIENTE%NOTFOUND; DBMS_OUTPUT.PUT_LINE(VNOME||' - '||VCIDADE); END LOOP; CLOSE C_CLIENTE; END;

Exemplo 5 (outra forma de loop no cursor):

CREATE OR REPLACE PROCEDURE DESATIVA_CLIENTES IS BEGIN FOR VCLI IN (SELECT CLI_COD

FROM CLIENTE WHERE CLI_ATIVO='N') LOOP INSERT INTO CLIENTES_INATIVOS (CLI_COD, DATA) VALUES (VCLI.CLI_COD, SYSDATE); DELETE FROM CLIENTE WHERE CLI_COD = VCLI.CLI_COD;

Page 38: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

38

END LOOP; COMMIT; END;

13.2 Cursor Implícito O cursor implícito é chamado cursor SQL, porque ele armazena as informações referentes ao processamento da última declaração SQL não associada a um cursor explícito. Todas as instruções SQL são executadas dentro de uma área de contexto e, portanto, têm um cursor (implícito) que aponta para essa área. Diferentemente dos cursores explícitos, o cursor SQL não é aberto ou fechado pelo programa. A PL/SQL implicitamente abre o cursor SQL, processa a instrução SQL nele e em seguida fecha o cursor. Este cursor é utilizado para processar as instruções INSERT, UPDATE, DELETE E SELECT...INTO. Pelo fato de o cursor SQL ser aberto e fechado pelo mecanismo PL/SQL, os comandos OPEN, FETCH E CLOSE não são relevantes. Entretanto, os atributos de cursor podem ser aplicados no cursor SQL. Embora SQL%NOTFOUND possa ser utilizada com instruções SELECT...INTO, não é realmente útil fazer isso, pois uma instrução SELECT...INTO levantará o erro do Oracle (ORA-1403: no data found) quando ela não corresponder a nenhuma linha. Esse erro faz com que o controle passe imediatamente para a seção de tratamento de exceção do bloco, evitando a verificação em SQL%NOTFOUND.

Veremos nos exemplos a seguir as situações apresentadas. Atributos de Cursor Descrição

SQL%ISOPEN atributo booleano – sempre avalia para “FALSE” SQL%NOTFOUND Atributo booleano que avalia se a mais recente declaração SQL

não afetou nenhuma linha SQL%FOUND Atributo booleano que avalia se o mais recente declaração SQL

afetou uma ou mais linhas SQL%ROWCOUNT Atributo numérico que retorna o número total de linhas que foram

processadas pela declaração SQL mais recente.

Page 39: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

39

Exemplo 1: CREATE OR REPLACE PROCEDURE ALTERA_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE, P_CID_NOME CIDADE.CID_NOME%TYPE, P_CID_UF CIDADE.CID_UF%TYPE, P_ERRO OUT VARCHAR2, P_MSG OUT VARCHAR2) IS V_CID_COD CIDADE.CID_COD%TYPE; BEGIN P_ERRO := 'N'; P_MSG := 'OK'; UPDATE CIDADE SET CID_NOME = P_CID_NOME, CID_UF = P_CID_UF WHERE CID_COD = P_CID_COD; IF SQL%NOTFOUND THEN -- CURSOR IMPLICITO P_ERRO := 'S'; P_MSG := 'CÓDIGO NÃO ENCONTRADO...'; ELSE P_MSG := 'CIDADE ALTERADA COM SUCESSO...'; COMMIT; END IF; END;

Page 40: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

40

Exemplo 2: CREATE OR REPLACE PROCEDURE CONSULTA_CIDADE (P_CID_COD CIDADE.CID_COD%TYPE, P_CID_NOME OUT CIDADE.CID_NOME%TYPE, P_CID_UF OUT CIDADE.CID_UF%TYPE) IS BEGIN BEGIN SELECT CID_NOME, CID_UF INTO P_CID_NOME, P_CID_UF FROM CIDADE WHERE CID_COD = P_CID_COD; -- se o código da cidade não existir, não chega na verificação -- abaixo, dá erro no select e vai imediatamente para a seção -- de tratamento de erros IF SQL%NOTFOUND THEN P_CID_NOME := 'CIDADE NÃO ENCONTRADA...'; P_CID_UF := 'XX'; END IF; EXCEPTION -- bloco de tratamento de erros da PL/SQL - Oracle WHEN NO_DATA_FOUND THEN P_CID_NOME := 'CIDADE NÃO ENCONTRADA...'; P_CID_UF := 'XX'; END; END; 13.3 Ref Cursor Ref cursor ou cursor de referência é um tipo de variável de cursor que assume a estrutura de um “SELECT” como se fosse uma tabela, com múltiplas colunas e múltipas linhas; sua principal vantagem é poder ser um parâmetro de saída de uma procedure ou uma function. Este é um recurso muito interessante para ser utilizado em consultas (select). Complementando, uma variável de cursor é um tipo de referência. Ela pode referir-se a posições de memória diferentes à medida que o programa é executado. Os exemplos até aqui abordaram cursores estáticos que sempre estão associados a somente uma instrução “select”. Variáveis de cursor (ref cursor) podem conter diferentes valores em tempo de execução. TYPE nome_do_tipo IS REF CURSOR [RETURN tipo_de_retorno]

Onde: nome_do_tipo é o nome do novo tipo de referência tipo_de_retorno é um tipo de registro que indica os tipos da lista “select” que por fim retornarão pela variável de cursor.

Este bloco fica sem utilidade

Page 41: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

41

Exemplo 1 – declarando como um tipo específico (estático): DECLARE -- utilizando %rowtype TYPE TP_CIDADE IS REF CURSOR RETURN CIDADE%ROWTYPE; -- definindo um novo tipo de registro TYPE TP_REGISTRO IS RECORD (cli_nome cliente.cli_nome%type,

cid_nome cidade.Cid_nome%type);

V_VAR1 TP_REGISTRO;

-- criando uma variável de cursor que utiliza o tipo registro -- que foi criado TYPE TP_MEU_REFCURSOR IS REF CURSOR RETURN TP_REGISTRO;

V_MEU_CURSOR TP_MEU_REFCURSOR; Exemplo 2 – Fazendo um LOOP em um Ref Cursor:

CREATE OR REPLACE PROCEDURE TESTE_CLIENTES IS TYPE T_MEU_TIPO IS REF CURSOR; C_CLIENTE T_MEU_TIPO; VCLI_COD NUMBER(6); BEGIN OPEN C_CLIENTE FOR SELECT CLI_COD FROM CLIENTE; LOOP FETCH C_CLIENTE INTO VCLI_COD; EXIT WHEN C_CLIENTE%NOTFOUND; INSERT INTO CLIENTE_TESTE (CLI_COD) VALUES (VCLI_COD); END LOOP; CLOSE C_CLIENTE; COMMIT; END;

Para utilizarmos o Ref Cursor para declarar uma variável a ser utilizada como parâmetro de saída em uma procedure ou function, a principal funcionalidade no escopo em questão, tem-se que criar uma package criando e definindo um nome para um tipo “ref cursor”:

Page 42: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

42

Exemplo 3: Passo 1 – É necessária a criação do tipo “ref cursor”. Como trata-se de um cursor variável que pode representar diferentes estruturas e resultados de instruções “select”, basta criar um único tipo para ser utilizado em todo o banco de dados. Não há a necessidade de criar um tipo para cada variável ou parâmetro de stored procedure que tiver que ser declarada.

CREATE OR REPLACE PACKAGE PK_REF_CURSOR AS TYPE TP_REF_CURSOR IS REF CURSOR; END PK_REF_CURSOR; /

Passo 2 – Cria-se uma procedure ou function que tenha como parâmetro de saída uma variável do tipo ref cursor definido na package:

CREATE OR REPLACE PROCEDURE RETORNA_PRODUTOS (P_PRO_DESC IN PRODUTO.PRO_DESC%TYPE, P_SAIDA OUT PK_REF_CURSOR.TP_REF_CURSOR) AS BEGIN OPEN P_SAIDA FOR SELECT PRO_COD, PRO_DESC, PRO_PRVENDA FROM PRODUTO WHERE PRO_DESC LIKE '%'||P_PRO_DESC||'%' ORDER BY PRO_DESC; END;

Para testar no Sql/Plus: -- cria uma variável PL/SQL dentro do SQL/PLUS para receber o --- resultado do parâmetro de saída VARIABLE RETORNO REFCURSOR; EXECUTE RETORNA_PRODUTOS(‘A’,:RETORNO); PRINT RETORNO;

Page 43: Oracle Resumo

Universidade do Oeste Paulista Faculdade de Informática de Presidente Prudente

43

Referências Bibliográficas URMAN, Scott; tradução: Edson Furmankiewicz. Oracle 9i Programação PL/Sql. Rio de Janeiro: Elsevier, 2002.