Você está na página 1de 43

Universidade do Oeste Paulista

Faculdade de Informática de Presidente Prudente

Material de Apoio

Oracle

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

Í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

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

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 o schema é o mesmo que o nome do


(coluna tipo_de_dado dono. Na parte prática veremos com
[DEFAULT expressão]) mais atenção a criação de tabelas.

ALTER TABLE tabela acrescenta colunas em uma tabela


ADD (coluna tipo_de_dado
[DEFAULT expressão])
ALTER TABLE tabela altera colunas em uma tabela
MODIFY (coluna tipo_de_dado
[DEFAULT expressão])
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 adiciona comentário em tabela
‘comentário’ (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,

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

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).

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

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 “nome da 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:

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

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.

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

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;

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

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

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

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 retorna a posição em que a string2 está contida
(str1,str2,p_ini,ocorrencia,’string’) 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, decifra a coluna/expressão e compara com
pesquisa1, resultado1[, pesquisa2, pesquisaN, devolvendo como resultado o
resultado2,...,][default]) 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

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

(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.

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

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 Linguagem de manipulação de dados
Update (DML)
Delete
Create Linguagem de definição de dados (DDL)
Alter
Drop
Rename
Truncate
Commit Controles de Transações
Rollback
Savepoint
Grant Linguagem de controle de dados (DCL)
Revoke

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.

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

7.3. Sintaxe

7.3.1. Select

SELECT * FROM tabela; seleciona todos os elementos da tabela


SELECT seleciona as colunas mencionadas da
coluna1,coluna2,...,colunan tabela
FROM tabela;
SELECT (coluna1+300)+100, seleciona as colunas mencionadas com
coluna2* 2 FROM tabela; 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 posso dar um apelido as colunas
salário” FROM tabela; associando um alias ao mesmo. As aspas
duplas preservam a formatação interna
dos caracteres.
SELECT nome||’ ‘||sobrenome || é o operador de concatenação.
FROM tabela;
SELECT DISTINCT salário FROM a clausula distinct elimina as linhas
tabela; duplicadas na consulta.

7.3.2. Restringindo e ordenando dados

SELECT * seleciona todos os elementos da tabela


FROM tabela cujo nome seja exatamente ‘JOÃO’.
WHERE nome= ‘JOÃO’;
Operadores de comparação = (igual)
> (maior)
>= (maior ou igual)
< (menor)
<= (menor ou igual)
<> (diferente)

SELECT nome,salário posso colocar tantas cláusulas restritivas


FROM tabela quantas eu quiser adicionando AND, OR
WHERE cargo<>‘diretor’ and ou NOT - operadores lógicos.Têm a
salário > 10000; 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,

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

FROM tabela ORDER BY nome trazendo os dados de forma ordenada em


[DESC][ASC]; 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 Quando dados de mais de uma tabela no


tabela1.coluna1,tabela2.coluna2 banco de dados são requeridos, podem
FROM tabela1,tabela2 ser juntados com a cláusula WHERE ao
WHERE lado. Geralmente isto se dá com chaves
tabela1.chave1 = tabela2.chave2 primárias e chaves estrangeiras.
SELECT A SQL ao lado devolve um produto
tabela1.coluna1,tabela2.coluna2 cartesiano das duas tabelas (mostra para
FROM tabela1,tabela2 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 Retorna registros que não
SELECT tabela1.coluna1, necessariamente encontraram
tabela2.coluna2 correspondência. No Exemplo ao lado
FROM tabela1 , tabela2 pegamos os dados da tabela1 que não
WHERE tabela1.codigo(+) = têm correspondente na tabela2 e os
tabela2.codigo; exibimos mesmo assim com valor nulo.

Self join Podemos ter uma tabela relacionada com


SELECT unique e1.cargo, e1.nome ela mesmo e extrair os dados baseados
FROM empregados e1, nesta informação.
empregados e2 EMPREGADOS
EMP_COD, NOME, CHEFE
WHERE e1.chefe = e2.emp_codigo;

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

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

SELECT têm que estar agrupados ou usando


departamento,AVG(salário) funções de agrupamento.
FROM empregados
GROUP BY departamento
HAVING Esta cláusula é usada para especificar
quais grupos serão mostrados.
SELECT
departamento,AVG(salário)
FROM empregados
GROUP BY departamento
HAVING AVG(salário) > 1000
ORDER BY departamento

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;

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

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, Opcional


exceções definidas pelo usuário que
estão referenciadas nas sessões de
execução
Executável contém as declarações SQL para Obrigatória
manipulação de dados no banco de
dados e instruções PL/SQL para
manipulação de dados no bloco.
Exception Handling Especifica a ação a tomar quando erros Opcional
(manipulação de exceções) e condições anormais ocorrem na
sessão executável.

Tipos de blocos

Anonymous Procedure Function


[DECLARE] PROCEDURE nome IS FUNCTION nome
RETURN tipo_de_dado
BEGIN BEGIN IS
-- comandos -- comandos
[EXCEPTION] [EXCEPTION] BEGIN
-- comandos
END; END; 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;

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

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“.

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

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;

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

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: Chave do índice

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;

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

• 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

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

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
. TYPEtipo 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

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

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

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

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;

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

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;

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

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 Exibe os erros da procedure, se houver.
ERRORS

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

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)

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

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/D Indica em quais eventos o trigger será disparado. No caso de
ELETE 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 Indica se o trigger será disparado após o término do comando de
STATEMENT 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.

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

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 ...

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

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.

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

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 Bloco de
A NUMBER:=1; tratamento de
B NUMBER:=0; erros
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; Declara uma variável do tipo exception
V_MEU_ERRO EXCEPTION;
BEGIN
SELECT COUNT(*) INTO V_CONT
FROM CIDADE
WHERE CID_COD = P_CID_COD;
IF VCONT=0 THEN RAISE – desvia a execução para o
RAISE V_MEU_ERRO; bloco de tratamento de erros, para a
ELSE variável correspondente.
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;

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

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.

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
Tentativa de abertura de um cursor que
ORA-6511 CURSOR_ALREADY_OPEN
já está aberto
Uma instrução SELECT..INTO
ORA-1422 TOO_MANY_ROWS
corresponde mais que uma linha

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

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 Se neste “select” não encontrar


FROM FUNCIONARIO nenhuma linha, então dá um erro
WHERE FUN_CODIGO = P_FUN_CODIGO; de NO_DATA_FOUND, se
houver qualquer outro erro, é
RETURN(V_FUN_SAL); capturado pelo WHEN OTHERS.

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.

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

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)

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

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 Se durante o delete ocorrer o erro


FROM CIDADE -2292, a exceção é capturada em
WHERE CID_COD = P_CID_COD; V_ERRO2

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;

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

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.

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

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;

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

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;

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

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;

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

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.

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

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;

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

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 Este bloco


P_CID_NOME := 'CIDADE NÃO ENCONTRADA...'; fica sem
P_CID_UF := 'XX'; utilidade
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.

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

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”:

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

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;

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

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

43

Você também pode gostar