Casa do Código
Prefácio
Sempre gostei de livros que “conversam” com o leitor, principalmente os técnicos. Como se fosse uma troca de ideias entre o autor e a pessoa que o está
lendo. Procurei escrever desta forma, pois creio que com isso a leitura se torna
mais clara e amigável, um bate papo entre amigos, conversando sobre qualquer assunto. A intenção foi colocar aqui tudo o que você vai precisar saber
sobre a linguagem PL/SQL. O livro aborda conceitos que são utilizados no
dia a dia do desenvolvimento e análise de sistemas para banco de dados Oracle. Demonstrei diversos exemplos, que também vão ajudá-lo como fonte de
referência para consulta de comandos e como utilizá-los. Tenha uma otima
leitura!
Público alvo
Este livro se destina a iniciantes e experientes na linguagem PL/SQL. Para
os iniciantes, são abordados conceitos sobre a estrutura da linguagem PL/SQL
e suas características. Ele ensina como criar programas, dos mais simples
até os mais complexos, para atender às mais diversas necessidades. Você vai
aprender como esta linguagem pode trazer um alto grau de produtividade e
performance para as suas aplicações. Para os já experientes, ele ajudará como
fonte de referência e para relembrar conceitos e técnicas da linguagem.
Como o livro está dividido?
Primeiramente, são abordados conceitos básicos da linguagem, como sua
definição, como é estruturada e seus principais componentes. Logo após, entramos a fundo na sua estrutura, conhecendo cada comando e cada compoi
Casa do Código
nente que ela utiliza, explorando suas funcionalidades e propriedades. O livro também mostra como incorporar a linguagem SQL dentro dos programas
escritos em PL/SQL, para a recuperação e manipulação de dados. Tipos de
dados, estruturas condicionais e de repetição, armazenamento de programas
através de procedures (procedimentos) e functions (funções), e modularização
através de packages (pacotes) são alguns dos itens mostrados.
Toda essa abordagem é realizada no âmbito prático, onde são detalhadas
suas estruturas, seus comandos e características, sempre através de exemplos
práticos e de fácil compreensão.
Os scripts de base (tabelas e dados) e fontes para a execução
dos exemplos do livro estão disponíveis no endereco https://github.com/
eduardogoncalvesbr/livroplsql-casadocodigo.
Confira outras obras do autor
SQL: Uma abordagem para bancos de dados Oracle http://www.
casadocodigo.com.br/products/livro-sql-oracle
Contatos
Para falar com o autor, envie e-mail para eduardogoncalhttps://www.facebook.com/
ves.br@gmail.com Página no facebook:
eduardogoncalvesescritor
ii
Casa do Código
Sobre o autor
Formado em Tecnologia da Informação, possui mais de 10 anos de experiência em análise e desenvolvimento de sistema voltados a tecnologias Oracle,
trabalhando por grandes empresas como Lojas Renner, Mundial S.A, Tigre
S.A, Pernambucanas, Tractebel Energia, Portobello Ceramica, Bematech, entre outros. Eduardo Gonçalvez é instrutor de cursos oficiais da Oracle – nas
linguagens SQL e PL/SQL. Também atua no desenvolvimento de aplicações
mobile para a plataforma iOS. Atualmente, atua como Coordenador de Operações na Supero Tecnologia.
iii
Casa do Código
Agradecimentos
Dedico este livro a todas os meus amigos e colegas da área de tecnologia, bem
como meus professores e mentores, que tive o prazer de conhecer, e com os
quais aprendi e até mesmo trabalhei. Durante esta minha trajetória aprendi
muitas coisas com estas pessoas extraordinárias. Trocamos experiências e
aprendemos muito, uns com os outros, programando e quebrando a cabeça
para escrever a linha de código que ajudasse a solucionar um problema (regado a muito café, na maioria das vezes... risos), ou até mesmo, apenas pela
paixão de programar. Saibam que cada um de vocês contribuiu imensamente
para este trabalho! Sem vocês isto não seria possível! Ficam aqui meus sinceros agradecimentos!
v
Casa do Código
Sumário
Sumário
1
PL/SQL
1.1 O que é PL/SQL? . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Por que aprender PL/SQL? . . . . . . . . . . . . . . . . . . . .
1.3 SQL, SQL*Plus, PL/SQL: Qual é diferença? . . . . . . . . . .
1
1
2
3
2
Programação em bloco
7
3
Primeiros passos
3.1 Como iniciar no PL/SQL . . . . . . . . . . . . . . . . . . . . .
13
13
4 Pacote dbms_output
4.1 Exceções para o pacote dbms_output . . . . . . . . . . . . . .
19
26
5
27
27
31
35
Variáveis bind e de substituição
5.1 Variáveis bind . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Variáveis de substituição . . . . . . . . . . . . . . . . . . . . .
5.3 Utilizando variáveis em arquivos . . . . . . . . . . . . . . . .
6 Aspectos iniciais da programação PL/SQL
6.1 Caracteres e operadores . . . . . . . . . .
6.2 Identificadores . . . . . . . . . . . . . . .
6.3 Transações . . . . . . . . . . . . . . . . .
6.4 Transações em PL/SQL . . . . . . . . . .
6.5 Trabalhando com variáveis e constantes
6.6 Tipos de dados em PL/SQL . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
43
44
44
47
51
52
53
vii
Casa do Código
Sumário
7
Exceções
7.1 Exceções predefinidas . . . . . . . . . . . . . . . . . . . . . . .
7.2 Exceções definidas pelo usuário . . . . . . . . . . . . . . . . .
59
60
79
8
Estruturas de condição: if
8.1 Estruturas do comando if-end if . . . . . . .
8.2 Estruturas do comando if-else-end if . . . .
8.3 Estruturas do comando if-elsif(-else)-end if
8.4 Formatando as declarações if . . . . . . . . .
8.5 Evitando erros comuns no uso de if . . . . .
.
.
.
.
.
85
86
87
89
93
94
.
.
.
.
95
95
101
102
105
10 Cursores
10.1 Cursores explícitos . . . . . . . . . . . . . . . . . . . . . . . . .
107
108
9 Comandos de repetição
9.1 for loop . . . . . . . . .
9.2 while loop . . . . . . . .
9.3 loop . . . . . . . . . . .
9.4 Qual loop deve-se usar?
10.3
10.4
10.5
10.6
10.7
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
118
119
121
128
130
11 Funções de caracteres e operadores aritméticos
11.1 Funções de caracteres . . . . . . . . . . . . . . . . . . . . . . .
11.2 Funções de cálculos . . . . . . . . . . . . . . . . . . . . . . . .
11.3 Operadores aritméticos . . . . . . . . . . . . . . . . . . . . . .
143
144
149
154
12 Funções de agregação (grupo)
159
13 Funções de data
177
viii
Cursor for loop com definição interna .
Cursores implícitos . . . . . . . . . . . .
Atributos de cursor explícito e implícito
Cursores encadeados . . . . . . . . . . .
Cursor com for update . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Casa do Código
Sumário
14 Funções de conversão
183
14.1 to_date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
14.2 to_number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
14.3 to_char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
15 Funções condicionais
15.1 decode vs. case . . . . . . . . . . . . . . . . . . . . . . . . . . .
211
217
16 Programas armazenados
16.1 procedures e functions . . . . . . . . . .
16.2 Uso do comando replace . . . . . . . . .
16.3 Recompilando programas armazenados
16.4 Recuperando informações . . . . . . . .
16.5 Recuperando códigos . . . . . . . . . . .
16.6 Visualizando erros de compilação . . . .
16.7 Passando parâmetros . . . . . . . . . . .
16.8 Dependência de objetos . . . . . . . . . .
.
.
.
.
.
.
.
.
225
226
236
238
238
239
240
243
249
.
.
.
.
.
.
265
266
270
278
278
279
280
17 packages
17.1 Estrutura de um package . . . . .
17.2 Acesso a packages . . . . . . . . .
17.3 Recompilando packages . . . . . .
17.4 Recuperando informações . . . .
17.5 Recuperando códigos . . . . . . .
17.6 Visualizando erros de compilação
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18 Transações autônomas
283
19 Triggers
19.1 Trigger de banco de dados
19.2 Trigger de tabela . . . . . .
19.3 Trigger de linha . . . . . .
19.4 Mutante table . . . . . . . .
19.5 Trigger de sistema . . . . .
19.6 Trigger de view . . . . . . .
293
294
294
301
316
324
330
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
ix
Sumário
Casa do Código
20 PL/SQL Tables (estruturas homogêneas)
349
21 PL/SQL Records (estruturas heterogêneas)
359
22 Pacote utl_file
365
23 SQL dinâmico
23.1 Ref cursor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
385
397
24 Apêndice: SQL – Primeiros passos
405
24.1 Como iniciar no SQL . . . . . . . . . . . . . . . . . . . . . . . 405
25 Referências bibliográficas
413
26 Anexos
415
x
Capítulo 1
PL/SQL
1.1
O que é PL/SQL?
A sigla PL/SQL significa Procedural Language / Structured Query Language,
ou seja, trata-se de uma linguagem procedural tendo como base a SQL (Linguagem de Consulta Estruturada). A PL/SQL é direcionada para o banco de
dados Oracle e é escrita através de blocos de código que são executados diretamente no banco de dados. Ela permite o desenvolvimento de programas
complexos, nos quais grandes volumes de informação são processados.
Como qualquer outra linguagem de programação, a PL/SQL é escrita
através de códigos, sendo que os princípios de lógica de programa e programação estruturada podem ser implementados.
Os blocos PL/SQL podem ser escritos e guardados no próprio banco de
dados, através de funções ( functions), procedimentos ( procedures),
1.2. Por que aprender PL/SQL?
Casa do Código
gatilhos ( triggers) ou pacotes ( packages) para serem executados e reaproveitados quando necessário.
Os códigos podem ser feitos utilizando-se uma interface, como o
SQL*Plus, que é totalmente integrada ao banco de dados. Outras ferramentas como Oracle Forms, Oracle Reports e Workflow Builder também possuem motores PL/SQL que permitem validar e compilar os códigos escritos
em PL/SQL.
Através de todos esses atributos, a PL/SQL se mantém como uma linguagem robusta e muito utilizada pelos desenvolvedores e analistas do mundo
todo. Muito provavelmente, isso se dá ao fato de sua crescente história, que
vem desde as primeiras versões do banco de dados e sua evolução permanente
desde então.
No mais, a PL/SQL dá suporte aos mais variados recursos de programação de sistemas como a utilização de variáveis, constantes, cursores, estruturas
de repetição e condicional, o uso de pacotes, funções, procedimentos armazenados, tratamento de erros, chamadas à API, gatilhos, vetores, registros,
execução direta de comandos SQL etc. Além do mais, ela condiciona em sua
estrutura os padrões ANSI para linguagem SQL e suporte à codificação Java.
1.2 Por que aprender PL/SQL?
É importante conhecer a linguagem PL/SQL, independente da utilização ou
não das ferramentas de desenvolvimento. Mesmo utilizando apenas o banco
de dados, é fundamental conhecê-la tendo em vista que muitos processos
dentro do servidor do banco são escritos ou executados por blocos nesta linguagem.
No que diz respeito ao desenvolvimento, a PL/SQL proporciona rapidez,
eficiência e segurança para seus programas, pois seus códigos, ou melhor, programas, podem ser armazenados no banco de dados. Assim sendo, na próxima vez que precisar executá-lo novamente, é só chamá-lo, ele já está pronto.
Outro ponto interessante é que os programas não precisam estar no cliente,
já que a PL/SQL utiliza o servidor do banco de dados para a execução e armazenamentos dos seus processos.
Outra vantagem de se aprender PL/SQL é que no banco de dados Oracle,
2
Casa do Código
Capítulo 1. PL/SQL
embora seja implementado em diversas plataformas de hardware e software, a
PL/SQL é igual para todas elas. Com isto, a portabilidade se mantém presente.
1.3
SQL, SQL*Plus, PL/SQL: Qual é diferença?
É tanto “SQL” nos títulos dos produtos Oracle que acabamos nos confundindo. Vamos entender o que é cada uma destas siglas.
• SQL: a sigla SQL significa Structured Query Language. É uma linguagem estruturada de acesso aos bancos de dados, declarativa, que usa
comandos como SELECT, INSERT, UPDATE e DELETE. Ela sempre
é executada no servidor através de uma interface conectada ao banco
de dados. Apesar de não ser propriedade da Oracle, ela a incorpora em
sua estrutura base e em suas linguagens.
• PL/SQL: é uma linguagem de procedimentos, propriedade da Oracle.
Caracteriza-se por uma linguagem não declarativa, ou seja, não bastam
apenas comandos SQL. É necessário o uso de codificação em blocos,
chamados blocos PL/SQL. Os códigos podem ser executados tanto no
cliente (Oracle Forms, Reports etc.) quanto diretamente no servidor
do banco de dados.
• SQL*Plus: pode-se dizer que ele é a interface entre o usuário e o banco
de dados. Quando executamos um comando SQL ou um bloco PL/SQL
pelo SQL*Plus, ele os envia a um motor PL/SQL que executa os comandos PL/SQL e verifica a existência de comandos SQL. Caso existam, são
enviados para um executor SQL, que os passa para o banco de dados.
O SQL*Plus exibe o resultado na tela do seu computador.
Para visualizar de forma mais clara os conceitos empregados, observe a
imagem a seguir onde é mostrado o papel de cada um dentro do contexto de
suas aplicações.
3
1.3. SQL, SQL*Plus, PL/SQL: Qual é diferença?
Casa do Código
Fig. 1.1: Esquema com as funções do SQL*Plus, PLSQL e SQL
Conforme foi dito, através do SQL*Plus nós podemos entrar com comandos SQL ou blocos PL/SQL. Eles são encaminhados ao servidor do banco de
dados, que pode direcionar para o motor PL/SQL, ou seja, o processador que
vai validar e executar o bloco PL/SQL, e/ou para o executor de declarações de
comandos SQL. Através desta visualização é possível entender a finalidade e
importância de cada um desses produtos.
Um ponto importante a entender é como são processadas as instruções
SQL e blocos PL/SQL dentro de aplicações desenvolvidas com Oracle Forms
ou Reports. Para entendimento, o Oracle Forms e Reports são ferramentas
RAD para o desenvolvimento de formulários e relatórios. Essas ferramentas
se conectam nativamente ao banco de dados Oracle. O termo “nativamente”
faz referência a como é realizada a conexão com o banco de dados. Na maioria das vezes, uma aplicação se conecta através de drivers disponíveis pela
ferramenta ou por algum gerenciador de conexão, por exemplo, via ODBC
(encontrado no Windows). Pois bem, dentro das ferramentas Oracle é possível inserir tanto comandos SQL, quanto blocos PL/SQL. Esses comandos ou
blocos serão executados para algum fim e quando isso acontece a solicitação
de execução pode ser feita de formas diferentes
4
Casa do Código
Capítulo 1. PL/SQL
Quando temos dentro da aplicação comandos SQL distintos, eles são enviados um a um para o servidor do bando de dados. Dessa forma, a aplicação
envia um comando para o servidor, espera a resposta e depois envia outro.
Quando temos blocos PL/SQL, eles são enviados por completo ao servidor do banco de dados, não importando o seu teor. Dentro deste bloco podemos ter vários comandos SQL e demais estruturas em PL/SQL. Desse modo
economizamos tempo, pois a aplicação envia de uma só vez todas as solicitações, e o número de respostas esperadas também reduz muito. Reduzindo o
número de respostas e tráfego de informações entre aplicação e o servidor do
banco de dados aumentamos a chance de ganho de desempenho, principalmente se esta comunicação depender de uma rede cliente x servidor. Veja a
seguir a ilustração deste conceito.
Fig. 1.2: Diferença entre comandos SQL e Blocos PLSQL
5
Capítulo 2
Programação em bloco
A linguagem PL/SQL trabalha em blocos de comando. Dentro de bloco podemos ter outros blocos, que neste caso são chamados de sub-blocos. Quando
queremos escrever um programa para um determinado fim, utilizamos blocos para estruturar os comandos e a forma de como este programa vai se comportar.
Um bloco PL/SQL é iniciado pela expressão begin e é finalizada por
end. Estas duas expressões determinam a área do nosso bloco. Veja um exemplo de bloco PL/SQL.
❙◗▲❃ ❜❡❣✐♥
✷
✸ ❡♥❞❀
✹
❙◗▲❃
Casa do Código
Como mencionado anteriormente, podemos ter blocos dentro de outros
blocos, os quais são chamados de sub-blocos.
❙◗▲❃ ❜❡❣✐♥
✷
❜❡❣✐♥
✸
✹
❡♥❞❀
✺
✻
✼ ❡♥❞❀
✽
❙◗▲❃
Além das expressões de delimitação do bloco, também podemos ter o
declare, que é utilizado para delimitar uma área para declaração de variáveis que serão utilizadas pela aplicação e também a expressão exception,
que delimita uma área para tratamento de erros. Basicamente, um bloco
PL/SQL é composto por:
• Área de declaração de variáveis ( declare);
• Área de escopo para inserção de comandos e demais sub-blocos (
begin-end);
• Área de tratamento de erros.
A seguir um bloco PL/SQL contemplando estas premissas básicas.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✸ ❜❡❣✐♥
✹
✺
❜❡❣✐♥
✻
✼
❡♥❞❀
✽
✾ ❡①❝❡♣t✐♦♥
✶✵
✇❤❡♥ ♦t❤❡rs t❤❡♥
8
Casa do Código
Capítulo 2. Programação em bloco
✶✶
✶✷ ❡♥❞❀
✶✸
✶✹
❙◗▲❃
Este tipo de bloco é chamado de bloco anônimo, pois não possuem um
cabeçalho e também não podem ser gravados diretamente no banco de dados.
Caso você queira executá-los novamente, é necessário salvar em um arquivo,
pois ao fechar a ferramenta ele não é guardado.
A programação em bloco torna os programas mais estruturados e limpos. Principalmente, quando utilizamos vários sub-blocos para a realização
de determinadas tarefas distintas, como a seleção de dados, uma atualização
ou exclusão. Fazendo desta forma, é possível tratar cada bloco buscando uma
programação mais lógica e que possa fornecer informações sobre os comandos contidos nele ou até mesmo identificar possíveis erros que possam surgir.
Veja um exemplo de programa.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
❞❡❝❧❛r❡
s♦♠❛ ♥✉♠❜❡r❀
❜❡❣✐♥
s♦♠❛ ✿❂ ✹✺✰✺✺❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙♦♠❛ ✿✬⑤⑤s♦♠❛✮❀
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✶✱✬❊rr♦ ❛♦ s♦♠❛r ✈❛❧♦r❡s✦✬✮❀
❡♥❞❀
❙◗▲❃
Neste programa, é possível verificar a existência de uma área de declaração de variáveis onde temos a variável soma declarada como number (veremos estes conceitos mais adiante); uma área onde são inseridos os comandos
propriamente ditos, soma recebendo a soma de 45+45. Também temos o pacote dbms_output, utilizado quando queremos escrever algo na tela. Neste
caso, estamos solicitando a escrita do resultado da soma. Por último, temos
9
Casa do Código
uma área de declaração de erros onde podemos tomar alguma ação caso um
erro aconteça. Neste exemplo, caso surja qualquer tipo de erro, chamamos o
procedimento raise_application_error, que faz com que a aplicação
pare e imprima uma mensagem na tela.
Vale lembrar que as áreas de declaração e tratamento de erros podem existir também dentro dos sub-blocos.
Ok. Nosso programa já está criado. Agora vamos ver como executálo. Para isso, podemos utilizar a ferramenta SQL*Plus. Através do comando
barra / podemos executar um bloco PL/SQL.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
❙♦♠❛
❞❡❝❧❛r❡
s♦♠❛ ♥✉♠❜❡r❀
❜❡❣✐♥
s♦♠❛ ✿❂ ✹✺✰✺✺❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙♦♠❛ ✿✬⑤⑤s♦♠❛✮❀
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✶✱✬❊rr♦ ❛♦ s♦♠❛r ✈❛❧♦r❡s✦✬✮❀
❡♥❞❀
✴
✿✶✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
O comando / executa o bloco PL/SQL, mostrando a saída gerada pelo
dbms_output. Blocos PL/SQL não necessariamente possuem uma saída impressa na tela. Uma mensagem indicando que o bloco foi executado com sucesso também é mostrada. Caso ocorra algum erro de sintaxe na construção
do comando, ou seja, algum comando escrito incorretamente ou uma função
utilizada indevidamente, ele também é mostrado. A seguir vamos simular um
erro de sintaxe para ver como a ferramenta se comporta.
❙◗▲❃ ❞❡❝❧❛r❡
✷
s♦♠❛ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
s♦♠❛ ✹✺✰✺✺❀
10
Casa do Código
Capítulo 2. Programação em bloco
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙♦♠❛ ✿✬⑤⑤s♦♠❛✮❀
✻ ❡①❝❡♣t✐♦♥
✼
✇❤❡♥ ♦t❤❡rs t❤❡♥
✽
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✶✱✬❊rr♦ ❛♦ s♦♠❛r ✈❛❧♦r❡s✦✬✮❀
✾ ❡♥❞❀
✶✵ ✴
s♦♠❛ ✹✺✰✺✺❀
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✹✿
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✹✱ ❝♦❧✉♥❛ ✽✿
P▲❙✲✵✵✶✵✸✿ ❊♥❝♦♥tr❛❞♦ ♦ sí♠❜♦❧♦ ✧✹✺✧ q✉❛♥❞♦ ✉♠ ❞♦s s❡❣✉✐♥t❡s
sí♠❜♦❧♦s ❡r❛ ❡s♣❡r❛❞♦✿
✿❂ ✳ ✭ ❅ ✪ ❀
❖ sí♠❜♦❧♦ ✧✿❂✧ ❢♦✐ s✉❜st✐t✉í❞♦ ♣♦r ✧✹✺✧ ♣❛r❛ ❝♦♥t✐♥✉❛r✳
❙◗▲❃
Quando o comando é executado, a ferramenta SQL*Plus faz várias verificações, inclusive a de sintaxe de comandos. Na linha 4 está faltando o
comando de atribuição := que atribui a soma de 45+55 à variável soma.
Com isso, um erro é gerado e mostrado na tela. Ele geralmente vem acompanhado de algumas informações como a linha e a coluna onde o erro está ocorrendo. Além disso, a ferramenta costuma clarear o motivo pelo qual o erro
está ocorrendo. Neste nosso exemplo, ele diz que foi encontrado o símbolo
“45” quando na verdade era esperado algum outro, por exemplo, o símbolo
de atribuição.
Note que este erro foi detectado antes mesmo de o Oracle executar o
bloco. Agora vamos gerar um erro, mas não de sintaxe, mas sim, um erro
referente a dados incorretos. Vamos tentar somar números com caracteres
alfanuméricos.
❙◗▲❃ ❞❡❝❧❛r❡
✷
s♦♠❛ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
s♦♠❛ ✿❂ ✹✺✰✬❆✬❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙♦♠❛ ✿✬⑤⑤s♦♠❛✮❀
✻ ❡①❝❡♣t✐♦♥
11
Casa do Código
✼
✇❤❡♥ ♦t❤❡rs t❤❡♥
✽
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✶✱✬❊rr♦ ❛♦ s♦♠❛r ✈❛❧♦r❡s✦✬✮❀
✾ ❡♥❞❀
✶✵ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✶✿
❖❘❆✲✷✵✵✵✶✿ ❊rr♦ ❛♦ s♦♠❛r ✈❛❧♦r❡s✦
❖❘❆✲✵✻✺✶✷✿ ❡♠ ❧✐♥❡ ✽
❙◗▲❃
Agora temos outro erro, entretanto, ele ocorreu quando o bloco foi executado. Neste caso, o programa transferiu a ação para a área de tratamento de
erros, gerando uma saída que informa a circunstância em que erro aconteceu.
Já vimos que para construir um programa em PL/SQL temos que trabalhar em nível de bloco. Assim sendo, a linguagem PL/SQL permite adicionar,
dentro das estruturas destes blocos, todo e qualquer recurso para que este
programa possa executar ações ou procedimentos servindo.
Dentro dos blocos é possível declarar variáveis e constantes, executar comandos DML ( select, delete, update e insert), executar procedimentos armazenados, funções, utilizar estruturas de repetição, estruturas de
condição, além do uso de operadores relacionais e numéricos.
12
Capítulo 3
Primeiros passos
3.1
Como iniciar no PL/SQL
Uma das dificuldades que encontramos quando estamos aprendendo uma
linguagem de programação é saber por onde começar. No caso do aprendizado da PL/SQL, não seria diferente. É uma situação normal. Até sentirmos
segurança e termos conhecimento suficiente, é interessante termos um roteiro
contendo os primeiros passos para iniciar um programa PL/SQL.
Demonstro aqui uma técnica que utilizo bastante, mesmo tendo um bom
conhecimento na linguagem. Na verdade, já está implícito na minha forma de
pensar, tanto que acabo executando-a mentalmente, enquanto escrevo nesta
linguagem. Este método não foi retirado de nenhum livro, foi algo que, entendendo a lógica, fui seguindo e deu certo. Espero que ajude vocês.
Vamos tomar como exemplo, o enunciado a seguir:
Casa do Código
3.1. Como iniciar no PL/SQL
Escreva um programa PL/SQL que imprima na tela os nomes os empregados de um determinado gerente e de uma determinada localização.
Primeiro passo
Identifico no enunciado as fontes de dados, ou seja, as tabelas que farão
parte do programa, caso seja necessário.
Caso tenha dúvida em identificar a fonte de dados, veja o documento: 24.
Após identificar as tabelas, monto os selects e executo os comandos para
trazer os dados que o programa solicita. Tudo isso sem escrever uma única
linha em PL/SQL. Somente monto os selects e os executo para ver se os
dados estão sendo retornados. Exemplo:
❙◗▲❃
✷
✸
✹
s❡❧❡❝t
❢r♦♠
✇❤❡r❡
❛♥❞
✺
❛♥❞
✻
✴
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❆▲▲❊◆
❲❆❘❉
▼❆❘❚■◆
❚❯❘◆❊❘
❏❆▼❊❙
❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
❡♠♣✱ ❞❡♣t
❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❞❡♣t✳❧♦❝ ❂ ✬❈❍■❈❆●❖✬ ✲✲ s❡rá ♦ ♣❛râ♠❡tr♦ r❡❢❡r❡♥t❡
❛ ❧♦❝❛❧✐③❛çã♦
❡♠♣✳♠❣r
❂ ✬✼✻✾✽✬
✲✲ s❡rá ♦ ♣❛râ♠❡tr♦ r❡❢❡r❡♥t❡
❛♦ ❣❡r❡♥t❡
❏❖❇
✲✲✲✲✲✲✲✲✲
❙❆▲❊❙▼❆◆
❙❆▲❊❙▼❆◆
❙❆▲❊❙▼❆◆
❙❆▲❊❙▼❆◆
❈▲❊❘❑
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❙❆▲❊❙
❙❆▲❊❙
❙❆▲❊❙
❙❆▲❊❙
❙❆▲❊❙
Tendo montado todos os selects de que o programa necessita, vamos
para o próximo passo.
Segundo passo
Inicio a montagem da estrutura do programa PL/SQL.
Neste caso, analiso que tipo de objeto o programa pede. Geralmente, o
enunciado traz esta informação, por exemplo, “faça um bloco PL/SQL anônimo”, uma procedure, uma function, uma package etc. No nosso
14
Casa do Código
Capítulo 3. Primeiros passos
exemplo, ele não menciona. Como ele não pede para retornar informações,
apenas imprimir na tela, não criarei uma function, por exemplo. Como
também não menciona nada sobre programas armazenados, também não criarei uma procedure, muito menos uma package. Como também não
menciona disparos de triggers, não será preciso criar um. Vou criar um
bloco PL/SQL anônimo, mesmo porque, se for o caso, mais adiante eu posso
criar um cabeçalho para tornar este objeto um programa armazenado. É simples.
Começo desenhando o bloco PL/SQL, seguindo a seguinte estrutura:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
❞❡❝❧❛r❡
❜❡❣✐♥
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
❡♥❞❀
✴
Esta não é a estrutura mínima de um PL/SQL, pois sabemos que a área
de declaração de variáveis ( declare) e a área de tratamento de erros (
exception) não são obrigatórias, embora esta última seja imprescindível,
pois o tratamento de erros é fundamental para o bom funcionamento do sistema. Contudo, na grande maioria dos programas teremos esta estrutura:
a área de declaração de variáveis, a área onde ficarão a maioria dos comandos, propriamente ditos, ( begin- end), e a área de tratamento de erros (
exception).
Pronto. A estrutura inicial do seu programa PL/SQL está pronta para ser
utilizada. Dentro da área de declaração de variáveis, você vai colocar todas
as que você vai utilizar dentro do seu programa. Aqui também estarão declarados os tipos de dados definidos por você, os cursores, exceptions de
usuário, funções e procedimentos etc. Caso seu programa não vá utilizar esta
área, ela pode ser excluída.
Já dentro do corpo do programa, begin-end, é onde você vai escrever a
parte principal dele. É nele onde se localizam e serão executados os comandos
15
3.1. Como iniciar no PL/SQL
Casa do Código
da SQL, condições ifs, laços de repetição, aberturas de cursor, chamadas a
funções e outros procedimentos armazenados, e assim por diante.
A área de tratamento de erros é onde você vai tratar os possíveis problemas que poderão surgir durante a execução do seu programa. Quando estiver
escrevendo um programa PL/SQL sempre trate os possíveis erros. Pelo menos a exception others deve ser tratada, para que ao sinal de um problema,
o programa não aborte. Também é recomendada a utilização das funções
sqlerrm e sqlcode, para que o motivo do erro seja mencionado na mensagem.
Um programa PL/SQL sempre seguirá esta estrutura. Vale ressaltar também que podemos ver esta estrutura declare-BEGIN-exception-END, de forma
encadeada, ou seja, um bloco dentro de outro, como forma de isolar determinadas informações ou realizar verificações dentro do programa. Contudo, a
estrutura lógica é a mesma.
Segue o programa completo:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡ ❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✽
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶ ❜❡❣✐♥
✶✷
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽✱ ♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
✶✸
❧♦♦♣
✶✹
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✺
✲✲
✶✻
✐❢ ❝✶✪❢♦✉♥❞ t❤❡♥
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✶✽
❡❧s❡
✶✾
✲✲
✷✵
❡①✐t❀
16
Casa do Código
Capítulo 3. Primeiros passos
✷✶
❡♥❞ ✐❢❀
✷✷
❡♥❞ ❧♦♦♣❀
✷✸
✲✲
✷✹
❝❧♦s❡ ❝✶❀
✷✺ ❡①❝❡♣t✐♦♥
✷✻
✇❤❡♥ ♦t❤❡rs t❤❡♥
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠✮❀
✷✽ ❡♥❞❀
✷✾ ✴
◆♦♠❡✿ ❆▲▲❊◆ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆
◆♦♠❡✿ ❲❆❘❉ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆
◆♦♠❡✿ ▼❆❘❚■◆ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆
◆♦♠❡✿ ❚❯❘◆❊❘ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆
◆♦♠❡✿ ❏❆▼❊❙ ❈❛r❣♦✿ ❈▲❊❘❑
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Observação
Para garantir a impressão na tela, através do pacote dbms_output,
execute o seguinte comando no SQL*Plus: set serveroutput on.
17
Capítulo 4
Pacote dbms_output
Este pacote possui funções e procedimentos que permitem a geração de mensagens a partir de blocos anônimos de PL/SQL, procedures, packages
ou triggers. Ele utiliza-se de um buffer em memória para transferência
destas mensagens na sessão onde o programa está sendo executado. Quando
um programa envia mensagens através do pacote dbms_output, elas são
armazenadas na área de buffer e são apresentadas apenas ao término do programa.
Se estivermos utilizando a ferramenta SQL*Plus, pode-se habilitar este
recurso digitando o seguinte comando: set serveroutput on. Fazendo
isso, todas as mensagens passarão a ser visualizadas no prompt da ferramenta.
Na tabela a seguir, serão vistos os componentes mais usados deste pacote,
todos do tipo procedure.
• enable: habilita a chamada das demais rotinas do pacote.
Casa do Código
• disable: desabilita a chamada das demais rotinas do pacote.
• put: inclui uma informação na área de buffer.
• put_line: inclui uma informação na área de buffer e adiciona, simultaneamente, um caractere para quebra de linha (linha nova).
• get_line: recupera uma linha do buffer.
• get_lines: recupera várias linhas do buffer.
Agora, será abordado em detalhes, com scripts exemplos, como são utilizados estes componentes.
enable
Esta procedure habilita chamadas para put, put_line, new_line,
get_line e get_lines. Deve ser especificado um tamanho para a área do
buffer a ser usada, definido em bytes e podendo variar de 2.000 até 1.000.000.
Se isso for ultrapassado, uma mensagem de erro será mostrada.
❙◗▲❃ ❜❡❣✐♥
✷
❞❜♠s❴♦✉t♣✉t✳❡♥❛❜❧❡✭✷✵✵✵✮❀
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❚❊❙❚❊✬✮❀
✹ ❡♥❞❀
✺ ✴
❚❊❙❚❊
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
disable
Esta procedure desabilita as chamadas para put,
put_line,
new_line, get_line e get_lines e limpa o buffer. É muito útil na depuração de programas, quando for indesejado o surgimento de mensagens
informativas.
20
Casa do Código
Capítulo 4. Pacote dbms_output
❙◗▲❃ ❜❡❣✐♥
✷
❞❜♠s❴♦✉t♣✉t✳❞✐s❛❜❧❡❀
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❚❊❙❚❊✬✮❀
✹ ❡♥❞❀
✺ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note que a mensagem “TESTE” não apareceu na tela.
put
Esta procedure recebe um parâmetro cujo valor será armazenado na área
do buffer imediatamente após a última informação. Não é incluído qualquer
caractere indicativo de fim de linha ( enter). É bom lembrar que estes valores de saída são transformados em strings (caractere), portanto, se desejar
que eles tenham uma formatação diferente será preciso fazê-lo através do comando to_char ou to_number, por exemplo. Esta procedure por si só
não imprime na tela. Por isso, podemos utilizá-la juntamente com a procedure new_line. Neste exemplo, como forma de armazenamento no buffer,
utilizamos vários procedimentos put, um para cada letra. Veja o exemplo a
seguir.
❙◗▲❃ ❜❡❣✐♥
✷
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❚✬✮❀
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❊✬✮❀
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❙✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❚✬✮❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❊✬✮❀
✼
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✽ ❡♥❞❀
✾ ✴
❚❊❙❚❊
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
21
Casa do Código
put_line
Este procedimento envia o parâmetro informado para a área de buffer,
acrescentando, automaticamente, um caractere indicativo de fim de linha
após o texto enviado. Com isso, o resultado é impresso na tela, sem a necessidade da execução de qualquer outro procedimento. Note que em cada
execução do put_line o buffer é limpo.
❙◗▲❃ ❜❡❣✐♥
✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❚✬✮❀
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊✬✮❀
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❚✬✮❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊✬✮❀
✼ ❡♥❞❀
✽ ✴
❚
❊
❙
❚
❊
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
get_line
Este procedimento permite ler do buffer uma única linha de cada vez.
Ele possui dois parâmetros de saída onde o primeiro retornará o conteúdo da
linha ( line) e o segundo retornará seu status ( status). O status indica se
a linha foi recuperada seguindo os critérios: 1 indica que foi recuperada uma
linha do buffer;
❙◗▲❃ s❡t s❡r✈❡r♦✉t♣✉t ♦❢❢
❙◗▲❃ ❜❡❣✐♥
✷
❞❜♠s❴♦✉t♣✉t✳❡♥❛❜❧❡✭✷✵✵✵✮❀
✸
✲✲
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❈♦♠♦✬✮❀
22
Casa do Código
Capítulo 4. Pacote dbms_output
✺
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❛♣r❡♥❞❡r✬✮❀
✼
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬P▲❙◗▲❄✬✮❀
✾
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✶✵ ❡♥❞❀
✶✶ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ s❡t s❡r✈❡r♦✉t♣✉t ♦♥
❙◗▲❃ ❞❡❝❧❛r❡
✷
✈❛r✶
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✸
✈❛r✷
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✹
✈❛r✸
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✺
st❛t✉s ♥✉♠❜❡r
❞❡❢❛✉❧t ♥✉❧❧❀
✻ ❜❡❣✐♥
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳❣❡t❴❧✐♥❡✭✈❛r✶✱st❛t✉s✮❀
✾
❞❜♠s❴♦✉t♣✉t✳❣❡t❴❧✐♥❡✭✈❛r✷✱st❛t✉s✮❀
✶✵
❞❜♠s❴♦✉t♣✉t✳❣❡t❴❧✐♥❡✭✈❛r✸✱st❛t✉s✮❀
✶✶
✲✲
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬P❡r❣✉♥t❛✿ ✬⑤⑤✈❛r✶⑤⑤✬ ✬⑤⑤✈❛r✷⑤⑤✬
✬⑤⑤✈❛r✸✮❀
✶✸ ❡♥❞❀
✶✹ ✴
P❡r❣✉♥t❛✿ ❈♦♠♦ ❛♣r❡♥❞❡r P▲❙◗▲❄
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Primeiramente, configuramos a sessão para não mostrar as saídas dos comandos put e put_line, através do comando set serveroutput off.
Logo após, no primeiro bloco, habilitamos um buffer de 2000 bytes (linha 2).
Nas linhas 4 a 9, temos comandos put inserindo caracteres no buffer que
acabamos de habilitar. Estamos utilizando também o comando new_line
para que os caracteres sejam guardados em linhas diferentes.
23
Casa do Código
No segundo bloco, temos declaradas as variáveis var1, var2 e var3
(linha 2 a 4), que utilizaremos para atribuir os valores do buffer. Também
declaramos a variável status (linha 5), que será utilizada para completar
a chamada da procedure get_line. Nas linhas 8 a 10, temos as chamadas
à procedure get_line, que recuperam as linhas do buffer e atribuem os
valores às variáveis declaradas, anteriormente. Na linha 12, utilizamos o comando put_line para imprimir na tela o conteúdo das variáveis, ou seja, os
mesmos recuperados do buffer. Note que, para que a impressão em tela funcione, executamos o comando set serveroutput on, antes da execução
do segundo bloco.
get_lines
Este procedimento permite ler várias linhas do buffer utilizando um array de caracteres. Ele possui dois parâmetros, um de saída ( lines) e outro
de entrada e saída ( numlines). O primeiro parâmetro, lines, se trata
de uma tabela do tipo varchar2(255), podendo ser declarada com tipo
dbms_output.chararr. Já o parâmetro numlines serve tanto para informar a quantidade de linhas que se deseja recuperar, quanto para retornar
a quantidade de linhas que realmente foram retornadas após a execução da
procedure. Veja o exemplo a seguir.
❙◗▲❃
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡t s❡r✈❡r♦✉t♣✉t ♦❢❢
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳❡♥❛❜❧❡✭✷✵✵✵✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❈♦♠♦✬✮❀
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬❛♣r❡♥❞❡r✬✮❀
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
❞❜♠s❴♦✉t♣✉t✳♣✉t✭✬P▲❙◗▲❄✬✮❀
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
24
Casa do Código
Capítulo 4. Pacote dbms_output
❙◗▲❃ s❡t s❡r✈❡r♦✉t♣✉t ♦♥
❙◗▲❃ ❞❡❝❧❛r❡
✷
t❛❜
❞❜♠s❴♦✉t♣✉t✳❝❤❛r❛rr❀
✸
qt❧✐♥❡s ♥✉♠❜❡r
❞❡❢❛✉❧t ✸❀
✹
r❡s
✈❛r❝❤❛r✷✭✶✵✵✮
❞❡❢❛✉❧t ♥✉❧❧❀
✺ ❜❡❣✐♥
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳❣❡t❴❧✐♥❡s✭t❛❜✱qt❧✐♥❡s✮❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❘❡t♦r♥♦✉✿ ✬⑤⑤qt❧✐♥❡s⑤⑤✬ r❡❣✐str♦s✳✬✮❀
✶✵
✲✲
✶✶
❢♦r ✐ ✐♥ ✶✳✳qt❧✐♥❡s ❧♦♦♣
✶✷
r❡s ✿❂ r❡s⑤⑤✬ ✬⑤⑤t❛❜✭✐✮❀
✶✸
❡♥❞ ❧♦♦♣❀
✶✹
✲✲
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬P❡r❣✉♥t❛✿ ✬⑤⑤r❡s✮❀
✶✻
✲✲
✶✼ ❡♥❞❀
✶✽ ✴
❘❡t♦r♥♦✉✿ ✸ r❡❣✐str♦s✳
P❡r❣✉♥t❛✿ ❈♦♠♦ ❛♣r❡♥❞❡r P▲❙◗▲❄
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Muito parecido com o exemplo anterior, neste exemplo, a alteração foi
substituir as três variáveis var1, var2 e var3, pela variável tab, do tipo
array (linha 2). Também declaramos as variáveis qtlines e res (linhas
3 e 4), sendo que a primeira é usada para passar a quantidade de registros a
serem retornados (e consequentemente fazer o retorno) e a segunda apenas
para montar a string a ser impressa na tela. Na linha 7, temos a chamada à
procedure get_lines, que retorna os dados do buffer para dentro de nossa
variável tab. Já nas linhas 11 a 13, utilizamos uma estrutura loop, para ler
os dados da variável array e concatená-los na variável res. Observe que
utilizamos a variável qtlines (contendo a quantidade de linhas retornadas) para determinar o valor final da faixa para loop. Na linha 15, temos a
25
4.1. Exceções para o pacote dbms_output
Casa do Código
impressão do conteúdo de res.
4.1 Exceções para o pacote dbms_output
Existem duas exceções que podem ocorrer quando utilizamos o pacote
dbms_output. Seguem informações sobre elas e como tratá-las.
• ORU-10027 (Overflow de buffer). Solução: aumentar o tamanho do
buffer se possível. Caso contrário, encontrar um modo de gravar menos
dados.
• ORU-10028 (Overflow de comprimento de linha, limite de 255 caracteres por linha). Solução: verificar se todas as chamadas feitas a caracteres
por linha put e put_line têm menos de 255 caracteres por linha.
Neste capítulo falamos sobre o dbms_output e seus recursos. Durante o
todo o livro de PL/SQL vamos utilizar este pacote para gerar as saídas das informações para nossos exemplos. Desta forma, é muito importante conhecêlo e saber utilizá-lo.
26
Capítulo 5
Variáveis bind e de substituição
A ferramenta SQL*Plus permite o uso de variáveis com referências do tipo
bind e de substituição.
5.1 Variáveis bind
As variáveis bind são declaradas dentro do SQL*Plus e podem ser utilizadas
em todo seu ambiente, sendo em comandos SQL ou dentro de programas
PL/SQL. A declaração deste tipo de variável é muito semelhante à declaração
utilizada no PL/SQL, onde a nomeamos e definimos um tipo para ela. Contudo, não é necessária uma área específica para declaração, bastando apenas
declará-la no prompt do SQL*Plus. Veja o exemplo:
❙◗▲❃ ✈❛r✐❛❜❧❡ ♠❡♥s❛❣❡♠ ✈❛r❝❤❛r✷✭✷✵✵✮
❙◗▲❃
5.1. Variáveis bind
Casa do Código
Estamos declarando uma variável chamada mensagem do tipo
varchar2 com 200 posições. Depois de declarada, é só utilizá-la nos programas.
❙◗▲❃ ❜❡❣✐♥
✷
✿♠❡♥s❛❣❡♠ ✿❂ ✬❈✉rs♦ P▲❙◗▲✬❀
✸ ❡♥❞❀
✹ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note que estamos utilizando-a dentro de um bloco PL/SQL, onde atribuímos um valor para ela. Para recuperar ou atribuir um valor para uma variável
bind, em um programa PL/SQL ou comando SQL, é necessário referenciá-la
através da utilização do caractere dois pontos ( :), colocando-o antes do seu
nome. No entanto, quando a definimos ou quando forçamos a impressão do
seu valor em tela, não há a necessidade deste caractere especial.
Para visualizar o conteúdo de uma variável bind na tela do SQL*Plus, você
deve habilitar a impressão através do comando a seguir.
❙◗▲❃ s❡t ❛✉t♦♣r✐♥t ♦♥
❙◗▲❃
Após habilitar a impressão, o conteúdo da variável é impresso logo após
a execução do comando ou programa onde ela está sendo utilizada. Veja a
execução do exemplo anterior, agora com o autoprint ligado.
❙◗▲❃ ❜❡❣✐♥
✷
✿♠❡♥s❛❣❡♠ ✿❂ ✬❈✉rs♦ P▲❙◗▲✬❀
✸ ❡♥❞❀
✹ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
▼❊◆❙❆●❊▼
28
Casa do Código
Capítulo 5. Variáveis bind e de substituição
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❈✉rs♦ P▲❙◗▲
❙◗▲❃
Veja mais um exemplo, agora utilizando a variável no comando select.
❙◗▲❃ s❡❧❡❝t ✿♠❡♥s❛❣❡♠ ❢r♦♠ ❞✉❛❧❀
✿▼❊◆❙❆●❊▼
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❈✉rs♦ P▲❙◗▲
❙◗▲❃
Note que, como a variável já havia recebido um valor, quando executamos
o bloco PL/SQL, este valor ainda persiste em execuções posteriores.
Para alterar um valor de uma variável bind diretamente pelo SQL*Plus,
podemos utilizar o comando exec. Veja o exemplo a seguir, onde definimos
uma variável chamada gdepno, e logo após atribuímos o valor 10 a ela.
❙◗▲❃ ✈❛r✐❛❜❧❡ ❣❞❡♣♥♦ ♥✉♠❜❡r
❙◗▲❃
❙◗▲❃ ❡①❡❝ ✿❣❞❡♣♥♦ ✿❂ ✶✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❣❞❡♣♥♦
✲✲✲✲✲✲✲✲✲✲
✶✵
❙◗▲❃
Agora, selecionamos os empregados com base no código do departamento, vindo da variável bind gdepno.
❙◗▲❃ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿❣❞❡♣♥♦❀
29
5.1. Variáveis bind
Casa do Código
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃
Se quisermos visualizar o conteúdo de uma variável bind, utilizamos o
comando print. Veja o exemplo a seguir:
❙◗▲❃ ♣r✐♥t ❣❞❡♣♥♦❀
❣❞❡♣♥♦
✲✲✲✲✲✲✲✲✲✲
✶✵
❙◗▲❃
Uma variável bind tem sua vida útil com base na sessão do SQL*Plus.
Portanto, outras sessões não as enxergam, somente a que as criou. Quando o
SQL*Plus é fechado, automaticamente, elas são excluídas da memória.
A utilização de variáveis bind tem algumas restrições, por exemplo seu
uso na cláusula from, que não é permitido, e na substituição de palavras
reservadas.
Para ver todas as variáveis binds declaradas em uma sessão do SQL*Plus
utilize o comando var.
❙◗▲❃ ✈❛r
✈❛r✐á✈❡❧
✇❞♥❛♠❡
❚✐♣♦ ❞❡ ❞❛❞♦s ◆❯▼❇❊❘
✈❛r✐á✈❡❧
❣♥♦♠❡
❚✐♣♦ ❞❡ ❞❛❞♦s
✈❛r❈❍❆❘✷✭✶✵✵✮
❙◗▲❃
30
Casa do Código
5.2
Capítulo 5. Variáveis bind e de substituição
Variáveis de substituição
Outro tipo de variável de usuário é a variável de substituição. Este tipo também pode ser utilizado em comandos DML ou PL/SQL. Seu objetivo é substituir tal variável, dentro de comandos SQL ou PL/SQL, por um conjunto de
caracteres predefinidos ou definidos em tempo de execução. Ao contrário das
variáveis binds, as de substituição podem ser utilizadas também como forma
de completar comandos SQL, pois ela permite a utilização de palavras reservadas em seu teor. Veja a seguir como definir uma variável de substituição.
❙◗▲❃ ❞❡❢✐♥❡ ✇❡♠♣♥♦ ❂ ✼✸✻✾
❙◗▲❃
Para definir uma variável de substituição utilizamos o comando define
seguido de um nome para a variável. Neste exemplo, além de definir um
nome, atribuímos um valor para a variável através do operador de igualdade (
=). Note que para as variáveis de substituição não definimos um tipo, pois são
sempre do tipo alfanumérico. Veja um exemplo, utilizando a variável wempno
que acabamos de definir.
❙◗▲❃ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦❀
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✸✻✾
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❙◗▲❃
Note que, para utilizarmos a variável de substituição, colocamos na frente
de seu nome o &. Esta é a indicação de que estamos utilizando uma variável
de substituição. Veja um exemplo utilizando-a em PL/SQL.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ✐ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦✮ ❧♦♦♣
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✐✳❡♥❛♠❡✮❀
✹
❡♥❞ ❧♦♦♣❀
✺ ❡♥❞❀
31
Casa do Código
5.2. Variáveis de substituição
✻ ✴
❛♥t✐❣♦
♥♦✈♦
❙▼■❚❍
✷✿
✷✿
❢♦r ✐ ✐♥ ✭
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦✮ ❧♦♦♣
❢♦r ✐ ✐♥ ✭
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✸✻✾✮ ❧♦♦♣
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Para alterar um valor de uma variável de substituição também utilizamos
o comando define. Veja a seguir:
❙◗▲❃ ❞❡❢✐♥❡ ✇❡♠♣♥♦ ❂ ✶✵
❙◗▲❃
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ✐ ✐♥ ✭
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦✮ ❧♦♦♣
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✐✳❡♥❛♠❡✮❀
✹
❡♥❞ ❧♦♦♣❀
✺ ❡♥❞❀
✻ ✴
❛♥t✐❣♦ ✷✿
❢♦r ✐ ✐♥ ✭
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫✇❡♠♣♥♦✮ ❧♦♦♣
❢♦r ✐ ✐♥ ✭
♥♦✈♦ ✷✿
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✶✵✮ ❧♦♦♣
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Já para sabermos qual o valor corrente de uma variável de substituição,
utilizamos o comando define seguido do nome da variável.
❙◗▲❃ ❞❡❢✐♥❡ ✇❡♠♣♥♦
❞❡❢✐♥❡ ✇❡♠♣♥♦
❙◗▲❃
32
❂ ✧✶✵✧ ✭❈❍❆❘✮
Casa do Código
Capítulo 5. Variáveis bind e de substituição
Como mencionado anteriormente, as variáveis de substituição podem
também ser utilizadas para substituição de palavras reservadas, ou seja, podemos não só substituir tal variável por um valor alfanumérico, como também
por uma sentença SQL, como uma clausula where ou order by. Veja o
exemplo:
❙◗▲❃ ❞❡❢✐♥❡ ❣❢r♦♠ ❂ ✬❢r♦♠ ❡♠♣✬
❙◗▲❃ ❞❡❢✐♥❡ ❣✇❤❡r❡ ❂ ✬✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✸✻✾✬
❙◗▲❃ ❞❡❢✐♥❡ ❣♦r❞❡r❜② ❂ ✬♦r❞❡r ❜② ✶✬
❙◗▲❃
❙◗▲❃ s❡❧❡❝t ❡♥❛♠❡ ✫❣❢r♦♠ ✫❣✇❤❡r❡ ✫❣♦r❞❡r❜②❀
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ✫❣❢r♦♠ ✫❣✇❤❡r❡ ✫❣♦r❞❡r❜②
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✸✻✾ ♦r❞❡r ❜② ✶
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❙◗▲❃
Isso também funciona para PL/SQL.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ✐ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡ ✫❣❢r♦♠ ✫❣✇❤❡r❡ ✫❣♦r❞❡r❜②✮ ❧♦♦♣
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✐✳❡♥❛♠❡✮❀
✹
❡♥❞ ❧♦♦♣❀
✺ ❡♥❞❀
✻ ✴
❛♥t✐❣♦ ✷✿
❢♦r ✐ ✐♥ ✭
s❡❧❡❝t ❡♥❛♠❡ ✫❣❢r♦♠ ✫❣✇❤❡r❡ ✫❣♦r❞❡r❜②✮ ❧♦♦♣
❢♦r ✐ ✐♥ ✭
♥♦✈♦ ✷✿
s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡
❡♠♣♥♦ ❂ ✼✸✻✾ ♦r❞❡r ❜② ✶✮ ❧♦♦♣
❙▼■❚❍
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
33
5.2. Variáveis de substituição
Casa do Código
A vida útil de uma variável de substituição também será limitada pela
sessão do SQL*Plus. Enquanto a sessão estiver ativa, ela existirá. Outras sessões não podem vê-la, como também acontece com as variáveis do tipo bind.
Uma variável de substituição pode ter sua definição excluída. Para tal ação,
podemos utilizar o comando undefine. Veja o exemplo.
❙◗▲❃ ✉♥❞❡❢✐♥❡ ❣❢r♦♠
❙◗▲❃
Ao contrário de uma variável bind, uma variável de substituição não necessita ser obrigatoriamente definida ou declarada. Podemos simplesmente
informá-la em nosso comando SQL ou PL/SQL, e deixar que o motor do
SQL*Plus solicite o valor para ela, sem que seja necessária uma definição prévia. Observe o exemplo a seguir:
❙◗▲❃ s❡❧❡❝t ❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫❝♦❞✐❣♦❀
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ ❝♦❞✐❣♦✿ ✼✾✵✷
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫❝♦❞✐❣♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✾✵✷
❏❖❇
✲✲✲✲✲✲✲✲✲
❆◆❆▲❨❙❚
❙◗▲❃ ❞❡❢✐♥❡
❞❡❢✐♥❡ ❴❈❖◆◆❊❈❚❴■❉❊◆❚■❋■❊❘ ❂ ✧①❡✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❙◗▲P▲❯❙❴❘❊▲❊❆❙❊ ❂ ✧✾✵✷✵✵✵✶✵✵✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❊❉■❚❖❘
❂ ✧◆♦t❡♣❛❞✧ ✭❈❍❆❘✮
❂ ✧❖r❛❝❧❡ ❉❛t❛❜❛s❡ ✶✵❣ ❊①♣r❡ss ❊❞✐t✐♦♥
❞❡❢✐♥❡ ❴❖❴❱❊❘❙■❖◆
❘❡❧❡❛s❡ ✶✵✳✷✳✵✳✶✳✵ ✲ Pr♦❞✉❝t✐♦♥✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❖❴❘❊▲❊❆❙❊
❂ ✧✶✵✵✷✵✵✵✶✵✵✧ ✭❈❍❆❘✮
❂ ✧✶✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ✶
❞❡❢✐♥❡ ❴❘❈
❂ ✧✶✧ ✭❈❍❆❘✮
❂ ✧✶✶✶✶✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ✇❡♠♣♥♦
❞❡❢✐♥❡ ●✇❤❡r❡
❂ ✧✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✸✻✾✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ●❖❘❉❊❘❇❨
❂ ✧♦r❞❡r ❜② ✶✧ ✭❈❍❆❘✮
❙◗▲❃
34
Casa do Código
Capítulo 5. Variáveis bind e de substituição
Veja que utilizamos uma variável como substituição, chamada codigo.
Vale ressaltar que não a definimos em nenhum momento. Mesmo assim, o
SQL*Plus a reconheceu como uma variável, pois utilizamos o & na frente
do seu nome, e solicitou um valor para ela. Desta forma, se não tivermos a
variável de substituição já definida, o SQL*Plus vai solicitar um valor. Note
também que após a sua utilização o SQL*Plus não a deixa definida, ou seja,
isso ocorre apenas em tempo de execução. Em PL/SQL também podemos
utilizá-la desta forma.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❥♦❜ ❡♠♣✳❥♦❜✪t②♣❡❀
✸ ❜❡❣✐♥
✹
s❡❧❡❝t ❥♦❜ ✐♥t♦ ✇❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫❝♦❞❴❡♠♣❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇❥♦❜✮❀
✼ ❡♥❞❀
✽ ✴
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ ❝♦❞❴❡♠♣✿ ✼✾✵✷
❛♥t✐❣♦ ✹✿ s❡❧❡❝t ❥♦❜ ✐♥t♦ ✇❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✫❝♦❞❴❡♠♣❀
♥♦✈♦ ✹✿ s❡❧❡❝t ❥♦❜ ✐♥t♦ ✇❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✾✵✷❀
❆◆❆▲❨❙❚
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
5.3
Utilizando variáveis em arquivos
Também podemos utilizar variáveis binds ou de substituição dentro de arquivos e depois executá-los via SQL*Plus. Nesses casos, se forem encontradas
variáveis do tipo bind ou de substituição, o SQL*Plus vai fazer o preenchimento dos valores correspondentes.
Nos casos de variáveis bind, o SQL*Plus não solicitará os valores, pois eles
já devem estar definidos. No caso de variáveis de substituição, vai depender
se já se encontram ou não definidas na sessão. Veja os exemplos:
A seguir estamos criando um arquivo de script chamado S_EMP.sql
contendo o comando para retornar os empregados com base em um depar35
5.3. Utilizando variáveis em arquivos
Casa do Código
tamento informado via uma variável bind.
❙◗▲❃ s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿❜❞❡♣t♥♦
✷
❙◗▲❃ s❛✈❡ ❇❴❊▼P✳sq❧
❈r✐❛❞♦ ❛rq✉✐✈♦ ❇❴❊▼P✳sq❧
❙◗▲❃
❙◗▲❃ ❣❡t ❇❴❊▼P✳sq❧
✶✯ s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿❜❞❡♣t♥♦
❙◗▲❃
Definindo a variável bind dentro da sessão do SQL*Plus:
❙◗▲❃ ✈❛r ❜❞❡♣t♥♦ ♥✉♠❜❡r
❙◗▲❃
Definindo um valor para a variável bind bdeptno:
❙◗▲❃ ❡①❡❝ ✿❜❞❡♣t♥♦ ✿❂ ✶✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ ♣r✐♥t ❜❞❡♣t♥♦
❇❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
❙◗▲❃
Executando o arquivo S_EMP.sql:
❙◗▲❃ ❅❇❴❊▼P✳sq❧
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃
36
❏❖❇
✲✲✲✲✲✲✲✲✲
▼❆◆❆●❊❘
P❘❊❙■❉❊◆❚
❈▲❊❘❑
Casa do Código
Capítulo 5. Variáveis bind e de substituição
Agora vamos ver outro exemplo utilizando variáveis de substituição:
❙◗▲❃ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫s❞❡♣t♥♦
✷
❙◗▲❃ s❛✈❡ ❙❴❊▼P✳sq❧
❈r✐❛❞♦ ❛rq✉✐✈♦ ❙❴❊▼P✳sq❧
❙◗▲❃
❙◗▲❃
No caso das variáveis de substituição, conforme já mencionado, mesmo
não as definindo, o SQL*Plus faz a solicitação de valores. Vamos testar.
❙◗▲❃ ❅❙❴❊▼P✳sq❧
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ s❞❡♣t♥♦✿ ✷✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫s❞❡♣t♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❙◗▲❃
Note que o SQL*Plus solicitou o valor através da linha “Informe o valor
para sdeptno:”. Neste caso, foi informado o valor 20. Contudo, como a
variável não está definida, sempre que executamos este script o programa vai
solicitar um valor.
Para que ele não fique solicitando um valor sempre o que script for executado, definimos a variável através do comando define. Com isso, o
SQL*Plus não pedirá mais o valor. Veja o exemplo:
❙◗▲❃ ❞❡❢✐♥❡ s❞❡♣t♥♦ ❂ ✶✵
❙◗▲❃ ❅❙❴❊▼P✳sq❧
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫s❞❡♣t♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
37
5.3. Utilizando variáveis em arquivos
Casa do Código
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃
Repare que agora ele não pede mais o valor, apenas faz a substituição da
variável com base no valor guardado na sessão do SQL*Plus. Se excluirmos a
definição da variável, ele volta a solicitar o valor.
❙◗▲❃ ✉♥❞❡❢✐♥❡ s❞❡♣t♥♦
❙◗▲❃ ❅❙❴❊▼P✳sq❧
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ s❞❡♣t♥♦✿ ✷✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫s❞❡♣t♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❙◗▲❃
Outra forma de definir uma variável de substituição é utilizando && (duplo) em vez de um só &. Isso faz com que o SQL*Plus crie a definição da
variável:
❙◗▲❃ ❡❞✐t ❙❴❊▼P✳sq❧
❙◗▲❃ ❣❡t ❙❴❊▼P✳sq❧
✶✯ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✫s❞❡♣t♥♦
❙◗▲❃
❙◗▲❃ ❅❙❴❊▼P✳sq❧
38
Casa do Código
Capítulo 5. Variáveis bind e de substituição
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ s❞❡♣t♥♦✿ ✶✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✫s❞❡♣t♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃ ❅❙❴❊▼P✳sq❧
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✫s❞❡♣t♥♦
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃
Veja que editamos o arquivo S_EMP e acrescentamos mais um & ao já
existente. Depois, salvamos o arquivo. Ao executá-lo, o SQL*Plus detectou os
&&, contudo, como a variável não continha nenhum valor inicial definido, ele
solicitou um valor. Já na segunda vez que executamos o arquivo, o SQL*Plus
já não o solicitou. Se executarmos o comando define para ver as variáveis
de substituição definidas na sessão, veremos que o SQL*Plus definiu automaticamente a nossa variável SDEPTNO.
❙◗▲❃ ❞❡❢✐♥❡
❞❡❢✐♥❡ ❴❈❖◆◆❊❈❚❴■❉❊◆❚■❋■❊❘ ❂ ✧①❡✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❙◗▲P▲❯❙❴❘❊▲❊❆❙❊ ❂ ✧✾✵✷✵✵✵✶✵✵✧ ✭❈❍❆❘✮
❂ ✧◆♦t❡♣❛❞✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❊❉■❚❖❘
❞❡❢✐♥❡ ❴❖❴❱❊❘❙■❖◆
❂ ✧❖r❛❝❧❡ ❉❛t❛❜❛s❡ ✶✵❣ ❊①♣r❡ss ❊❞✐t✐♦♥
❘❡❧❡❛s❡ ✶✵✳✷✳✵✳✶✳✵ ✲ Pr♦❞✉❝t✐♦♥✧ ✭❈❍❆❘✮
❂ ✧✶✵✵✷✵✵✵✶✵✵✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ❴❖❴❘❊▲❊❆❙❊
❞❡❢✐♥❡ ❴❘❈
❂ ✧✶✧ ✭❈❍❆❘✮
❞❡❢✐♥❡ ✶
❂ ✧✸✵✧ ✭❈❍❆❘✮
39
Casa do Código
5.3. Utilizando variáveis em arquivos
❞❡❢✐♥❡ ❙❉❊P❚◆❖
❙◗▲❃
❂ ✧✶✵✧ ✭❈❍❆❘✮
Outro recurso que pode ser utilizado é a passagem de valores para as variáveis de substituição quando executamos um arquivo. Este recurso está habilitado somente para as variáveis deste tipo. Neste caso, devemos utilizar
indexadores numéricos juntamente com o &, como por exemplo, &1, &2 etc.
nos comandos dentro do arquivo. Caso contrário, o SQL*Plus vai ignorar este
valores, solicitando a entrada deles assim que for executado o arquivo. Veja o
exemplo a seguir:
❙◗▲❃ ❡❞✐t ❙❴❊▼P✳sq❧
❙◗▲❃ ❣❡t ❙❴❊▼P✳sq❧
✶✯ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✶
❙◗▲❃
Editamos o arquivo S_EMP.sql modificando o nome da variável de
substituição de sdeptno para 1. Agora vamos executar o arquivo passando
um valor como parâmetro na chamada da execução.
❙◗▲❃ ❅❙❴❊▼P✳sq❧ ✶✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✶
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃
Veja que o valor 10 informado na chamada da execução do arquivo foi
passado para dentro dele, substituindo a variável &1. Com o uso de indexadores, o SQL*Plus define automaticamente a variável na sessão, e com isso,
nas próximas execuções, não necessitamos informar o valor caso ele não seja
diferente da execução anterior. Para trocar o valor da variável, basta informar
um novo valor na chamada.
40
Casa do Código
Capítulo 5. Variáveis bind e de substituição
❙◗▲❃ ❅❙❴❊▼P✳sq❧
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✶
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❈▲❆❘❑
❑■◆●
▼■▲▲❊❘
❙◗▲❃ ❅❙❴❊▼P✳sq❧ ✷✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫✶
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❙◗▲❃
Note que, na primeira execução, apenas chamamos o arquivo sem a passagem de um valor. Como anteriormente já havíamos executado o arquivo
passando o valor 10, ele assumiu este valor para as demais execuções. Na segunda execução, informamos um valor diferente, 20, fazendo com que ele seja
passado como parâmetro a partir de então.
Outro comando que é utilizado para definir uma variável de substituição
é o accept. A diferença dele para define é que podemos formatar uma
mensagem para ser mostrada ao usuário no momento de solicitar a entrada
de um valor. Sua utilização é muito interessante quando estamos executando
scripts via arquivo. Veja o exemplo.
❙◗▲❃ ❡❞✐t ❙❴❊▼P✳sq❧
❙◗▲❃ ❣❡t ❙❴❊▼P✳sq❧
41
5.3. Utilizando variáveis em arquivos
Casa do Código
✶ ❛❝❝❡♣t ❙❉❊P❚◆❖ ♥✉♠❜❡r ❢♦r ✾✾✾ ❞❡❢❛✉❧t ✷✵ ♣r♦♠♣t ✧■♥❢♦r♠❡ ♦
❞❡♣t♥♦✿ ✧
✷✯ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫❙❉❊P❚◆❖
❙◗▲❃
❙◗▲❃ ❅❙❴❊▼P✳sq❧
■♥❢♦r♠❡ ♦ ❞❡♣t♥♦✿ ✷✵
❛♥t✐❣♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✫❙❉❊P❚◆❖
✷✵
♥♦✈♦ ✶✿ s❡❧❡❝t ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❙◗▲❃
Em primeiro lugar, alteramos o arquivo S_EMP acrescentando a linha
referente ao accept, que deve vir antes do comando SQL ao qual se quer
associar a mensagem e a variável. Neste nosso exemplo, o comando está antes
do select. Logo após o comando accept, informamos o nome para variável, seguido pelo tipo do dado. Escolhemos uma variável do tipo number
que vai se chamar SDEPTNO. Logo após o tipo da variável, podemos informar
também a máscara utilizando o comando for seguido do formato. No exemplo, colocamos o formato como 999 (máximo de 3 casas). Também definimos
o valor 20 como padrão, através da expressão default, ou seja, a variável já
será inicializada com este valor. E agora vem o suprassumo do recurso. Através do comando prompt, definimos uma mensagem para ser mostrada para
o usuário no momento da solicitação dos valores. Esta mensagem deve ser
informada sempre logo após o comando. Por fim, executamos o arquivo.
42
Capítulo 6
Aspectos iniciais da programação
PL/SQL
Como em qualquer linguagem de programação, em PL/SQL também há regras que devem ser seguidas na hora de codificar programas. Cada linguagem
de programação trabalha de uma forma, contudo certos conceitos prevalecem
entre todas.
Aspectos relacionados ao desenvolvimento, como áreas predefinidas para
declarações de variáveis, tratamentos de erros ou comentários em programas,
por exemplo, são comuns em todas as linguagens. O que difere entre elas é a
forma como cada uma trata estes aspectos.
Para programar em PL/SQL, você deve conhecer sua sintaxe e os elementos que podem ser utilizados na codificação dos programas. Veja agora alguns
pontos importantes para você iniciar na escrita de códigos nesta linguagem.
6.1. Caracteres e operadores
6.1
Casa do Código
Caracteres e operadores
Dentro da linguagem você pode utilizar caracteres e operadores para auxiliar
na codificação. São eles:
• Caracteres: A a Z (maiúsculos e minúsculos), números de 0 a 9 e os
caracteres especiais: ( ) + - * / < > = ! ; : . ’ @ % , "$ & _ \{ } [ ] | #
• Operadores Relacionais: <, >, =, !=, >=, <=, IS NULL, IS NOT NULL
• Operadores Lógicos: AND, OR e NOT
6.2
Identificadores
Para nomear identificadores em PL/SQL, por exemplo, variáveis, constantes
ou qualquer objeto, nós devemos seguir algumas regras. São elas:
• A quantidade de caracteres para nomear um identificador é de no máximo 30.
• Não podemos utilizar palavras reservadas como begin, if, loop, end etc.
• Para nomear os identificadores, podemos utilizar letras, números e alguns caracteres especiais, mas nem todos.
• Obrigatoriamente, o primeiro caractere em um nome de identificador
deve ser uma letra.
Escopo de identificadores
O escopo de um identificador está limitado ao bloco onde foi declarado.
Podemos ter vários blocos encadeados. Logo, cada bloco pode ter sua própria área de declaração de identificadores. Neste caso, um identificador, por
exemplo, uma variável, declarada em um bloco mais interno, não poderá ser
acessada em um bloco mais externo. Veja o exemplo a seguir.
❙◗▲❃
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ❢♦❧❤❛❴♣❛❣❛♠❡♥t♦✭♣qt❴❞✐❛s ♥✉♠❜❡r✮ ✐s
44
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
✷
✲✲
✸
✇qt❴❞✐❛s
♥✉♠❜❡r❀
✹
✇✈❧❴❜r✉t♦
♥✉♠❜❡r❀
✺
✇✈❧❴✐r
♥✉♠❜❡r❀
✻
✇✈❧❴❧✐q✉✐❞♦ ♥✉♠❜❡r❀
✼
✲✲
✽ ❜❡❣✐♥
✾
✇✈❧❴❜r✉t♦
✿❂ ✭♣qt❴❞✐❛s ✯ ✷✺✮❀
✶✵
✲✲
✶✶
❞❡❝❧❛r❡
✶✷
✇t①❴✐r ♥✉♠❜❡r❀
✶✸
❜❡❣✐♥
✶✹
✐❢ ✇✈❧❴❜r✉t♦ ❃ ✺✹✵✵ t❤❡♥
✶✺
✲✲
✶✻
✇t①❴✐r ✿❂ ✷✼❀
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❚❛①❛ ■❘✿ ✬⑤⑤✇t①❴✐r✮❀
✶✽
✲✲
✶✾
❡❧s❡
✷✵
✲✲
✷✶
✇t①❴✐r ✿❂ ✽❀
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❚❛①❛ ■❘✿ ✬⑤⑤✇t①❴✐r✮❀
✷✸
✲✲
✷✹
❡♥❞ ✐❢❀
✷✺
✲✲
✷✻
✇✈❧❴✐r
✿❂ ✭✇✈❧❴❜r✉t♦ ✯ ✇t①❴✐r✮ ✴ ✶✵✵❀
✷✼
✲✲
✷✽
✇✈❧❴❧✐q✉✐❞♦ ✿❂ ✭✇✈❧❴❜r✉t♦ ✲ ✇✈❧❴✐r✮❀
✷✾
✲✲
✸✵
❡♥❞❀
✸✶
✲✲
✸✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❱❛❧♦r ❞♦ s❛❧❛r✐♦ ❜r✉t♦✿ ✬⑤⑤✇✈❧❴❜r✉t♦✮❀
✸✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡s❝♦♥t♦ ❞♦ ✈❛❧♦r ❞♦ ■❘✿ ✬⑤⑤✇✈❧❴✐r✮❀
✸✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❱❛❧♦r ❞♦ s❛❧❛r✐♦ ❧✐q✉✐❞♦✿ ✬⑤⑤✇✈❧❴❧✐q✉✐❞♦✮❀
✸✺
✲✲
✸✻ ❡①❝❡♣t✐♦♥
✸✼
✇❤❡♥ ♦t❤❡rs t❤❡♥
45
6.2. Identificadores
Casa do Código
✸✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ❝❛❧❝✉❧❛r ♣❛❣❛♠❡♥t♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠✮❀
✸✾ ❡♥❞ ❢♦❧❤❛❴♣❛❣❛♠❡♥t♦❀
✹✵ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Nesse exemplo, temos um programa que calcula o valor a ser pago a um
empregado, mediante a quantidade de horas passada por parâmetro a um
procedimento. Uma das premissas para calcular o valor líquido a ser pago
é o cálculo do imposto de renda (IR). Se analisarmos o programa, é possível
identificar dois blocos. Um principal e outro mais interno. O bloco interno
é utilizado para o cálculo do IR. Note que nele criamos uma segunda área de
declaração de variáveis que é específica deste bloco. Ali declaramos a variável
wtx_ir que receberá a taxa para o cálculo do imposto mediante uma condição. A partir da obtenção da taxa, é calculado o valor do imposto e também
o valor líquido a ser pago.
Observações importantes: o escopo da variável wtx_ir está limitado ao
bloco em que ela foi declarada. Caso a usássemos fora deste escopo, o Oracle geraria um erro indicando que ela não foi declarada. Em contrapartida,
podemos observar que as variáveis wvl_ir e wvl_liquido estão sendo
utilizadas dentro do bloco mais interno, sem que nenhum erro aconteça. Isso
é possível devido ao fato de elas terem sido declaradas em um bloco mais
externo. Logo, seus escopos abrangem todo o bloco onde foram declaradas,
inclusive, blocos internos contidos neste. Segue o resultado.
❙◗▲❃ ❜❡❣✐♥ ❢♦❧❤❛❴♣❛❣❛♠❡♥t♦✭♣qt❴❞✐❛s ❂❃ ✸✵✵✮❀ ❡♥❞❀
✷ ✴
❚❛①❛ ■❘✿ ✷✼
❱❛❧♦r ❞♦ s❛❧❛r✐♦ ❜r✉t♦✿ ✼✺✵✵
❉❡s❝♦♥t♦ ❞♦ ✈❛❧♦r ❞♦ ■❘✿ ✷✵✷✺
❱❛❧♦r ❞♦ s❛❧❛r✐♦ ❧✐q✉✐❞♦✿ ✺✹✼✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
46
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
❙◗▲❃
6.3
Transações
Primeiramente, antes de começarmos a trabalhar com PL/SQL, é preciso conhecer o conceito de transação. Uma das características mais bem-vindas dos
bancos de dados Cliente/Servidor, em relação aos bancos de dados desktop,
é o conceito de transações. Uma transação é uma unidade lógica de trabalho composta por uma ou mais declarações da Data Manipulation Language
(DML) ou Data Definition Language (DDL). Os comandos para o controle da
transação são aqueles necessários para que se possa controlar a efetivação ou
não das modificações feitas no banco de dados.
Para explicar o que é uma transação, pode-se tomar como exemplo uma
transferência bancária onde um determinado valor é transferido de uma
conta para outra. O processo de transferência deste valor consiste em vários
passos, que são agrupados de modo que, se não forem concluídos em sua totalidade, ou seja, se a transação não chegar até o final, todas as outras alterações
já realizadas serão descartadas e a conta voltará ao seu estado anterior, como
se nenhuma transferência tivesse sido realizada. Através deste controle, podese garantir que os dados permanecerão consistentes. Os comandos commit
e rollback da DCL auxiliam neste trabalho.
Commit
Tornam permanentes todas as alterações feitas no banco de dados durante
a sessão. Todas as alterações realizadas em uma determinada transação serão
confirmadas caso este comando seja aplicado.
47
6.3. Transações
Casa do Código
Fig. 6.1: Confirmando as alterações no banco de dados
Rollback
Usado para desfazer todas as alterações feitas desde o último commit durante a sessão. Esse comando vai restaurar os dados ao lugar onde eles estavam
no último commit. Alterações serão desfeitas caso a transação seja encerrada
pelo comando rollback.
48
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
Fig. 6.2: Desfazendo as alterações no banco de dados
No Oracle, uma transação se inicia com a execução da primeira instrução
SQL e termina quando as alterações são salvas ou descartadas. O comando
set transaction também inicia uma transação – transação explícita. O
uso do comando set transaction determina algumas regras, as quais são
listadas a seguir.
49
6.3. Transações
Casa do Código
• Deve ser o primeiro comando da transação (caso contrário, ocorrerá
um erro);
• Somente consultas são permitidas na transação;
• Um commit, rollback ou qualquer outro comando de DDL
(possuem commits implícitos) encerram o efeito do comando set
transaction.
Fig. 6.3: Abrindo uma nova transação dentro do SQL*Plus
Nota: A figura mostra um comando DML sendo executado e, logo após,
uma transação sendo aberta. Como uma das regras para se abrir uma transação é que ela seja um dos primeiros comandos da transação, o erro acontece quando executamos o comando. Note que após encerrarmos a transação
(através do rollback) aberta pelo comando DML, nós conseguimos executar o comando e abrir uma nova transação.
50
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
6.4 Transações em PL/SQL
As transações em PL/SQL seguem os mesmo preceitos expostos anteriormente. Um ponto a acrescentar é o uso dos savepoints. Quando trabalhamos com PL/SQL temos este recurso que nos permite definir pontos
de salvamento dentro do programa. Todavia, não é uma prática muito utilizada, principalmente pelo fato de geralmente trabalharmos com grandes volumes de código, pois pode dificultar o entendimento do programa e inclusive
desestruturá-lo logicamente. É sempre bom ter muito cuidado quanto à efetivação de dados no momento de construirmos nossos programas. Devemos
visar sempre à consistência e integridade das informações manipuladas a fim
de atingirmos o objetivo esperado. Além de permitir que sejam salvas partes
de ações em determinados pontos do programa, também é possível desfazer
tais ações usando estes mesmos pontos de salvamento.
Veja um exemplo simples do uso deste recurso.
❙◗▲❃ ❜❡❣✐♥
✷
✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✹✶✱ ✬●❊◆❊❘❆▲ ▲❊❉●❊❘✬✱ ✬✬✮❀
✸
s❛✈❡♣♦✐♥t ♣♦♥t♦❴✉♠❀
✹
✲✲
✺
✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✹✷✱ ✬P❯❘❈❍❆❙■◆●✬✱ ✬✬✮❀
✻
s❛✈❡♣♦✐♥t ♣♦♥t♦❴❞♦✐s❀
✼
✲✲
✽
✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✹✸✱ ✬❘❊❈❊■❱❆❇▲❊❙✬✱ ✬✬✮❀
✾
s❛✈❡♣♦✐♥t ♣♦♥t♦❴tr❡s❀
✶✵
✲✲
✶✶
✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✹✹✱ ✬P❆❨❆❇▲❊❙✬✱ ✬✬✮❀
✶✷
r♦❧❧❜❛❝❦ t♦ s❛✈❡♣♦✐♥t ♣♦♥t♦❴❞♦✐s❀
✶✸
✲✲
✶✹
❝♦♠♠✐t❀
✶✺ ❡♥❞❀
✶✻ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo temos vários pontos de salvamento identificados por
51
6.5. Trabalhando com variáveis e constantes
Casa do Código
ponto_um, ponto_dois e ponto_tres. Cada ponto está referenciando
um comando insert. Logo após, temos um rollback to savepoint
desfazendo todas as operações a partir do ponto_dois. Isso indica que os
comandos referentes às linhas 2 e 5 permanecem intactos. Já os comandos
referentes às linhas 8 e 11 serão descartados.
6.5 Trabalhando com variáveis e constantes
Identificadores de variáveis e constantes são muito comuns em programas
PL/SQL, pois toda a informação geralmente é manipulada dentro deles e na
maioria das vezes precisamos armazená-la em memória antes de, por exemplo, inseri-la em uma tabela, enviar para uma impressora ou para exportá-la
para algum outro sistema.
Dessa forma, variáveis e constantes nada mais são que áreas em memória
definidas e usadas dentro de programa que servem para guardar informações
em tempo de execução. Como o nome sugere, uma variável pode ter seus
valores atualizados várias vezes ao longo da execução de um programa. Contudo, uma constante nasce com um valor definido e o mantém até o término
da sua utilização.
Uma variável ou constante deve ter um tipo definido, que não se altera
ao longo da execução de um programa. Ao declará-las, recebem um nome
que será sua identificação. Por regra, dentro do Oracle, este nome não pode
ultrapassar 30 caracteres. No mais, ela deve obedecer às regras de definição
mencionadas anteriormente quando falamos de identificadores. Esta definição deve ser feita dentro de uma área específica de declarações de variáveis
que cada bloco PL/SQL pode ter, identificada como declare.
O escopo de uma variável ou constante se limita ao bloco em que foram
declaradas, podendo sempre ser acessadas no seu bloco e em blocos mais internos, nunca em blocos externos à sua declaração. Entretanto, caso uma variável tenha sido declarada duas vezes (mesmo nome), uma em um bloco externo e outra em um bloco mais interno, a variável do bloco externo não poderá ser acessada dentro do interno, pois haveria um conflito. Todavia, pelas
boas práticas de programação não devemos ter identificadores com o mesmo
nome. Logo, casos como este não são comuns.
52
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
Além dos tipos predefinidos, como numérico, data, string, entre outros,
as variáveis e constantes podem referenciar tipos de dados de determinadas
colunas de uma tabela criada em um banco de dados ( %TYPE), ou seu tipo
pode referenciar uma tabela inteira ( %ROWTYPE). Quando declaramos uma
variável podemos definir um valor padrão, chamado de DEFAULT, para que
ela já inicialize assim. Para as constantes, isso é obrigatório.
No mais, os valores de variáveis e constantes podem ser manipulados e
convertidos para outros tipos a fim de serem utilizados dentro dos programas para satisfazer objetivos específicos. Seguem exemplos de declarações de
variáveis.
❉❊❈▲❆❘❊
❉❚❴❊◆❚❘❆❉❆
❉❚❴❙❆■❉❆
❋❖❘◆❊❈❊❉❖❘
❉❆❚❊
❉❊❋❆❯▲❚ ❙❨❙❉❆❚❊❀
❉❆❚❊❀
❚■P❖❴P❊❙❙❖❆❀ ✲✲ ❚✐♣♦ ❞❡ ❞❛❞♦ ❞❡❢✐♥✐❞♦ ♣❡❧♦
❞❡s❡♥✈♦❧✈❡❞♦r
◆❯▼❇❊❘✭✺✮ ❉❊❋❆❯▲❚
✶✵✵✵❀
◗❚❴▼❆❳
◗❚❴▼■◆
❈❖◆❙❚❆◆❚ ◆❯▼❇❊❘✭✺✵✮ ❉❊❋❆❯▲❚
✶✵✵❀
◆▼❴P❊❙❙❖❆
❈❍❆❘✭✻✵✮❀
◆❯▼❇❊❘✭✶✶✱✷✮❀
❱▲❴❙❆▲❆❘■❖
❈❉❴❉❊P❚❖
◆❯▼❇❊❘✭✺✮❀
■◆❴◆❆❖
❈❖◆❙❚❆◆❚ ❇❖❖▲❊❆◆ ❉❊❋❆❯▲❚ ❋❆▲❙❊❀
◆❯▼❇❊❘✭✶✵✮ ✿❂ ✵❀
◗❚❉
❱▲❴P❊❘❈
❈❖◆❙❚❆◆❚ ◆❯▼❇❊❘✭✹✱✷✮ ✿❂ ✺✺✳✵✵❀
❈❉❴❈❆❘●❖
❊▼P▲❖❨❊❊✳❏❖❇✪❚❨P❊❀
❘❊●❴❉❊P❚
❉❊P❆❘❚▼❊◆❚✪❘❖❲❚❨P❊❀
6.6 Tipos de dados em PL/SQL
VARCHAR2
Tamanho máximo para campos de tabela: 4.000 bytes. Tamanho máximo
para PL/SQL: 32.767 bytes. O VARCHAR2 é variável e somente usa o espaço
que está ocupado. Diferentemente do CHAR.
VARCHAR é um subtipo (assim como STRING) que existe por questões
de compatibilidade com outras marcas de banco de dados e também com
o padrão SQL. Entretanto, a Oracle no momento não recomenda o uso do
53
6.6. Tipos de dados em PL/SQL
Casa do Código
tipo VARCHAR porque sua definição deve mudar à medida que o padrão SQL
evoluir. Deve-se usar VARCHAR2.
CHAR
Tamanho máximo: 2.000 bytes
O tipo CHAR é usado para conter dados de string de comprimento fixo.
Ao contrário das strings de VARCHAR2, uma string CHAR sempre contém o
número máximo de caracteres.
Outros tipos:
• NCHAR Tamanho máximo: 2.000 bytes;
• NCHAR VARYING Tamanho máximo: 4.000 bytes;
• CHAR VARYING Tamanho máximo: 4.000 bytes.
NUMBER(p,s)
Numérico com sinal e ponto decimal, sendo que p é a precisão de 1 a 38
dígitos e s é a escala, de -84 a 127.
Este tipo também possui subtipos como:
• DECIMAL: igual a NUMBER
• DEC: igual a DECIMAL
• DOUBLE PRECISION: igual a NUMBER
• NUMERIC: igual a NUMBER
• REAL: igual a NUMBER
• INTEGER: equivalente a NUMBER(38)
• INT: igual a INTEGER
• SMALLINT: igual a NUMBER(38)
• FLOAT: igual a NUMBER
54
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
• FLOAT(prec): igual a NUMBER(prec), mas a precisão é expressa em
termos de bits binários, não de dígitos decimais. A precisão binária
pode variar de 1 até 126.
• BINARY_INTEGER: semelhante a INTEGER. É usada para indexar tabela PL/SQL.
DATE
1 JAN 4712 BC até 31 DEC 4712 AD (DATA com hora, minuto e segundo) O tipo DATE é usado para armazenar os valores de data e hora. Um
nome melhor seria DATETIME porque o componente de hora está sempre lá,
independente de você usá-lo ou não. Se não for especificada a hora ao atribuir um valor para uma variável deste tipo, o padrão de meia-noite (12:00:00
a.m.) será usado.
BOOLEAN
True e False.
LONG
Tamanho máximo para tabela: 2 GB. Tamanho máximo para PLSQL:
32.760. Somente pode existir uma coluna por tabela.
RAW
Tamanho máximo para campos de tabela: 2.000 bytes. Tamanho máximo
para PL/SQL: 32.767. LONG RAW é outro tipo parecido com RAW, a diferença
é que ele possui 7 bytes a menos quando utilizado em PL/SQL.
CLOB
Tamanho máximo: (4 GB - 1) * DB_BLOCK_SIZE. Parâmetro de
inicialização: 8 TB a 128 TB. O número de colunas CLOB por tabela é limitado
somente pelo número máximo de colunas por tabela.
Armazena textos, que são validados conforme o set de caracteres, ou seja,
armazena acentuação etc.
55
6.6. Tipos de dados em PL/SQL
Casa do Código
Tipos LOB, surgiram em substituição aos tipos LONG e LONG RAW, pois
eles só permitiam uma coluna por tabela. Já os tipos LOB permitem mais de
uma coluna.
NCLOB
Tamanho máximo: (4 GB - 1) * DB_BLOCK_SIZE. Parâmetro de
inicialização: 8 TB a 128 TB. O número de colunas NCLOB por tabela é limitado somente pelo número máximo de colunas por tabela.
Objeto de grande capacidade de caracteres nacionais – contém até 4 GB de
caracteres de bytes simples ou caracteres multibyte que atendem o conjunto
de caracteres nacional definido pelo banco de dados Oracle.
BLOB
Tamanho máximo: (4 GB - 1) * DB_BLOCK_SIZE. Parâmetro de
inicialização: 8 TB a 128 TB. O número de colunas BLOB por tabela é limitado
somente pelo número máximo de colunas por tabela.
Armazenam dados não estruturados como: som, imagem, dados binários.
BFILE
Tamanho máximo: 4 GB. Tamanho máximo para o nome do arquivo: 255
caracteres. Tamanho máximo para o nome do diretório: 30 caracteres. O
valor máximo de BFILEs é limitado pelo valor do parâmetro de inicialização SESSION_MAX_OPEN_FILES, o qual é limitado pelo número máximo
de arquivos abertos que o sistema operacional suporta.
ROWID
É um tipo especial usado para armazenar os ROWIDs (endereços físicos)
das linhas armazenadas em uma tabela.
Campos LONG
Em resumo, os tipos comumente utilizados são:
NUMBER, DATE, BOOLEAN e os da família LOB.
56
CHAR, VARCHAR2,
Casa do Código
Capítulo 6. Aspectos iniciais da programação PL/SQL
No entanto, existem algumas restrições para campos LONG e LONG RAW.
• Não se pode criar um OBJECT TYPE com o atributo de LONG.
• Uma coluna LONG não pode estar dentro da cláusula WHERE ou com
referência integral dos dados, exceto NULL ou NOT NULL.
• Uma função não pode retornar um campo LONG.
• Uma tabela poderá ter somente um campo LONG.
• LONG não pode ser indexada.
• LONG não pode usar cláusulas WHERE, conforme já mencionado,
GROUP BY, ORDER BY e CONNECT BY.
Uma dica para você usar um campo LONG na cláusula WHERE é criar uma
tabela temporária com os campos da tabela original, mas alterando um tipo
LONG para CLOB. Também é possível alterar diretamente na tabela o campo
LONG para CLOB, caso não tenha problema de alterar a estrutura da tabela
original.
57
Capítulo 7
Exceções
Exceções são utilizadas dentro do Oracle quando algum erro acontece.
Quando construímos programas em PL/SQL é fundamental tratarmos as exceções que podem ocorrer mediante a execução do sistema e seus diversos
processos. Basicamente, existem dois tipos de exceções dentro do Oracle: as
predefinidas e as definidas pelo usuário.
• Exceções predefinidas: são exceções existentes implicitamente dentro
do Oracle e que são disparadas automaticamente por ele quando ocorre
um erro no programa.
• Exceções definidas pelo usuário: são exceções que precisam ser declaradas e disparadas pelo usuário. O Oracle desconhece sua existência.
7.1. Exceções predefinidas
Casa do Código
7.1 Exceções predefinidas
Como foi dito, uma exceção é acionada quando um erro acontece dentro do
programa. Mesmo que não as tratemos, o Oracle intercepta o problema e
mostra o erro. Todavia, se deixarmos que o Oracle faça isto nós podemos ter
sérios problemas, pois erros que não são tratados causam a parada do sistema,
ou seja, o programa é abortado.
Dentro da PL/SQL tratamos estes erros através das exceptions. Os
mais variados tipos de erros podem ser tratados através deste recurso. Por
exemplo, se temos dentro do nosso programa PL/SQL um cálculo onde possa
acontecer uma divisão por zero, caso ocorra, um erro é disparado, pois sabemos que matematicamente não é possível resolvê-lo. A PL/SQL sabe disso e
vai gerar uma exceção caso isto ocorra. Mediante isto, podemos nos antecipar
e tratar este possível erro.
Um ponto bom de tratarmos os erros é a possibilidade de mostrarmos
mensagens mais amigáveis aos usuários e lhes propor ações que possam
ajudá-los a resolver sem a intervenção da área de suporte, por exemplo. Além
do mais, evitamos que o programa ou todo o sistema seja abortado, o que
geraria um grande incômodo. Através do tratamento de exceções também é
possível determinar se o programa pode continuar ou não com a ação após o
erro ter ocorrido.
Como este acionamento é feito?
Quando acontece um desses erros predefinidos pelo Oracle, automaticamente a PL/SQL percebe sua ocorrência e o transfere para uma área de tratamento de erro. No entanto, às vezes esses erros demonstram certa falta de clareza em suas descrições, envolvendo termos muito técnicos, geralmente em
inglês, o que pode confundir o usuário. Com isso em mente, eles podem ser
tratados pelo desenvolvedor de sistemas a fim de torná-los mais compreensíveis. Contudo, o mesmo não acontece com os erros causados pelos usuários.
Este tipo de erro a PL/SQL não consegue detectar pelo fato de não estarem
incluídos implicitamente no Oracle. O uso das exceções é bem flexível, podendo ser usadas dentro de blocos anônimos, procedures, functions,
packages e triggers.
60
Casa do Código
Capítulo 7. Exceções
Primeiramente, vamos falar sobre as exceptions predefinidas. Segue
uma lista de exceptions que podem ser utilizadas em PL/SQL.
• no_data_found: dispara quando um select into é executado e
não retorna nenhum registro. Não ocorre se usarmos funções de grupo,
pois estas retornam valores nulos quando não há registros. Também
não ocorre em fetch (usado em cursores). Neste caso usamos atributos de cursor. Exemplo: C1%NO* TFOUND retorna verdadeiro se não
encontrar mais linhas.
• invalid_cursor: tentamos usar um cursor que não está aberto.
• invalid_number: quando a conversão de um tipo para outro não é
possível, ou quando um valor ultrapassa o número de casas definidas
para o tipo de dado. Exemplo: uma variável number(2) recebe o valor
100.
• login_denied: tentativa de conectar ao banco de dados com usuário
inválido.
• cursor_already_open: tentamos abrir um cursor que já se encontra aberto.
• dup_val_on_index: tentativa de inserir valor duplicado em um índice único. Usado na verificação de chave primária ou única.
• not_logged_on: tentamos usar algum recurso do banco sem estarmos conectados.
• program_error: erro interno ao sistema Oracle, chamado de
internal.
• rowtype_mismatch: quando um fetch retorna uma determinada
linha do banco de dados para uma variável do tipo registro onde os dados desta linha não são compatíveis com os tipos definidos na variável.
• timeout_on_resource: tempo expirou quando o banco esperava
pelo recurso.
61
7.1. Exceções predefinidas
Casa do Código
• too_many_rows: um select into retornou mais de uma linha.
• value_error:
em algumas circunstâncias
invalid_number ou value_error.
é
disparado
• zero_divide: tentamos dividir por zero.
• others: quando não sabemos qual erro pode ocorrer.
Esta é uma lista das exceptions mais comuns. Para maiores detalhes e
demais exceções, consulte a documentação do banco de dados da versão que
estiver utilizando.
Vamos abrir um parêntese para falar um pouco sobre a exceção others
e sobre as exceções invalid_number e value_error.
A exception others é muito utilizada, pois mesmo que tratemos erros específicos sempre a utilizamos para garantir que demais erros não causem a parada do sistema. Qualquer exception quando não tratada em
específico acaba sendo amparada pela exceção others. Portanto, quando
tratamos diversas exceções devemos sempre colocá-la por último na seção de
tratamento. Outro ponto altamente recomendado é que pelo menos a exceção
others seja sempre tratada, independente se já estamos tratado de outras em
específico.
Já com relação às exceções invalid_number e value_error, embora,
possam parecer redundantes, existem lugares específicos onde elas podem ser
usadas. invalid_number é acionada por erros em comandos SQL dentro
dos blocos PL/SQL. Já a exceção value_error é disparada por erros em
comandos PL/SQL.
Veja onde e como tratar as exceções. Analise o caso a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❡♠♣♥♦ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
s❡❧❡❝t ❡♠♣♥♦
✻
✐♥t♦ ✇❡♠♣♥♦
✼
❢r♦♠ ❡♠♣
✽
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾✾✾❀
62
Casa do Código
Capítulo 7. Exceções
✾
✲✲
✶✵ ❡♥❞❀
✶✶ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✶✿
❖❘❆✲✵✶✹✵✸✿ ❞❛❞♦s ♥ã♦ ❡♥❝♦♥tr❛❞♦s
❖❘❆✲✵✻✺✶✷✿ ❡♠ ❧✐♥❡ ✺
❙◗▲❃
Neste exemplo estamos tentando selecionar o empregado com o código
9999. Entretanto, este empregado não existe. Como estamos utilizando um
select into, sabemos que quando um select deste tipo não retorna
linhas o Oracle dispara uma exceção. Neste caso, foi o que aconteceu. Ao
tentarmos selecionar a linha, o comando não a localizou fazendo com que
o Oracle gerasse uma exceção. O resultado foi uma mensagem de erro informando que os dados não foram encontrados. Contudo, estamos falando
de um exemplo simples. Se tivéssemos um programa com muitos comandos
select, ficaria difícil saber onde estaria o erro. Sem falar que a mensagem
não ajudaria muito o usuário a resolver o problema por si só. Agora vamos
tratar esta exceção e ver o que acontece.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❡♠♣♥♦ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
s❡❧❡❝t ❡♠♣♥♦
✻
✐♥t♦ ✇❡♠♣♥♦
✼
❢r♦♠ ❡♠♣
✽
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾✾✾❀
✾
✲✲
✶✵ ❡①❝❡♣t✐♦♥
✶✶
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✶✸
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳✬✮❀
63
7.1. Exceções predefinidas
Casa do Código
✶✺ ❡♥❞❀
✶✻ ✴
❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Primeiramente, vamos analisar o programa. Como pode ser visto, entre o begin e o end, temos a expressão exception. É nesta área que
definimos quais exceções vamos tratar. Perceba que logo após a expressão
exception temos várias cláusulas when indicando quais exceções estamos
tratando. Neste exemplo, estamos tratando as exceções no_data_found
e others. O tratamento de exceções deve sempre acompanhar um bloco
PL/SQL e seu escopo é válido somente dentro dele. Veja a sintaxe.
❞❡❝❧❛r❡
✲✲ ✈❛r✐á✈❡✐s
❜❡❣✐♥
✲✲
✲✲ ❝♦♠❛♥❞♦s
❜❡❣✐♥
✲✲ ❝♦♠❛♥❞♦s
❡①❝❡♣t✐♦♥
✇❤❡♥ ❁❡①❝❡♣t✐♦♥ ✶❃ t❤❡♥
✲✲ ❝♦♠❛♥❞♦s ♦✉ ♠❡♥s❛❣❡♥s✳
✇❤❡♥ ❁❡①❝❡♣t✐♦♥ ♥❃ t❤❡♥
✲✲ ❝♦♠❛♥❞♦s ♦✉ ♠❡♥s❛❣❡♥s✳
❡♥❞❀
✲✲ ♠❛✐s ❝♦♠❛♥❞♦s
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ❁❡①❝❡♣t✐♦♥ ✶❃ t❤❡♥
✲✲ ❝♦♠❛♥❞♦s ♦✉ ♠❡♥s❛❣❡♥s✳
✇❤❡♥ ❁❡①❝❡♣t✐♦♥ ♥❃ t❤❡♥
✲✲ ❝♦♠❛♥❞♦s ♦✉ ♠❡♥s❛❣❡♥s✳
❡♥❞❀
Veja neste exemplo que temos um bloco dentro de outro, e cada um possui
64
Casa do Código
Capítulo 7. Exceções
sua área de tratamento de exceções. Note também que esta é definida sempre
no fim do bloco. Muito bem, continuando nosso exemplo, podemos perceber
que nele temos dois tratamentos. Um para verificar se o empregado existe
e outro para o caso de acontecer qualquer outro erro de que não se tenha
conhecimento.
De propósito, tentamos selecionar os empregados que são de um departamento que não existe na tabela EMP para que a exceção fosse acionada. Com
o acionamento da exceção, a mensagem “Empregado não encontrado” foi impressa na tela, atingindo nosso objetivo. Com isso, foi possível mostrar uma
mensagem muito mais inteligível e de quebra não permitimos que o Oracle
abortasse o programa. Utilizamos o pacote dbms_output para imprimir na
tela a nossa mensagem de erro.
Neste exemplo, vamos colocar um código de departamento que existe na
tabela EMP.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
❊rr♦
❞❡❝❧❛r❡
✇❡♠♣♥♦ ♥✉♠❜❡r❀
❜❡❣✐♥
✲✲
s❡❧❡❝t ❡♠♣♥♦
✐♥t♦ ✇❡♠♣♥♦
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳✬✮❀
❡♥❞❀
✴
❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Analisando este segundo exemplo podemos observar que a exceção
65
7.1. Exceções predefinidas
Casa do Código
no_data_found não foi acionada. Entretanto a exceção others foi. Tam-
bém pudera, quando colocamos um código de departamento existente na tabela EMP, o select retornou várias linhas. Várias linhas em um select
into geram uma exceção chamada too_many_rows. Desta forma vamos
incluí-la em nosso programa.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❡♠♣♥♦ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
s❡❧❡❝t ❡♠♣♥♦
✻
✐♥t♦ ✇❡♠♣♥♦
✼
❢r♦♠ ❡♠♣
✽
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✾
✲✲
✶✵ ❡①❝❡♣t✐♦♥
✶✶
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✶✸
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✶✺
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✶✻
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳✬✮❀
✶✽ ❡♥❞❀
✶✾ ✴
❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠
r❡❣✐str♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Incluindo a exceção too_many_rows, foi possível tratar o erro em específico e melhorar a mensagem de erro. Vale salientar que a exception foi
incluída antes da exceção others. Isso sempre deve ser feito desta forma.
Voltando um pouco no exemplo anterior a este, foi possível observar que
sem o tratamento da exceção too_many_rows, ficou difícil identificar qual
66
Casa do Código
Capítulo 7. Exceções
o problema ocorreu, pois como a exceção others é para todas as exceções
que podem ocorrer dentro do programa, não conseguimos especificar uma
mensagem de erro clara o suficiente. É óbvio que nesse exemplo, sabíamos
qual era o problema e alteramos o programa para tratá-lo. Contudo, mesmo
assim, outros tipos de problemas podem ocorrer fora os tratados especificamente. Caso isso aconteça, é necessário pelo menos uma mensagem mais
detalhada sobre o erro, para que o problema possa ser identificado e resolvido.
Para identificar erros não conhecidos, aqueles que acabam caindo na exceção others, podemos contar com duas variáveis que são alimentadas cada
vez que uma exception é disparada. As variáveis são sqlcode e sqlerrm.
A primeira mostra somente o código e a segunda mostra o código e a descrição do erro, vindos do Oracle. Cada erro dentro Oracle possui um código
associado a ele. Desta forma, quando uma exception é gerada, o código
do erro corrente é gravado na variável sqlcode. A mesma coisa acontece
com a variável sqlerrm. Cada erro possui uma descrição explicando seu
motivo. Ao ser gerada uma exceção, esta variável recebe a descrição do erro
corrente. Com isto, é possível obter o código e descrição do erro, o que possibilita identificar sua causa. Estas variáveis podem e devem ser usadas quando
tratamos a exceção others.
Vale salientar, entretanto, que na maioria das vezes a descrição dos erros
vindos do Oracle não são descrições muito amigáveis. Os usuários podem ter
dificuldades em identificar o que exatamente ocorreu. Por isso a importância
de tratarmos pelo menos as exceções conhecidas dentro de um programa,
a fim de clarear ao máximo os erros que podem ocorrer. Vamos voltar ao
exemplo anterior e usar as variáveis para identificar o problema ocorrido.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❡♠♣♥♦ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
s❡❧❡❝t ❡♠♣♥♦
✻
✐♥t♦ ✇❡♠♣♥♦
✼
❢r♦♠ ❡♠♣
✽
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✾
✲✲
✶✵ ❡①❝❡♣t✐♦♥
67
7.1. Exceções predefinidas
Casa do Código
✶✶
✶✷
✶✸
✶✹
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
✶✺
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✶✻ ❡♥❞❀
✶✼ ✴
❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ❖❘❆✲✵✶✹✷✷✿ ❛ ❡①tr❛çã♦ ❡①❛t❛
r❡t♦r♥❛ ♠❛✐s ❞♦
q✉❡ ♦ ♥ú♠❡r♦ s♦❧✐❝✐t❛❞♦ ❞❡ ❧✐♥❤❛s ✲ ❈ó❞✐❣♦✿ ✭✲✶✹✷✷✮✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
No exemplo a seguir concatenamos as variáveis sqlcode e sqlerrm
com nossa mensagem de erro. Uma observação, a variável sqlerrm já
traz o código do erro, não tendo necessidade de utilizar o sqlcode, a menos, é claro, que você queira usar este código para algo diferente de apenas mostrar a informação. Para mostrar apenas a descrição do erro use
sqlerrm(sqlcode). Note também que a informação vinda do banco de
dados não é muito clara. Dependendo da linguagem instalada para banco de
dados, o Oracle procura traduzir a mensagem de erro e às vezes torna mais
difícil sua compreensão.
Uma dica importante: caso você não compreenda a mensagem de erro
ou ela não exista, é possível, através do código do erro, pesquisar maiores
detalhes na documentação do banco Oracle ou na internet. Estes códigos são
padronizados e em qualquer versão ou linguagem eles se mantêm os mesmos.
Uma vez gerada a exceção, isso não garante que o programa vá parar o
processo. Como foi visto, podemos ter vários blocos dentro do mesmo programa PL/SQL e cada um destes blocos podem ter tratamentos de erros. Estes
blocos, por sua vez, podem conter dependências uns com os outros e para isto
pode ser necessário parar o processo quando um erro acontece, não permitindo que o programa continue.
68
Casa do Código
Capítulo 7. Exceções
Nota: o fato de nós tratarmos as exceptions nos remete a outro
ponto a que devemos estar atentos. Quando não a tratamos, o Oracle
realiza este tratamento e aborta o programa. Já quando o tratamento fica
por nossa conta, ou melhor, por conta do nosso programa, somos nós
quem define se haverá ou não uma parada no sistema ou no processo
que está sendo executado, ou seja, quando tratamos um erro, o Oracle
passa a não tratá-lo mais e as ações ficam por nossa conta.
Veja o exemplo a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
♥✉♠❜❡r❀
✸
✇❞❡♣t♥♦ ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ❛✈❣✭s❛❧✮✱ ❞❡♣t♥♦
✽
✐♥t♦ ✇s❛❧✱ ✇❞❡♣t♥♦
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾
✶✶
❣r♦✉♣ ❜② ❞❡♣t♥♦❀
✶✷
❡①❝❡♣t✐♦♥
✶✸
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳✬✮❀
✶✺
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ✈❛❧♦r❡s
r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳ ✾✾✳ ✬⑤⑤
✶✼
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✶✽
❡♥❞❀
✶✾
✲✲
✷✵
❜❡❣✐♥
✷✶
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷✷
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
69
7.1. Exceções predefinidas
Casa do Código
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✲✲
❝♦♠♠✐t❀
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✷✾
✸✵
❡♥❞❀
✸✶
✲✲
✸✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✸✸
✲✲
✸✹ ❡①❝❡♣t✐♦♥
✸✺
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✸✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✸✼
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
✸✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✸✾
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✹✵
✇❤❡♥ ♦t❤❡rs t❤❡♥
✹✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
✹✷
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✹✸ ❡♥❞❀
✹✹ ✴
❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳
❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo criamos um bloco PL/SQL que insere um novo empregado. Dentro do nosso programa temos um select que busca a média dos
salários dos empregados de um determinado departamento. Neste select
estamos tratando as exceções no_data_found e others. Logo após, realizamos a inclusão do empregado através do comando insert informando
como salário deste empregado o valor vindo do select anterior. Depois
70
Casa do Código
Capítulo 7. Exceções
informamos ao usuário que o empregado foi inserido com sucesso. Veja que
para o comando insert também estamos tratando a exceção others para
o caso de algum erro.
Entretanto, executando o programa podemos observar que algumas mensagens foram geradas, inclusive a de que os valores dos salários não foram encontrados para o departamento em questão. O resultado disso foi a inclusão
do empregado com o salário igual a zero.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣ ♦r❞❡r ❜② ❡♠♣♥♦❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✹✾✾
✼✺✷✶
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✽✸✾
✼✽✹✹
✼✾✵✵
✼✾✸✹
✼✾✸✺
✽✵✵✶
✽✵✵✷
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❆▲▲❊◆
❲❆❘❉
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❑■◆●
❚❯❘◆❊❘
❏❆▼❊❙
▼■▲▲❊❘
P❆❯▲
❙■▲❱❊❙❚❊❘
❆◆●❊▲■◆❆
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✵✴✵✷✴✽✶
✶✻✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✷✴✵✷✴✽✶
✶✷✺✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✽✴✵✾✴✽✶
✶✷✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✶✴✵✺✴✽✶
✷✽✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✾✴✵✻✴✽✶
✷✹✺✵
P❘❊❙■❉❊◆❚
✶✼✴✶✶✴✽✶
✺✵✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✵✽✴✵✾✴✽✶
✶✺✵✵
❈▲❊❘❑
✼✻✾✽ ✵✸✴✶✷✴✽✶
✾✺✵
❈▲❊❘❑
✼✼✽✷ ✷✸✴✵✶✴✽✷
✶✸✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✶✺✴✵✸✴✽✵
✶✵✵✵
▼❆◆❆●❊❘
✼✽✸✾
✶✵✵✵
▼❆◆❆●❊❘
✼✽✸✾ ✷✵✴✶✵✴✶✶
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✸✵✻
✸✵
✺✶✵
✸✵
✶✹✷✽
✸✵
✷✽✺
✸✵
✷✹✺
✶✵
✺✵✵
✶✵
✶✺✵
✸✵
✾✺
✸✵
✶✸✵
✶✵
✶✵✵
✸✵
✽✵
✷✵
71
Casa do Código
7.1. Exceções predefinidas
✶✷ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Podemos agravar a situação colocando a coluna SAL como not null,
para que surja um erro no momento da inserção do registro.
❙◗▲❃ ❛❧t❡r t❛❜❧❡ ❡♠♣ ♠♦❞✐❢② s❛❧ ♥✉♠❜❡r✭✼✱✷✮ ♥♦t ♥✉❧❧❀
❚❛❜❡❧❛ ❛❧t❡r❛❞❛✳
❙◗▲❃ ❞❡s❝ ❡♠♣
◆♦♠❡
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❊▼P◆❖
❊◆❆▼❊
❏❖❇
▼●❘
❍■❘❊❉❆❚❊
❙❆▲
❈❖▼▼
❉❊P❚◆❖
P❈❴❈❖▼❴❙❆▲
❚✐♣♦
◆✉❧♦❄
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
◆❖❚ ◆❯▲▲ ◆❯▼❇❊❘✭✹✮
❱❆❘❈❍❆❘✷✭✶✵✮
❱❆❘❈❍❆❘✷✭✾✮
◆❯▼❇❊❘✭✹✮
❉❆❚❊
◆❖❚ ◆❯▲▲ ◆❯▼❇❊❘✭✼✱✷✮
◆❯▼❇❊❘✭✼✱✷✮
◆❯▼❇❊❘✭✷✮
◆❯▼❇❊❘
❙◗▲❃
Vamos excluir o registro existente e executar o programa novamente.
❙◗▲❃ ❞❡❧❡t❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✽✵✵✷❀
✶ ❧✐♥❤❛ ❞❡❧❡t❛❞❛✳
❙◗▲❃ ❝♦♠♠✐t❀
❱❛❧✐❞❛çã♦ ❝♦♠♣❧❡t❛✳
❙◗▲❃
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
72
♥✉♠❜❡r❀
Casa do Código
Capítulo 7. Exceções
✸
✇❞❡♣t♥♦ ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ❛✈❣✭s❛❧✮✱ ❞❡♣t♥♦
✽
✐♥t♦ ✇s❛❧✱ ✇❞❡♣t♥♦
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾
❣r♦✉♣ ❜② ❞❡♣t♥♦❀
✶✶
✶✷
❡①❝❡♣t✐♦♥
✶✸
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳✬✮❀
✶✺
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ✈❛❧♦r❡s
r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳ ✾✾✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✶✼
✶✽
❡♥❞❀
✶✾
✲✲
✷✵
❜❡❣✐♥
✷✶
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷✷
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
✷✸
✲✲
✷✹
❝♦♠♠✐t❀
✷✺
✲✲
✷✻
❡①❝❡♣t✐♦♥
✷✼
✇❤❡♥ ♦t❤❡rs t❤❡♥
✷✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠ ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✷✾
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✸✵
❡♥❞❀
✸✶
✲✲
✸✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✸✸
✲✲
✸✹ ❡①❝❡♣t✐♦♥
73
7.1. Exceções predefinidas
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
Casa do Código
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
❡♥❞❀
✴
❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳
❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠ ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ❖❘❆✲✵✶✹✵✵✿ ♥ã♦ é
♣♦ssí✈❡❧ ✐♥s❡r✐r ◆❯▲▲ ❡♠ ✭✧❚❙◗▲✧✳✧❊▼P✧✳✧❙❆▲✧✮✳
❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Veja que o programa nos deu várias mensagens. A primeira informa que
não conseguiu recuperar o salário referente ao departamento encontrado. A
segunda nos alerta que o empregado não pode ser inserido pelo fato de um
erro ter ocorrido. Note que usamos a exceção others com as variáveis de
erro, que nos apontou que não é possível inserir valores nulos para o campo
SAL da tabela EMP. Isso aconteceu devido à alteração que realizamos. Entretanto, veja que a mensagem nos informando que o empregado foi inserido
com sucesso também é mostrada. Isso é um erro, pois na verdade ele não foi
inserido. Neste caso, temos que tratar estas situações no programa para que as
ações e mensagens estejam condizentes com que realmente está acontecendo.
Se nós partimos do pressuposto de que nenhum dos empregados pudesse
ser incluído sem um valor de salário definido, teríamos que alterar o programa para que ele não incluísse o empregado caso não conseguisse recuperar
o salário. Pois bem, sem alterar a estrutura do nosso programa vamos utilizar
um recurso da PL/SQL que permite parar a execução do programa quando
for necessário.
74
Casa do Código
Capítulo 7. Exceções
Quando desejarmos que um programa ou processo seja interrompido
após uma exceção, utilizamos a chamada raise_applications_error.
Esta chamada faz com que o programa pare sua execução a partir de um determinado ponto. Em contrapartida, ela desvia o programa para o primeiro
tratamento de erro existente, que se encaixe com o erro ocorrido, seguindo a
hierarquia dos blocos. No geral, este desvio sempre é interceptado pela exceção others.
Esta chamada requer dois parâmetros, um código de erro e uma descrição. Como já foi dito, a Oracle mantém uma padronização de códigos de
erros para que o mesmo erro seja identificado em qualquer banco de dados,
em qualquer versão ou idioma, seja aqui ou do outro lado do mundo. Logo,
estes códigos não podem ser usados pelos desenvolvedores para customizar
erros. Em contrapartida ela disponibiliza uma faixa de código que vai a partir
do número -20000 até -20999, para que utilizemos nestes casos. Seria uma
faixa de códigos de erros customizável. A descrição do erro fica por nossa
conta. Vamos testar a alteração do programa.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
♥✉♠❜❡r❀
✸
✇❞❡♣t♥♦ ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ❛✈❣✭s❛❧✮✱ ❞❡♣t♥♦
✽
✐♥t♦ ✇s❛❧✱ ✇❞❡♣t♥♦
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾
✶✶
❣r♦✉♣ ❜② ❞❡♣t♥♦❀
✶✷
❡①❝❡♣t✐♦♥
✶✸
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✶✹
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳✬✮❀
✶✺
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ✈❛❧♦r❡s
r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳ ✾✾✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✶✼
✶✽
❡♥❞❀
75
7.1. Exceções predefinidas
✶✾
✷✵
✷✶
Casa do Código
✲✲
❜❡❣✐♥
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷✷
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
✷✸
✲✲
✷✹
❝♦♠♠✐t❀
✷✺
✲✲
✷✻
❡①❝❡♣t✐♦♥
✷✼
✇❤❡♥ ♦t❤❡rs t❤❡♥
✷✽
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱✬❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠
♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✷✾
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✸✵
❡♥❞❀
✸✶
✲✲
✸✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✸✸
✲✲
✸✹ ❡①❝❡♣t✐♦♥
✸✺
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✸✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✸✼
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
✸✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✸✾
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✹✵
✇❤❡♥ ♦t❤❡rs t❤❡♥
✹✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
✹✷
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✹✸ ❡♥❞❀
✹✹ ✴
❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ❖❘❆✲✷✵✵✵✵✿ ❱❛❧♦r❡s ♥ã♦
❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳
✲
❈ó❞✐❣♦✿ ✭✲✷✵✵✵✵✮✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
76
Casa do Código
Capítulo 7. Exceções
❙◗▲❃
Analisando o resultado da execução, podemos perceber que ocorreu um
erro na busca pelo valor do salário, onde não foi encontrado. Isso gerou a exceção no_data_found. Através do tratamento desta exceção foi chamado
o raise_application_error, que gerou uma exceção fazendo com o
programa fosse desviado para o tratamento de exceção mais externo ao seu
bloco, no caso, o tratamento others, localizado na linha 40 no nosso programa. Isso, porque, embora, exista outro tratamento others logo a seguir,
no bloco referente ao insert, eles estão em um mesmo nível. Por isso, a ação
do programa foi desviada para o tratamento mais externo. Com o desvio, o
programa não continua com as ações subsequentes atingindo assim nosso objetivo de tratamento.
Nota: se estivermos utilizando uma estrutura loop e uma exceção for
gerada dentro dela, e não havendo uma área de tratamento de exceções
nesta estrutura, o loop é interrompido e o programa é desviado para o
primeiro tratamento encontrado em um nível mais externo. Caso haja
uma área de tratamento de exceções dentro loop, e ela não requerer
a parada do sistema, o loop continuará normalmente até alcançar o
término programado.
Agora vamos alterar o código do departamento para um existente, para
realizar um novo teste.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
♥✉♠❜❡r❀
✸
✇❞❡♣t♥♦ ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ❛✈❣✭s❛❧✮✱ ❞❡♣t♥♦
✽
✐♥t♦ ✇s❛❧✱ ✇❞❡♣t♥♦
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
77
7.1. Exceções predefinidas
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
78
Casa do Código
❣r♦✉♣ ❜② ❞❡♣t♥♦❀
❡①❝❡♣t✐♦♥
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❱❛❧♦r❡s ♥ã♦ ❡♥❝♦♥tr❛❞♦s ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ✾✾✳✬✮❀
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ✈❛❧♦r❡s
r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳ ✶✵✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
❡♥❞❀
✲✲
❜❡❣✐♥
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
✲✲
❝♦♠♠✐t❀
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠ ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
❡♥❞❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✇❤❡♥ ♦t❤❡rs t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
Casa do Código
Capítulo 7. Exceções
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✹✷
✹✸ ❡♥❞❀
✹✹ ✴
❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Como era o esperado, o programa funcionou normalmente. Pode-se
ainda simular o erro referente ao comando insert, atribuindo null à variável wsal antes da inclusão.
7.2 Exceções definidas pelo usuário
Como foi dito anteriormente, além das exceções predefinidas existentes no
Oracle, podemos criar novas exceções para atender a necessidades mais específicas do nosso programa. A diferença entre estes tipos está na definição
e controle destas exceções. Este tipo, quando utilizado pelo usuário, deve ser
declarado e manipulado pelo próprio programa. Para o Oracle, estas exceções
não existem, por isso, todo o controle deve ser feito pela aplicação. Vamos ver
o exemplo a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
♥✉♠❜❡r❀
✸
✇❡rr♦❴s❛❧❛r✐♦ ❡①❝❡♣t✐♦♥❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ♥✈❧✭❛✈❣✭s❛❧✮✱✵✮
✽
✐♥t♦ ✇s❛❧
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾❀
✶✶
✲✲
✶✷
✐❢ ✇s❛❧ ❂ ✵ t❤❡♥
✶✸
✲✲
✶✹
r❛✐s❡ ✇❡rr♦❴s❛❧❛r✐♦❀
79
7.2. Exceções definidas pelo usuário
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
Casa do Código
✲✲
❡♥❞ ✐❢❀
✲✲
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r ✈❛❧♦r❡s r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳
✾✾✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✷✶
✷✷
❡♥❞❀
✷✸
✲✲
✷✹
❜❡❣✐♥
✷✺
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷✻
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
✷✼
✲✲
✷✽
❝♦♠♠✐t❀
✷✾
✲✲
✸✵
❡①❝❡♣t✐♦♥
✸✶
✇❤❡♥ ♦t❤❡rs t❤❡♥
✸✷
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠ ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✸✸
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✸✹
❡♥❞❀
✸✺
✲✲
✸✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✸✼
✲✲
✸✽ ❡①❝❡♣t✐♦♥
✸✾
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✹✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✹✶
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
✹✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✹✸
✹✹
✇❤❡♥ ♦t❤❡rs t❤❡♥
✹✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
80
Casa do Código
Capítulo 7. Exceções
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✹✻
✹✼ ❡♥❞❀
✹✽ ✴
❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ❖❘❆✲✷✵✵✵✵✿ ❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r
✈❛❧♦r❡s r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳
✾✾✳
❊rr♦✿ ❯s❡r✲❉❡❢✐♥❡❞ ❡①❝❡♣t✐♦♥✳ ✲ ❈ó❞✐❣♦✿ ✭✲✷✵✵✵✵✮✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Vamos entender o exemplo. Primeiramente, precisamos definir um nome
para a exceção e declará-la na área de declaração de variáveis. No exemplo,
chamamos nossa exceção de werro_salario. Quando declaramos uma
variável do tipo exceção utilizamos o tipo exception. Feito isto, já podemos utilizá-la em nosso programa. Modificamos o programa utilizado nos
exemplos anteriores, justamente para mostrar formas diferentes de tratar os
mesmos problemas. Modificamos o select que busca o salário para que ele
não gere a exceção nativa do Oracle.
Sabemos que o uso de funções de agrupamento, como sum, min, max,
avg etc., não geram exceções mesmo não atendendo à cláusula where. Com
isso, a exceção no_data_found não é gerada. Contudo, para realizar o controle e não permitir que valores nulos ou zerados sejam cadastrados no campo
salário, nós utilizamos uma estrutura if para testar o resultado vindo do
select, e dependendo como for, acionar ou não a exceção que definimos.
Nosso teste é bem simples, verificamos se o valor é igual ou diferente de
zero. Caso seja igual a zero chamamos nossa exceção através do comando
raise. Este comando aciona nossa exceção e faz com que a ação do programa seja desviada para a área de tratamento de erros dentro da hierarquia
de níveis, ou seja, a partir daí as regras e sequências são as mesmas utilizadas
nas exceções predefinidas.
Uma observação importante. Se houver comandos após a chamada
raise, eles nunca serão executados. Portanto, fique atento quanto a isto.
Note também que duas mensagens de erro foram geradas, inclusive, uma que
81
7.2. Exceções definidas pelo usuário
Casa do Código
diz que a exceção gerada foi uma exceção definida pelo usuário: User-Defined
exception. Ainda podemos melhorar esta mensagem inibindo os códigos de
erro e fazendo com que apareça apenas uma mensagem. Veja a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧
♥✉♠❜❡r❀
✸
✇❡rr♦❴s❛❧❛r✐♦ ❡①❝❡♣t✐♦♥❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❜❡❣✐♥
✼
s❡❧❡❝t ♥✈❧✭❛✈❣✭s❛❧✮✱✵✮
✽
✐♥t♦ ✇s❛❧
✾
❢r♦♠ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✾✾❀
✶✶
✲✲
✶✷
✐❢ ✇s❛❧ ❂ ✵ t❤❡♥
✶✸
✲✲
✶✹
r❛✐s❡ ✇❡rr♦❴s❛❧❛r✐♦❀
✶✺
✲✲
✶✻
❡♥❞ ✐❢❀
✶✼
✲✲
✶✽
❡①❝❡♣t✐♦♥
✶✾
✇❤❡♥ ✇❡rr♦❴s❛❧❛r✐♦ t❤❡♥
✷✵
r❛✐s❡ ✇❡rr♦❴s❛❧❛r✐♦❀
✷✶
✇❤❡♥ ♦t❤❡rs t❤❡♥
✷✷
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱✬❊rr♦ ❛♦ s❡❧❡❝✐♦♥❛r
✈❛❧♦r❡s r❡❢❡r❡♥t❡s ❛♦ ❞❡♣t♦✳ ✾✾✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✷✸
✷✹
❡♥❞❀
✷✺
✲✲
✷✻
❜❡❣✐♥
✷✼
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷✽
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❆◆●❊▲■◆❆✬✱ ✬▼❆◆❆●❊❘✬✱ ✼✽✸✾✱
❚❖❴❉❆❚❊✭✬✷✵✴✶✵✴✷✵✶✶✬✱✬❉❉✴▼▼✴❘❘❘❘✬✮✱
✇s❛❧✱ ♥✉❧❧✱ ✷✵✮❀
✷✾
✲✲
✸✵
❝♦♠♠✐t❀
✸✶
✲✲
82
Casa do Código
Capítulo 7. Exceções
✸✷
✸✸
✸✹
❡①❝❡♣t✐♦♥
✇❤❡♥ ♦t❤❡rs t❤❡♥
r❛✐s❡❴❛♣♣❧✐❝❛t✐♦♥❴❡rr♦r✭✲✷✵✵✵✵✱
✬❊rr♦ ❛♦ ✐♥s❡r✐r ✉♠ ♥♦✈♦ ❡♠♣r❡❣❛❞♦✳ ✬⑤⑤
✬❊rr♦✿ ✬⑤⑤sq❧❡rr♠⑤⑤✬✳✬✮❀
✸✺
✸✻
❡♥❞❀
✸✼
✲✲
✸✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦ ❆◆●❊▲■◆❆ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
✸✾
✲✲
✹✵ ❡①❝❡♣t✐♦♥
✹✶
✇❤❡♥ ✇❡rr♦❴s❛❧❛r✐♦ t❤❡♥
✹✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❖ s❛❧ár✐♦ ♥❡❝❡ss✐t❛ s❡r ♠❛✐♦r q✉❡ ③❡r♦✳✬✮❀
✹✸
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✹✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦ ♥ã♦ ❡♥❝♦♥tr❛❞♦✳✬✮❀
✹✺
✇❤❡♥ t♦♦❴♠❛♥②❴r♦✇s t❤❡♥
✹✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦✿ ❖ ❝ó❞✐❣♦ ❞❡ ❞❡♣❛rt❛♠❡♥t♦ ✐♥❢♦r♠❛❞♦✬⑤⑤
✹✼
✬ r❡t♦r♥♦✉ ♠❛✐s ❞❡ ✉♠ r❡❣✐str♦✳✬✮❀
✹✽
✇❤❡♥ ♦t❤❡rs t❤❡♥
✹✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊rr♦ ❛♦ ✐♥s❡r✐r ❡♠♣r❡❣❛❞♦✳ ❊rr♦✿ ✬⑤⑤sq❧❡rr♠
✺✵
⑤⑤✬ ✲ ❈ó❞✐❣♦✿ ✭✬⑤⑤sq❧❝♦❞❡⑤⑤✬✮✳✬✮❀
✺✶ ❡♥❞❀
✺✷ ✴
❖ s❛❧ár✐♦ ♥❡❝❡ss✐t❛ s❡r ♠❛✐♦r q✉❡ ③❡r♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Com isso, finalizamos a parte sobre exceções. Vimos que através delas
é possível realizar todos os tratamentos de erros de uma forma organizada
e sem prejudicar o funcionamento do sistema. Outro fator que deve ser comentado é que as exceções não servem apenas para geração de mensagens de
erro. Dentro das áreas de tratamento podemos usar chamadas a functions,
procedures ou packages para solucionar problemas sem a intervenção ou
83
7.2. Exceções definidas pelo usuário
até mesmo sem conhecimento do usuário.
84
Casa do Código
Capítulo 8
Estruturas de condição: if
As estruturas de condição são utilizadas quando precisamos alterar o fluxo de
caminho de um programa. Através deste tipo de estrutura conseguimos criar
condições que podem levar o programa a executar tarefas diferentes dependendo de cada situação. Portanto, utilizamos a declaração if para avaliar
uma ou mais condições, executando ou não determinadas linhas de instruções.
No PL/SQL utilizamos o comando if (se) para montar estas condições.
Podemos ter condições simples, com uma condição apenas, até o uso de condições aninhadas onde podemos ter comandos if dentro de outros comandos if, em uma mesma estrutura.
Juntamente com o comando if temos o comando else (se não), que
é utilizado para direcionar o programa para outros caminhos caso o if não
satisfaça a condição desejada. Dentro da estrutura de um comando if podemos ter desde um else até vários elses ( elsif), seguindo sua sintaxe.
8.1. Estruturas do comando if-end if
Casa do Código
O que deve ficar claro é que esta estrutura gera um resultado mediante uma
condição que satisfaça o critério imposto.
No mais, podemos dizer que será comum achar este tipo de estrutura dentro dos programas. Portanto, você vai utilizá-la com frequência, pois como na
grande maioria das vezes escrevemos códigos que refletem e abstraem situações do dia a dia, precisamos testar n variáveis para fazer com que o programa
chegue ao objetivo proposto em cada situação.
8.1
Estruturas do comando if-end if
❙◗▲❃ ❜❡❣✐♥
✷
✲✲
✸
✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✹
❁✐♥str✉çõ❡s❃
❡♥❞ ✐❢❀
✺
✻ ❡♥❞❀
✼
❙◗▲❃
Nesta estrutura, temos apenas uma condição. Caso o resultado de
<condicao> (linha 3) seja verdadeiro, ele estará satisfazendo a condição e
executará os comandos que estiverem dentro do escopo do if. Caso contrário, não. O end if indica o fim do comando if. Veja as execuções a seguir,
onde o programa é executado duas vezes, mas com diferentes valores:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
86
❞❡❝❧❛r❡
① ♥✉♠❜❡r ✿❂ ✶✵❀
r❡s ♥✉♠❜❡r❀
❜❡❣✐♥
r❡s ✿❂ ♠♦❞✭①✱✷✮❀
✐❢ r❡s ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
❡♥❞ ✐❢❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
❡♥❞❀
✴
Casa do Código
Capítulo 8. Estruturas de condição: if
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✼❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✷✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡♥❞ ✐❢❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✶ ❡♥❞❀
✶✷ ✴
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
8.2 Estruturas do comando if-else-end if
❙◗▲❃ ❜❡❣✐♥
✷
✲✲
✸
✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✹
❁✐♥str✉çõ❡s❃
✺
❡❧s❡
✻
❁✐♥str✉çõ❡s❃
✼
❡♥❞ ✐❢❀
✽ ❡♥❞❀
✾
❙◗▲❃
Esta estrutura é formada por um if e um else. Caso a condição do if
87
8.2. Estruturas do comando if-else-end if
Casa do Código
não seja atendida o fluxo será desviado para o else. Note que o else não
faz restrição ou checagem de condição. Em vias gerais o comando quer dizer:
se a condição for verdadeira faça isso, se não faça aquilo.
Vamos ver o mesmo exemplo, agora com duas condições, if e else,
onde dependendo do resultado pode-se determinar qual fluxo o programa
deve percorrer.
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✶✵❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✷✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡❧s❡
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦✬✮❀
✶✵
❡♥❞ ✐❢❀
✶✶
✲✲
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✸ ❡♥❞❀
✶✹ ✴
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✼❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✷✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡❧s❡
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦✬✮❀
✶✵
❡♥❞ ✐❢❀
✶✶
✲✲
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✸ ❡♥❞❀
88
Casa do Código
Capítulo 8. Estruturas de condição: if
✶✹ ✴
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
8.3 Estruturas do comando if-elsif(-else)-end
if
❙◗▲❃ ❜❡❣✐♥
✷
✲✲
✸
✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✹
❁✐♥str✉çõ❡s❃
❡❧s✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✺
✻
❁✐♥str✉çõ❡s❃
✼
❡♥❞ ✐❢❀
✽ ❡♥❞❀
✾
❙◗▲❃
❙◗▲❃ ❜❡❣✐♥
✷
✲✲
✸
✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✹
❁✐♥str✉çõ❡s❃
❡❧s✐❢ ❁❝♦♥❞✐❝❛♦❃ t❤❡♥
✺
✻
❁✐♥str✉çõ❡s❃
❡❧s❡
✼
✽
❁✐♥str✉çõ❡s❃
✾
❡♥❞ ✐❢❀
✶✵ ❡♥❞❀
✶✶
❙◗▲❃
Esta estrutura permite testar mais de uma condição dentro de uma estrutura if. Além do if e else podemos ter o elsif. Podemos ter uma
89
8.3. Estruturas do comando if-elsif(-else)-end if
Casa do Código
estrutura if com vários elsif, dependendo da necessidade e quantidade
de condições que precisarmos testar. A seguir, um exemplo:
Entrando na primeira condição:
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✶✵❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✺✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦✬✮❀
✶✵
❡❧s❡
✶✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ♠❡♥♦r ③❡r♦✦✬✮❀
✶✷
❡♥❞ ✐❢❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✺ ❡♥❞❀
✶✻ ✴
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Entrando na segunda condição:
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✶✶❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✺✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦✬✮❀
✶✵
❡❧s❡
90
Casa do Código
Capítulo 8. Estruturas de condição: if
✶✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ♠❡♥♦r ③❡r♦✦✬✮❀
✶✷
❡♥❞ ✐❢❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✺ ❡♥❞❀
✶✻ ✴
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Entrando na terceira condição:
❙◗▲❃ ❞❡❝❧❛r❡
✷
① ♥✉♠❜❡r ✿❂ ✲✻❀
✸
r❡s ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
r❡s ✿❂ ♠♦❞✭①✱✺✮❀
✻
✐❢ r❡s ❂ ✵ t❤❡♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ③❡r♦✦✬✮❀
✽
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ ♥ã♦ é ③❡r♦✦✬✮❀
✶✵
❡❧s❡
✶✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ♠❡♥♦r ③❡r♦✦✬✮❀
✶✷
❡♥❞ ✐❢❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✶✺ ❡♥❞❀
✶✻ ✴
❖ r❡st♦ ❞❛ ❞✐✈✐sã♦ é ♠❡♥♦r ③❡r♦✦
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✲✶
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Vimos que a estrutura de condição nos dá várias possibilidades para fazer
com que os programas tomem rumos diferentes para cada situação. Também
91
8.3. Estruturas do comando if-elsif(-else)-end if
Casa do Código
foi mencionado anteriormente que é possível montar estruturas if aninhadas, ou seja, uma estrutura if dentro de outra estrutura if, por exemplo.
Portanto, pode-se usar um aninhamento de declarações if, quando se tem a
necessidade de filtrar uma série de dados. Mas tome cuidado, pois muitos níveis de declarações if podem causar problemas no momento da depuração
do programa. O número máximo de níveis de declarações if recomendado
são quatro. Veja a seguir o exemplo da sintaxe de declarações aninhadas if:
❙◗▲❃ ❜❡❣✐♥
✷
✐❢ ❁❝♦♥❞✐çã♦❃ t❤❡♥
✸
✐❢ ❁❝♦♥❞✐çã♦❃ t❤❡♥
✹
❁✐♥str✉çõ❡s❃
✺
❡❧s❡
✻
❁✐♥str✉çõ❡s❃
✼
✐❢ ❁❝♦♥❞✐çã♦❃ t❤❡♥
✽
❁✐♥str✉çõ❡s❃
✾
❡❧s❡
✶✵
❁✐♥str✉çõ❡s❃
✶✶
❡♥❞ ✐❢❀
✶✷
❡♥❞ ✐❢❀
✶✸
❡♥❞ ✐❢❀
✶✹ ❡♥❞❀
✶✺
❙◗▲❃
Vamos ver o exemplo:
❙◗▲❃ ❞❡❝❧❛r❡
✷
①✶ ♥✉♠❜❡r
✿❂ ✶✵❀
✸
①✷ ♥✉♠❜❡r
✿❂ ✺❀
✹
♦♣ ✈❛r❝❤❛r✷✭✶✮ ✿❂ ✬✰✬❀
✺
r❡s ♥✉♠❜❡r❀
✻ ❜❡❣✐♥
✼
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
✾
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
✶✵
r❡s ✿❂ ①✶ ✯ ①✷❀
✶✶
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
92
Casa do Código
Capítulo 8. Estruturas de condição: if
✶✷
✐❢ ①✷ ❂ ✵ t❤❡♥
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
✶✹
❡❧s❡
✶✺
r❡s ✿❂ ①✶ ✴ ①✷❀
✶✻
❡♥❞ ✐❢❀
✶✼
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
✶✽
r❡s ✿❂ ①✶ ✲ ①✷❀
✶✾
✐❢ r❡s ❂ ✵ t❤❡♥
✷✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
✷✶
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
✷✸
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
✷✺
❡♥❞ ✐❢❀
✷✻
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
✷✼
r❡s ✿❂ ①✶ ✰ ①✷❀
✷✽
❡❧s❡
✷✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
✸✵
❡♥❞ ✐❢❀
✸✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✸✷ ❡♥❞❀
✸✸ ✴
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
8.4
Formatando as declarações if
Para que o código que contenha a declaração if fique mais legível e mais
fácil de entender, é necessário o emprego de algumas regras de alinhamento
tais como:
• Usando-se várias declarações if, recua-se a próxima declaração if
alguns espaços para dentro;
• Os comentários devem ficar após a declaração end if;
• Os blocos de declarações devem ficar recuados alguns espaços para
dentro, contando a partir da declaração if;
93
8.5. Evitando erros comuns no uso de if
Casa do Código
• Se uma condição for muito grande e mudar de linha, recua-se esta linha
alguns espaços para dentro;
• Deve-se colocar o else sempre abaixo da declaração if ao qual ele é
correspondente, assim como o end if do mesmo;
8.5 Evitando erros comuns no uso de if
É recomendado que se tomem algumas precauções para que não ocorram
erros nas declarações if. A tabela a seguir demonstra alguns cuidados necessários:
• Verifique se toda declaração if tem uma declaração end if correspondente, e se você digitou elsif sem o e extra (como “elseif ”).
• Não faça loops aninhados muito complexos. A complexidade dificulta
o acompanhamento e a depuração quando ocorrerem problemas ou
alterações. Avalie sua lógica para ver se uma função realiza a mesma
tarefa.
• Verifique se você colocou um espaço na declaração end if em vez de
não usar espaço ou usar um traço.
• Não se esqueça da sua pontuação. Você precisa de pontos e vírgulas depois de end if e depois de cada uma das declarações, mas não depois
da palavra-chave then.
Nota: a função mod tem o objetivo de retornar o resto da divisão
entre dois números passados por parâmetro.
Nota: caso não esteja visualizando as saída do comando
dbms_output, no SQL*Plus, execute o seguinte comando:
set
serveroutput on.
94
Capítulo 9
Comandos de repetição
Os comandos de repetição são utilizados para que possamos repetir uma determinada ação ou ações dentro de um programa quantas vezes sejam necessárias. As repetições podem ser iniciadas a partir de uma condição e sua
finalização também deve acontecer através deste critério. Em PL/SQL temos
basicamente três tipos de estruturas de repetição. São elas: loop, while
loop e for loop. Cada estrutura possui características que se adequam às
mais variadas situações, conforme as necessidades de cada desenvolvimento.
Vamos conhecer os comandos que fazem parte destas estruturas:
9.1
for loop
Usa-se o for loop para repetir diversas vezes o mesmo bloco de código,
até que a condição predefinida seja atendida e impeça a execução do looping.
Veja a seguir um exemplo de looping for:
9.1. for loop
Casa do Código
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ✐ ✐♥ ✶✳✳✶✵ ❧♦♦♣
✸
✲✲
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✺ ❳ ✬⑤⑤✐⑤⑤✬ ❂ ✬⑤⑤✭✺✯✐✮✮❀
✺
✲✲
✻
❡♥❞ ❧♦♦♣❀
✼ ❡♥❞❀
✽ ✴
✺ ❳ ✶ ❂ ✺
✺ ❳ ✷ ❂ ✶✵
✺ ❳ ✸ ❂ ✶✺
✺ ❳ ✹ ❂ ✷✵
✺ ❳ ✺ ❂ ✷✺
✺ ❳ ✻ ❂ ✸✵
✺ ❳ ✼ ❂ ✸✺
✺ ❳ ✽ ❂ ✹✵
✺ ❳ ✾ ❂ ✹✺
✺ ❳ ✶✵ ❂ ✺✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Nota: caso não esteja conseguindo visualizar resultado na tela execute o
comando:
❙◗▲❃
❙◗▲❃ s❡t s❡r✈❡r♦✉t♣✉t ♦♥
❙◗▲❃
Este programa imprime na tela a tabuada de cinco. Criamos uma estrutura for loop que repetirá o bloco PL/SQL dez vezes, começando por 1.
Cada vez que uma volta acontece, a variável i, que neste caso não necessitou
ser declarada, pois o for loop a declara dentro do seu escopo, é incrementada. Quando esta variável chegar a 10, o bloco PL/SQL será executado uma
última vez e então o comando é finalizado. Note que utilizamos a variável i
como base para nosso cálculo, e assim montamos a saída proposta.
Juntamente com o comando for podemos utilizar o comando REVERSE.
Este comando faz com que a contagem aconteça de forma contrária. Neste
96
Casa do Código
Capítulo 9. Comandos de repetição
exemplo, i receberá 10 inicialmente, e será decrementado a cada volta.
Quando i chegar a 1, o bloco PL/SQL será executado uma última vez e o
comando é finalizado. Veja o exemplo:
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ✐ ✐♥ ❘❊❱❊❘❙❊ ✶✳✳✶✵ ❧♦♦♣
✸
✲✲
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✺ ❳ ✬⑤⑤✐⑤⑤✬ ❂ ✬⑤⑤✭✺✯✐✮✮❀
✺
✲✲
✻
❡♥❞ ❧♦♦♣❀
✼ ❡♥❞❀
✽ ✴
✺ ❳ ✶✵ ❂ ✺✵
✺ ❳ ✾ ❂ ✹✺
✺ ❳ ✽ ❂ ✹✵
✺ ❳ ✼ ❂ ✸✺
✺ ❳ ✻ ❂ ✸✵
✺ ❳ ✺ ❂ ✷✺
✺ ❳ ✹ ❂ ✷✵
✺ ❳ ✸ ❂ ✶✺
✺ ❳ ✷ ❂ ✶✵
✺ ❳ ✶ ❂ ✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
O loop for também pode ser executado aninhadamente. Quando se
aninha os loops for, o loop externo é executado primeiro e posteriormente os internos.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ① ✐♥ ✺✳✳✻ ❧♦♦♣
✸
✲✲
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❚❛❜✉❛❞❛ ❞❡ ✬⑤⑤①✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬ ✬✮❀
✻
✲✲
✼
❢♦r ② ✐♥ ✶✳✳✶✵ ❧♦♦♣
✽
✲✲
97
9.1. for loop
Casa do Código
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭①⑤⑤✬ ❳ ✬⑤⑤②⑤⑤✬ ❂ ✬⑤⑤✭①✯②✮✮❀
✶✵
✲✲
✶✶
❡♥❞ ❧♦♦♣❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬ ✬✮❀
✶✹
✲✲
✶✺
❡♥❞ ❧♦♦♣❀
✶✻ ❡♥❞❀
✶✼ ✴
❚❛❜✉❛❞❛ ❞❡ ✺
✺ ❳ ✶ ❂ ✺
✺ ❳ ✷ ❂ ✶✵
✺ ❳ ✸ ❂ ✶✺
✺ ❳ ✹ ❂ ✷✵
✺ ❳ ✺ ❂ ✷✺
✺ ❳ ✻ ❂ ✸✵
✺ ❳ ✼ ❂ ✸✺
✺ ❳ ✽ ❂ ✹✵
✺ ❳ ✾ ❂ ✹✺
✺ ❳ ✶✵ ❂ ✺✵
❚❛❜✉❛❞❛ ❞❡ ✻
✻ ❳ ✶ ❂ ✻
✻ ❳ ✷ ❂ ✶✷
✻ ❳ ✸ ❂ ✶✽
✻ ❳ ✹ ❂ ✷✹
✻ ❳ ✺ ❂ ✸✵
✻ ❳ ✻ ❂ ✸✻
✻ ❳ ✼ ❂ ✹✷
✻ ❳ ✽ ❂ ✹✽
✻ ❳ ✾ ❂ ✺✹
✻ ❳ ✶✵ ❂ ✻✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo, utilizamos os for loops aninhados para mostrar na
tela os cálculos das tabuadas de 5 e 6. Pode-se utilizar o incremento de um
loop como parte da lógica de um programa, fazendo com que determinadas
98
Casa do Código
Capítulo 9. Comandos de repetição
ações só sejam executadas tendo como base esta informação. Veja o exemplo
a seguir.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r ① ✐♥ ✶✳✳✶✺ ❧♦♦♣
✸
✲✲
✹
✐❢ ♠♦❞✭①✱✷✮ ❂ ✵ t❤❡♥
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✬⑤⑤①✮❀
✻
❡♥❞ ✐❢❀
✼
✲✲
✽
❡♥❞ ❧♦♦♣❀
✾ ❡♥❞❀
✶✵ ✴
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✷
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✹
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✻
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✽
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✵
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✷
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✹
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Aqui utilizamos uma repetição onde o bloco PL/SQL será executado 15
vezes. Contudo, a impressão em tela será realizada apenas se os critérios do
comando if forem verdadeiros. Neste exemplo, estamos solicitando que o
programa imprima em tela somente os números divisíveis por 2. Note que
estamos utilizando a variável de incremento (neste caso, X) como parte da
nossa lógica.
Outra opção interessante no uso do for loop é a possibilidade de substituir os números fixos do intervalo por variáveis. Veja o mesmo exemplo
utilizando variáveis para definir o intervalo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✐♥t❡r✶ ♥✉♠❜❡r ❞❡❢❛✉❧t ✶❀
✸
✐♥t❡r✷ ♥✉♠❜❡r ❞❡❢❛✉❧t ✶✺❀
99
9.1. for loop
Casa do Código
✹ ❜❡❣✐♥
✺
❢♦r ① ✐♥ ✐♥t❡r✶✳✳✐♥t❡r✷ ❧♦♦♣
✻
✲✲
✼
✐❢ ♠♦❞✭①✱✷✮ ❂ ✵ t❤❡♥
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✬⑤⑤①✮❀
✾
❡♥❞ ✐❢❀
✶✵
✲✲
✶✶
❡♥❞ ❧♦♦♣❀
✶✷ ❡♥❞❀
✶✸ ✴
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✷
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✹
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✻
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✽
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✵
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✷
◆ú♠❡r♦ ❞✐✈✐sí✈❡❧ ♣♦r ✷✿ ✶✹
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Cuidados ao utilizar o comando for loop
• Não se esquecer de colocar um espaço em end loop;
• Não se esquecer do ponto e vírgula depois de end loop;
• Não inserir o contador do mais alto para o mais baixo ao usar reserve
ou definir o intervalo do mais alto para o mais baixo e se esquecer de
usar reserve;
• Não definir as variáveis de um loop de modo que o limite inferior
tenha um valor maior do que o limite superior;
• Não permitir que as variáveis dos limites acabem em valores null;
• Ao aninhar os loops, verifique se as declarações seguem a lógica pretendida.
100
Casa do Código
9.2
Capítulo 9. Comandos de repetição
while loop
while loop é usado para avaliar uma condição antes de uma sequência de
códigos seja executado. A diferença entre o loop while e o loop for, é
que o loop while permite a execução de código apenas se a condição for
verdadeira, e o loop for faz com que o código seja executado pelo menos
uma vez, independente da condição. Veja a seguir um exemplo do loop
while:
❙◗▲❃ ❞❡❝❧❛r❡
✷
①
♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✸
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
✹
t❛♠❴❧❛❜❡❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✺ ❜❡❣✐♥
✻
✲✲
✼
t❛♠❴❧❛❜❡❧ ✿❂ ❧❡♥❣t❤✭❧❛❜❡❧❴✈❡rt✮❀
✽
✲✲
✾
✇❤✐❧❡ ✭① ❁ t❛♠❴❧❛❜❡❧✮ ❧♦♦♣
✶✵
✲✲
✶✶
① ✿❂ ① ✰ ✶❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭s✉❜str✭❧❛❜❡❧❴✈❡rt✱①✱✶✮✮❀
✶✹
✲✲
✶✺
❡♥❞ ❧♦♦♣❀
✶✻ ❡♥❞❀
✶✼ ✴
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ ❧❛❜❡❧✿ ❈❯❘❙❖ P▲❙◗▲
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
❛♥t✐❣♦ ✸✿
♥♦✈♦ ✸✿
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬❈❯❘❙❖ P▲❙◗▲✬❀
❈
❯
❘
❙
❖
P
▲
❙
◗
▲
101
Casa do Código
9.3. loop
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note que neste exemplo não temos um número determinado de repetições. O número vai depender do tamanho da string informada através da
variável label. Este programa imprime na tela em vertical uma string informada via parâmetro. A lógica foi escrita de forma que as repetições ocorram
conforme a quantidade de caracteres existente dentro da variável. O controle
é realizado pela existência da condição contida no comando while.
9.3
loop
O loop é o comando de repetição mais simples e fácil de entender. Seu objetivo é igual aos dos demais comandos de repetição. Entretanto, possui características diferentes de funcionamento. Neste comando não é permitido
definir um intervalo de repetição, muito menos uma condição que o faça iniciar e parar sua execução. Em tese, seu funcionamento é infinito, pois ao
entrar em uma estrutura como esta não há como sair. Por isso, juntamente
com ele utilizamos o comando exit. Este comando é quem vai determinar
a finalização das repetições, impedindo que o programa entre em um loop
eterno.
Declarações exit e exit when
Quando uma declaração exit é encontrada, o loop é imediatamente
encerrado e o controle é passado para a declaração seguinte. A declaração
exit when permite que você especifique a condição requerida para sair da
execução do loop. Se o resultado da condição for verdadeiro, o loop é
encerrado, e se o resultado for falso, o looping continua.
Ao usar exit ou exit when coloque sempre esses comandos no início ou no final do bloco loop. Dessa forma você pode evitar muitos erros
lógicos.
Seguem exemplos de loop utilizando exit e exit when:
102
Casa do Código
Capítulo 9. Comandos de repetição
No exemplo a seguir utilizamos a estrutura if para criar uma condição
que possa determinar a finalização do comando. Caso a condição contida no
if seja verdadeira, chamamos o comando exit para finalizar a sequência
de repetições. Caso contrário, o comando continua sua execução.
❙◗▲❃ ❞❡❝❧❛r❡
✷
①
♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✸
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
✹
t❛♠❴❧❛❜❡❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✺ ❜❡❣✐♥
✻
✲✲
✼
t❛♠❴❧❛❜❡❧ ✿❂ ❧❡♥❣t❤✭❧❛❜❡❧❴✈❡rt✮❀
✽
✲✲
✾
❧♦♦♣
✶✵
✲✲
✶✶
① ✿❂ ① ✰ ✶❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭s✉❜str✭❧❛❜❡❧❴✈❡rt✱①✱✶✮✮❀
✶✹
✲✲
✶✺
✐❢ ① ❂ t❛♠❴❧❛❜❡❧ t❤❡♥
✶✻
❡①✐t❀
✶✼
❡♥❞ ✐❢❀
✶✽
✲✲
✶✾
❡♥❞ ❧♦♦♣❀
✷✵ ❡♥❞❀
✷✶ ✴
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ ❧❛❜❡❧✿ ❖❘❆❈▲❊ P▲❙◗▲
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
❛♥t✐❣♦ ✸✿
♥♦✈♦ ✸✿
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬❖❘❆❈▲❊ P▲❙◗▲✬❀
❖
❘
❆
❈
▲
❊
P
▲
❙
◗
103
9.3. loop
Casa do Código
▲
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Já no exemplo a seguir utilizamos exit when, que nos permite incluir
uma condição que possa finalizar o comando. Note que com isso não precisamos utilizar estruturas auxiliares, como o if, como foi utilizado no exemplo
anterior.
❙◗▲❃ ❞❡❝❧❛r❡
✷
①
♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✸
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
✹
t❛♠❴❧❛❜❡❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✺ ❜❡❣✐♥
✻
✲✲
✼
t❛♠❴❧❛❜❡❧ ✿❂ ❧❡♥❣t❤✭❧❛❜❡❧❴✈❡rt✮❀
✽
✲✲
✾
❧♦♦♣
✶✵
✲✲
✶✶
① ✿❂ ① ✰ ✶❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭s✉❜str✭❧❛❜❡❧❴✈❡rt✱①✱✶✮✮❀
✶✹
✲✲
✶✺
❡①✐t ✇❤❡♥ ① ❂ t❛♠❴❧❛❜❡❧❀
✶✻
✲✲
✶✼
❡♥❞ ❧♦♦♣❀
✶✽ ❡♥❞❀
✶✾ ✴
■♥❢♦r♠❡ ♦ ✈❛❧♦r ♣❛r❛ ❧❛❜❡❧✿ ❈❯❘❙❖ P▲❙◗▲
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬✫❧❛❜❡❧✬❀
❛♥t✐❣♦ ✸✿
♥♦✈♦ ✸✿
❧❛❜❡❧❴✈❡rt ✈❛r❝❤❛r✷✭✷✹✵✮ ❞❡❢❛✉❧t ✬❈❯❘❙❖ P▲❙◗▲✬❀
❈
❯
❘
❙
❖
P
104
Casa do Código
Capítulo 9. Comandos de repetição
▲
❙
◗
▲
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Em outras linguagens de programação é comum encontrar o comando
repeat until (repita até). Na PL/SQL não existe este comando. Contudo,
utilizamos os comandos loop e exit when para sanar esta necessidade.
9.4 Qual loop deve-se usar?
Conforme visto até aqui, temos disponíveis três opções de loops. Mas como
saber se estamos fazendo uso do tipo correto de loop para determinada situação? A tabela a seguir ajuda a esclarecer esta dúvida.
• for: use sempre o loop for se você souber especificamente quantas vezes
o loop deve ser executado. Se tiver de codificar uma declaração exit
ou exit when em um loop for, você pode reconsiderar seu código
e usar um loop ou uma abordagem diferente.
• while: use este loop quando não há certeza se ele será executado. Embora seja possível conseguir esse resultado em um loop for usando
exit ou exit when, essa situação é mais adequada para o loop
while. O loop while é o loop mais usado porque ele fornece mais
flexibilidade.
• loop: você pode usar o loop simples se quiser criar um loop do tipo
repeat until. O loop simples é perfeito para executar essa tarefa.
Orientações sobre os loopS
A lista a seguir apresentará algumas orientações sobre os loops.
105
9.4. Qual loop deve-se usar?
Casa do Código
• Verifique ao usar um loop com uma declaração exit ou exit when
se a condição será atendida pelo menos uma vez; caso contrário, você
terá um loop infinito.
• Nunca crie um loop infinito.
• Use sempre os nomes de rótulos nos loops. Isso torna o código muito
mais fácil de acompanhar, além de lhe dar flexibilidade.
• Não use uma declaração return dentro de um loop ao usar os loops
em uma função. Embora isso funcione, essa é uma prática ruim de
programação que tem alguns resultados indesejados, e é o modo errado
de encerrar um loop.
• Use exit when em vez de exit. exit when é muito mais fácil de
acompanhar e requer menos código.
• Verifique se a pontuação dos seus loops está adequada. Selecione o
tipo de loop que vai usar com os incrementos. Você pode lidar com
qualquer tipo de incremento em qualquer loop.
• Crie variáveis de limite superior e inferior nos loops for se um dos limites puder ser alterado no futuro. Você pode atribuir esses limites
imediatamente ao seu código. Na verdade, muito provavelmente você
nem terá um limite fixo, de modo que você deve seguir este conselho
automaticamente.
106
Capítulo 10
Cursores
O cursor é um comando do PL/SQL que permite a construção de uma estrutura de repetição, ou seja, pode-se varrer uma tabela, linha por linha, coluna
por coluna através da utilização deste comando, e assim, podemos manipular
todos os dados de uma determinada tabela.
O cursor deve ser declarado no início do bloco, onde será utilizado. Depois de declará-lo, ele deve ser criado dentro da mesma estrutura. As informações contidas no cursor são baseadas nos dados pelos quais sua estrutura
foi definida. Por exemplo, se definirmos um cursor com base na tabela de empregados, será com os dados referentes aos empregados desta tabela em que
vamos trabalhar quando estivermos manipulando tal cursor. Portanto, os retornos dos dados apresentados pelo cursor provem de comandos selects
feitos em determinadas tabelas e que trazem dados de linhas e colunas específicas.
Existem dois tipos de cursores no PL/SQL, os explícitos e os implícitos. O
10.1. Cursores explícitos
Casa do Código
cursor explícito é o que definimos nos programas, e o implícito, como o nome
já diz é declarado implicitamente pelo Oracle, ou seja, quando usado o cursor
explícito, o desenvolvedor, no caso quem está escrevendo a aplicação, além de
declará-lo deve inserir comandos que especifiquem a sua inicialização e finalização, bem como a manipulação dos dados. Quando não existir um cursor
explícito associado para o comando SQL, o Oracle o cria implicitamente. Um
exemplo disto é quando temos um comando update ou delete, dentro
de uma aplicação. Embora, não seja visível explicitamente, o Oracle cria um
cursor para executar tal comando. Os cursores implícitos e explícitos podem
existir na mesma aplicação em um mesmo bloco.
Neste livro daremos ênfase nos cursores explícitos. Através deles podemos atender a situações bem específicas no desenvolvimento de nossos programas. Contudo, serão mostradas as características e o funcionamento destes dois tipos.
10.1 Cursores explícitos
Para utilizarmos um cursor explícito, algumas regras devem ser obedecidas.
Primeiramente, temos que declará-lo. Fazemos isto da mesma forma que com
as variáveis e constantes. Veja a seguir algumas formas de declaração:
❝✉rs♦r ❝✶ ✐s
s❡❧❡❝t ❡♥❛♠❡
✱❥♦❜
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
É na declaração que definimos a estrutura do cursor. Esta estrutura inicia
com a expressão cursor <nome cursor> is. O <nome cursor> segue
as mesmas regras da definição de variáveis. Com isto estamos definindo o cabeçalho do cursor, rotulando-o. Logo após a expressão is vem o comando
select que será a base do nosso cursor. Este select pode ser escrito normalmente como se fôssemos executá-lo pelo SQL*Plus, por exemplo. Os comandos select podem conter várias tabelas e colunas. Também pode ser
usada a expressão asterisco * para se referir a todas as colunas de uma ou mais
tabelas. Vale ressaltar que, quando utilizamos cursor, não é necessário usar
108
Casa do Código
Capítulo 10. Cursores
o comando into no select. Também podemos passar parâmetros para
o select através dos cursores. Isso torna nossa estrutura mais organizada
e possibilita utilizá-la para execução de diferentes critérios. Olhe o próximo
exemplo.
❝✉rs♦r ❝✶✭ ♣❞❡♣t♥♦ ♥✉♠❜❡r
✱♣❥♦❜
✈❛r❝❤❛r✷✮ ✐s
s❡❧❡❝t ❡♠♣♥♦
✱❡♥❛♠❡
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦
❛♥❞
❥♦❜
❃ ♣❥♦❜❀
O que difere nesta declaração é a definição de parâmetros. Note que, após
ser informado o nome do nosso cursor, são definidos parâmetros os quais serão utilizados dentro comando select. A definição de parâmetros é idêntica
a definição de variáveis. A única diferença é que não é necessário informar a
quantidade de caracteres para o tipo do parâmetro. Por exemplo, o parâmetro
pjob foi definido apenas como varchar2, não importando a quantidade
de caracteres. Nestes casos, o Oracle considera o máximo de caracteres que
o tipo suporta. Neste exemplo foram definidos dois parâmetros e os mesmos
foram utilizados na cláusula where do comando select.
Depois que definimos o cursor, precisamos declarar uma variável que receberá esta definição. Esta variável funcionará como um array, ou seja, ao
abrirmos o cursor os registros serão jogados para este array para trabalharmos com eles. Vejamos a declaração a seguir.
❞❡❝❧❛r❡
✲✲
❝✉rs♦r ❝✶ ✐s ✲✲ ❧✐st❛ t♦❞♦s ♦s ❡♠♣r❡❣❛❞♦s ❞♦ ❞❡♣❛rt❛♠❡♥t♦ ✸✵✳
s❡❧❡❝t ❡♥❛♠❡
✱❥♦❜
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✲✲
r✶ ❝✶✪r♦✇t②♣❡❀
✲✲
❜❡❣✐♥
109
10.1. Cursores explícitos
Casa do Código
Neste exemplo, é declarado o cursor C1 que seleciona todos os empregados do departamento 30. Depois de definido nosso cursor, foi declarada uma
variável chamada R1 que é do tipo c1%rowtype. C1 vem do nosso cursor.
Já o %rowtype, indica que nossa variável será um array de linhas vindas do
cursor. Com isto, nossa declaração está completa e já podemos usar nosso
cursor.
Quando utilizamos no select do cursor apenas uma tabela, podemos
optar por usar a própria estrutura da tabela como sendo o array para nossa
variável. Como a PL/SQL mantém uma conexão direta (chamamos de nativa)
com o banco de dados e seus objetos, ela consegue reconhecer a compatibilidade entre as duas estruturas, a do array e a do cursor. Veja o exemplo a
seguir.
❞❡❝❧❛r❡
✲✲
❝✉rs♦r ❝✶ ✐s ✲✲ ❧✐st❛ t♦❞♦s ♦s ❡♠♣r❡❣❛❞♦s ❞♦ ❞❡♣❛rt❛♠❡♥t♦ ✸✵✳
s❡❧❡❝t ✯
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✲✲
r✶ ❡♠♣✪r♦✇t②♣❡❀
✲✲
❜❡❣✐♥
Veja que neste exemplo, declaramos a nossa variável R1 do tipo EMP em
vez do tipo C1 referente ao nosso cursor. Quando informamos que R1 é do
tipo emp%rowtype, estamos dizendo que nossa variável array é do mesmo
tipo, ou melhor, terá a mesma definição baseada na estrutura da tabela EMP.
Logo, em nosso cursor, trazemos todas as colunas desta tabela. Assim sendo, o
Oracle compara a estrutura do cursor com a estrutura da tabela EMP e valida
esta definição.
Note que, neste caso, não poderíamos suprimir colunas no select do
cursor, pois na comparação entre as estruturas o Oracle acusaria uma diferença. Portanto, resumindo, os nomes, as quantidades e os tipos das colunas
devem ser iguais entre as estruturas.
110
Casa do Código
Capítulo 10. Cursores
Usando o cursor explícito
O uso de cursores basicamente envolve três passos. Abertura, recuperação e manipulação dos registros e fechamento do cursor. Segue o exemplo
mostrando o uso do cursor que declaramos anteriormente.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s ✲✲ ❧✐st❛ t♦❞♦s ♦s ❡♠♣r❡❣❛❞♦s ❞♦
❞❡♣❛rt❛♠❡♥t♦ ✸✵✳
✹
s❡❧❡❝t ❡♥❛♠❡
✺
✱❥♦❜
✻
❢r♦♠ ❡♠♣
✼
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵❀
✽
✲✲
✾
r✶ ❝✶✪r♦✇t②♣❡❀
✶✵
✲✲
✶✶ ❜❡❣✐♥
✶✷
✲✲
✶✸
♦♣❡♥ ❝✶❀
✶✹
❧♦♦♣
✶✺
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✻
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✶✼
✲✲
✶✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✶✾
✲✲
✷✵
❡♥❞ ❧♦♦♣❀
✷✶
✲✲
✷✷
❝❧♦s❡ ❝✶❀
✷✸
✲✲
✷✹ ❡♥❞❀
✷✺ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
As linhas 3 a 7 mostram a declaração do cursor visto anteriormente. Na
linha 9 está declarada a variável array R1 do tipo C1, que é nosso cursor. Na
111
10.1. Cursores explícitos
Casa do Código
linha 13 está presente o comando open c1;. Este comando abre o cursor.
Já na linha 15, temos o retorno das linhas referentes ao select através da
linha de comando fetch c1 into r1;. Em linhas gerais este comando
significa: retorne a primeira linha de registro do select. Na linha 18 temos
o comando put_line do pacote dbms_output que imprime na tela o nome
e cargo do empregado.
Note que o programa recupera estas informações através do array R1.
Note também que as mesmas colunas definidas no select do cursor agora
podem ser usadas através de R1. Para encerrar, na linha 22 temos o fechamento do cursor. Vale lembrar que estas delimitações não servem apenas para
tornar mais fácil a visualização do código, mas principalmente para demarcar
o uso dos dados vindos do cursor através do array. Por exemplo, não podemos utilizar r1.ename antes da abertura e fetch do cursor, nem após o
fechamento.
Vamos a uma observação interessante. Você deve estar se perguntando
sobre o porquê do loop presente dentro da estrutura, certo? Pois bem, anteriormente, para recuperar um registro utilizamos o comando fetch. Este comando dentro do nosso programa retornará apenas um registro, entretanto,
nosso comando select pode retornar mais de um registro. Por isso, em
conjunto com cursor precisamos sempre solicitar o retorno dos demais registros. O cursor por si só não retorna todos os registros resultante do comando
select. Por isso utilizamos uma estrutura de repetição para nos auxiliar.
Só para vocês entenderem, cada vez que abrimos um cursor o Oracle
aponta-o para o primeiro registro do select. Todavia, ele só é recuperado
quando chamamos o fetch. Este por sua vez traz apenas o primeiro registro. Para que os próximos registros sejam recuperados, temos que executar
o fetch novamente. É aí que entra a estrutura de repetição. Repetimos o
comando fetch até que não haja mais registros retornados. Para que o programa saiba quando não há mais registros para retornar, podemos utilizar a
linha de comando exit when c1%notfound. Esta linha indica quando
se deve sair da estrutura loop, ou seja, quando o cursor C1 não tiver mais
registros para retornar.
%notfound é um atributo de cursor que indica a não existência de mais
registros a serem lidos dentro de um cursor. Mais adiante veremos mais sobre
112
Casa do Código
Capítulo 10. Cursores
este assunto. Note que a estrutura de repetição deve obedecer às delimitações
de abertura e fechamento do cursor. A ausência de uma estrutura de repetição
não caracteriza um erro. Contudo, apenas um registro seria retornado.
No uso de cursor é mais comum vermos a estrutura do tipo loop simples,
mas podemos utilizar também as estruturas while e for loop, sendo que
este último torna a manipulação do cursor bem mais fácil, pois ele já faz alguns controles automaticamente. Mais à frente nós veremos um exemplo.
Vamos ver outro exemplo utilizando passagem de valores por parâmetro.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
✶✶
r✶ ❝✶✪r♦✇t②♣❡❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
♦♣❡♥ ❝✶✭✬❈❍■❈❆●❖✬✱✼✻✾✽✮❀
✶✻
❧♦♦♣
✶✼
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✽
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✶✾
✲✲
✷✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✶
✲✲
✷✷
❡♥❞ ❧♦♦♣❀
✷✸
✲✲
✷✹
❝❧♦s❡ ❝✶❀
✷✺
✲✲
✷✻ ❡♥❞❀
✷✼ ✴
113
10.1. Cursores explícitos
Casa do Código
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
A declaração de cursores com passagem de parâmetro, nós já havíamos
visto anteriormente. O que devemos prestar atenção é como e quando devemos passar os valores para o cursor. Observando a linha 15 do programa
anterior é possível verificar a abertura do cursor. É nesta abertura que devemos passar os valores para os parâmetros. Ao abrir o cursor, o Oracle já
leva os valores de entrada para serem utilizados dentro do select. Os valores informados devem seguir a mesma ordem definida para os parâmetros.
Uma alternativa a isso é a chamada passagem de parâmetro nomeada, onde
ao informar os valores também é informado qual parâmetro deve recebê-los.
Nestes casos, a ordem não precisa ser respeitada. Veja o mesmo programa,
agora utilizando passagem de parâmetros nomeada.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
✶✶
r✶ ❝✶✪r♦✇t②♣❡❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽
✶✻
✱♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
✶✼
❧♦♦♣
✶✽
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✾
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✷✵
✲✲
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
114
Casa do Código
Capítulo 10. Cursores
✷✷
✲✲
✷✸
❡♥❞ ❧♦♦♣❀
✷✹
✲✲
✷✺
❝❧♦s❡ ❝✶❀
✷✻
✲✲
✷✼ ❡♥❞❀
✷✽ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note as linhas 15 e 16. A passagem nomeada consiste em informar o nome
do parâmetro e o valor que ele deve receber. Deve ser informado o nome
do parâmetro seguido dos sinais =>, seguido do valor a ser passado como
parâmetro. Veja também que a ordem foi invertida com relação ao que foi
definido na declaração do cursor.
Contudo, como estamos informando qual parâmetro recebe tal valor, não
teremos problema se os parâmetros estiverem em uma ordem contrária. O
uso deste artifício é bem interessante quando temos uma grande quantidade
de parâmetros. Se a quantidade for grande corre-se o risco de colocar algum parâmetro fora da ordem correta, que certamente ocasionará um erro
na abertura do cursor ou na lógica do programa.
10.2
Cursor
FOR LOOP
Anteriormente, mencionei algo sobre o cursor com uso do for loop. Pois
bem. Conforme eu já havia falado, o uso de cursores com for loop torna o
trabalho mais cômodo, pois não precisamos nos preocupar em abrir e fechar
o cursor, nem realizar o fetch. Ele faz tudo sozinho. Para melhor entendimento vamos ver o programa a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
115
Casa do Código
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
❢r♦♠ ❡♠♣✱ ❞❡♣t
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✲✲
❜❡❣✐♥
✲✲
❢♦r r✶ ✐♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽
✱♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
É nítida a diferença entre um método e outro. Veja que eliminamos algumas linhas de código. O próprio for se encarrega de abrir o cursor, realizar
a busca dos registros, verificar quando não há mais registros e fechar o cursor. Mais um detalhe: utilizando o for loop, não é necessário declarar a
variável do tipo rowtype com base no cursor, o próprio for loop faz isto
mediante um nome informado. Veja que no exemplo, só foi preciso informar
um nome, no caso R1, após o comando for, que o resto ele se encarregou de
fazer. Assim como no uso do loop, o for também delimita uma área que
deve respeitada.
Agora você deve estar se questionando: por que usar loop se for loop
traz mais facilidade sem falar que não é necessário que se controle uma série
de coisas? Na verdade você tem razão, nada impede de você utilizar sempre
o cursor com for loop. Contudo, à medida que você for trabalhando com
cursores, vai sentir a necessidade de usar um ou outro. Por exemplo, quando
temos um cursor onde não necessariamente temos que ler todas as linhas
116
Casa do Código
Capítulo 10. Cursores
vindas do select, podemos utilizar o loop, pois neste método somos nós
que controlamos a busca das linhas.
Neste caso, é bem mais prático utilizar um loop. Vale ressaltar que com
o uso de for loop, devemos informar quando ele deve parar sua execução,
caso não for de nossa vontade que ele leia todos os registros resultantes do
select. Já com o uso do loop é o contrário, se quisermos que ele leia os
registros, devemos comandá-lo através do fetch. Quando quiser parar uma
execução for loop, utilizamos o comando exit ou exit when. Veja um
exemplo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
✶✶
✲✲
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
❢♦r r✶ ✐♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽
✶✻
✱♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮ ❧♦♦♣
✶✼
✲✲
✶✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✶✾
✲✲
✷✵
✴✯
✷✶
✐❢ r✶✳❡♥❛♠❡ ❂ ✬▼❆❘❚■◆✬ t❤❡♥
✷✷
❡①✐t❀
✷✸
❡♥❞ ✐❢❀
✷✹
✯✴
✷✺
✲✲
✷✻
❡①✐t ✇❤❡♥ r✶✳❡♥❛♠❡ ❂ ✬▼❆❘❚■◆✬❀
✷✼
✲✲
117
Casa do Código
✷✽
❡♥❞ ❧♦♦♣❀
✷✾
✲✲
✸✵ ❡♥❞❀
✸✶ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Mais à frente nós também veremos que às vezes pode ser mais performático utilizar um cursor para retornar um único registro em vez de utilizar
into. Neste caso não utilizamos estruturas de repetição.
10.3
Cursor for loop com definição interna
10.3. CURSOR FOR LOOP COM DEFINIÇÃO INTERNA
Com o uso de cursores com for loop temos disponível mais um recurso
que é a possibilidade de declararmos o comando select do cursor dentro
do próprio comando for loop. Desta forma, não precisamos declarar o
cursor no escopo de declarações, conforme visto nos exemplos anteriores, e
sim, na própria definição do for loop. O único inconveniente é que se nós
tivermos que chamar este cursor for loop várias vezes dentro do programa,
teremos o comando select escrito repetidamente em todas as aberturas.
No caso de uma alteração nele, teremos que modificar em todas as chamadas,
enquanto na declaração fora do for loop (no bloco declare) a alteração
será em um único lugar.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸ ❜❡❣✐♥
✹
✲✲
✺
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡
✻
❢r♦♠ ❡♠♣
✼
✇❤❡r❡ ❥♦❜ ❂ ✬▼❆◆❆●❊❘✬✮ ❧♦♦♣
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬●❡r❡♥t❡✿ ✬⑤⑤r✶✳❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤r✶✳❡♥❛♠❡✮❀
118
Casa do Código
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
Capítulo 10. Cursores
✲✲
❢♦r r✷ ✐♥ ✭s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ ❞♥❛♠❡
❢r♦♠ ❡♠♣✱ ❞❡♣t
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❛♥❞
♠❣r
❂ r✶✳❡♠♣♥♦✮ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬ ❙✉❜♦r❞✐♥❛❞♦✿ ✬⑤⑤r✷✳❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤r✷✳❡♥❛♠❡✮❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✬✮❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❡♥❞❀
✴
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
❙◗▲❃
10.4 Cursores implícitos
10.4. CURSORES IMPLÍCITOS
Em vias gerais quando não criamos um cursor explicito o Oracle cria um
cursor automaticamente. A este cursor se dá o nome de cursor implícito.
Implícito porque é criado, aberto, manipulado e fechado pelo próprio Oracle.
Mas como sabemos, ou melhor, como vemos o uso de tal cursor? Na verdade
não vemos, pelo menos não na sua totalidade.
O cursor implícito é criado quando dentro do nosso programa PL/SQL
utilizamos algum dos comandos: delete, update, insert ou select
into.
Quando executamos os comandos delete, insert ou update, o Oracle cria um cursor implícito, abre este cursor, executa o comando e depois o
fecha. Quando executamos um select into dentro do nosso programa,
por exemplo, o Oracle vai além e abre um cursor implicitamente e executa
vários passos e verificações adicionais. Veja os passos a seguir.
119
Casa do Código
Cursor implícito: passos realizados pelo Oracle
1) Cria um cursor implícito.
2) Realiza um primeiro fetch para retornar uma linha.
3) Realiza um segundo fetch para verificar se o comando não retorna mais
de uma linha.
4) Fecha o cursor.
Note que no caso do select into o Oracle precisa tratar determinadas
situações, pois o uso do comando select dentro dos programas PL/SQL
podem gerar exceptions. Quando não é retornada nenhuma linha uma
exception de no_data_found é disparada. Já quando várias linhas são
retornadas outra exception chamada too_many_rows precisa ser acionada
também.
Desta forma, quando se há certeza de que o select em questão vai retornar apenas uma linha, pode ser usado um cursor explícito. Neste caso,
menos passos serão utilizados, pois quem tratará estas situações somos nós
dentro do programa. Entretanto, esta forma parece ser mais trabalhosa, e com
certeza é! Contudo, quando estamos falando de performance, os ganhos podem ser bem consideráveis. É óbvio que estamos falando aqui para os casos
onde os comandos selects são complexos com muitas tabelas e grandes
quantidades de dados. Para um cursor explícito os passos ficariam assim:
Cursor explícito: passos realizados pelo programa
1) Cria um cursor implícito.
2) Realiza um primeiro fetch para retornar a linha.
3) Fecha o cursor.
Com isto, fazemos com que pelo menos um passo não seja executado.
Para um select que trabalhe com milhões de registros isso pode nos dar
um ótimo ganho de tempo de execução.
120
Casa do Código
10.5
Capítulo 10. Cursores
Atributos de cursor explícito e implícito
10.5. ATRIBUTOS DE CURSOR EXPLÍCITO E IMPLÍCITO
Nos exemplos anteriores vimos alguns atributos que auxiliam na hora de se
utilizar cursores. Estes atributos trazem informações que podem ajudar o desenvolvedor a tomar decisões e a fazer com que o programa tome certos caminhos. Estes atributos estão disponíveis tanto para cursores explícitos como
para os implícitos, com exceção do atributo %isopen que só pode ser utilizado em cursores explícitos. Estes atributos são utilizados da seguinte forma:
Quando estamos trabalhando com os cursores explícitos usamos o nome
do cursor seguido do atributo, por exemplo, c1%found. Para os cursores
implícitos, o Oracle disponibiliza o cursor “SQL” que aponta sempre para o
comando que está sendo executado no momento. Desta forma, usa-se o nome
deste cursor seguido do atributo, exemplo, sql%found. Observe que o Oracle utiliza sempre o mesmo cursor para uma ou mais execuções. Portanto, ele
deve ser utilizado sempre após a execução do comando, pois as informações
de um cursor recém-executado sobrescreverão as informações da execução
anterior. A seguir os atributos que podemos utilizar.
%found
Este atributo é utilizado para indicar se a última operação realizada pelo
fetch foi concluída com êxito ou se uma determinada linha foi alterada através de algum comando insert, update ou delete, ou se, no caso de um
select into ouve algum retorno de uma ou mais linhas. Para cursores
explícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
121
Casa do Código
✶✶
r✶ ❝✶✪r♦✇t②♣❡❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽✱ ♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
✶✻
❧♦♦♣
✶✼
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✽
✲✲
✶✾
✐❢ ❝✶✪❢♦✉♥❞ t❤❡♥
✷✵
✲✲
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✷
✲✲
✷✸
❡❧s❡
✷✹
✲✲
✷✺
❡①✐t❀
✷✻
✲✲
✷✼
❡♥❞ ✐❢❀
✷✽
❡♥❞ ❧♦♦♣❀
✷✾
✲✲
✸✵
❝❧♦s❡ ❝✶❀
✸✶
✲✲
✸✷ ❡♥❞❀
✸✸ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Para cursores implícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✹
✇❥♦❜ ❡♠♣✳❥♦❜✪t②♣❡❀
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✻
✲✲
✼ ❜❡❣✐♥
✽
✲✲
✾
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
122
Casa do Código
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
Capítulo 10. Cursores
✐♥t♦ ✇❡♥❛♠❡✱ ✇❥♦❜✱ ✇❞♥❛♠❡
❢r♦♠ ❡♠♣✱ ❞❡♣t
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❛♥❞
❞❡♣t✳❧♦❝ ❂ ✬❈❍■❈❆●❖✬
❛♥❞
❡♠♣✳♠❣r
❂ ✼✻✾✽
❛♥❞
❥♦❜
❂ ✬❈▲❊❘❑✬❀
✲✲
✐❢ ❙◗▲✪❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❖ s❡❧❡❝t r❡t♦r♥♦✉ ♦ s❡❣✉✐♥t❡ r❡❣✐str♦✿ ◆♦♠❡✿ ✬⑤⑤
✇❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤✇❥♦❜✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
%notfound
Este outro atributo mostra exatamente o contrário ao atributo %found,
pois o comando %notfound retorna sempre false se o último comando
fetch não retornar uma linha no caso de um cursor explícito, ou se o último comando de update, insert, delete não alterar nenhuma linha. O
mesmo não serve para o não retorno de uma linha em um comando select
into, pois neste caso a exception no_data_found é disparada. Para cursores explícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
123
Casa do Código
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✲✲
r✶ ❝✶✪r♦✇t②♣❡❀
✲✲
❜❡❣✐♥
✲✲
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽✱ ♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
❧♦♦♣
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✲✲
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✷
✲✲
✷✸
❡♥❞ ❧♦♦♣❀
✷✹
✲✲
✷✺
❝❧♦s❡ ❝✶❀
✷✻
✲✲
✷✼ ❡♥❞❀
✷✽ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Para cursores implícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✹
✇❥♦❜ ❡♠♣✳❥♦❜✪t②♣❡❀
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✻
✲✲
✼ ❜❡❣✐♥
✽
✲✲
✾
✉♣❞❛t❡ ❡♠♣
✶✵
s❡t
❞❡♣t♥♦ ❂ ✶✵✵
✶✶
✇❤❡r❡ ❥♦❜
❂ ✬❆◆❆▲■❙❚❆❴✶✬❀
124
Casa do Código
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
Capítulo 10. Cursores
✲✲
✐❢ ❙◗▲✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆❡♥❤✉♠ r❡❣✐str♦ ❢♦✐ ❛t✉❛❧✐③❛❞♦✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
%rowcount
Este atributo é utilizado para fazer a contagem do número de linhas lidas,
ou para linhas que foram afetadas por algum comando insert, update
ou delete, ou, por algum retorno ocasionado por um comando select
into. Vale salientar que a utilização deles segue as mesmas regras para os
tipos de cursores mencionados nos outros atributos anteriores. Para cursores
explícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
✶✶
r✶ ❝✶✪r♦✇t②♣❡❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽✱ ♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
✶✻
✲✲
125
Casa do Código
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
❧♦♦♣
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✲✲
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✸
✲✲
✷✹
❡♥❞ ❧♦♦♣❀
✷✺
✲✲
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✬✮❀
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❘❡❣✐str♦s r❡❝✉♣❡r❛❞♦s✿ ✬⑤⑤❝✶✪r♦✇❝♦✉♥t⑤⑤✬✳✬✮❀
✷✽
✲✲
✷✾
❝❧♦s❡ ❝✶❀
✸✵
✲✲
✸✶ ❡♥❞❀
✸✷ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Para cursores implícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✹
✇❥♦❜ ❡♠♣✳❥♦❜✪t②♣❡❀
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✻
✲✲
✼ ❜❡❣✐♥
✽
✲✲
✾
❞❡❧❡t❡ ❡♠♣
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✭s❡❧❡❝t ❞❡♣t♥♦
✶✶
❢r♦♠ ❞❡♣t
✶✷
✇❤❡r❡ ❞♥❛♠❡ ❂ ✬❙❆▲❊❙✬✮❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
❙◗▲✪r♦✇❝♦✉♥t⑤⑤✬ r❡❣✐str♦✭s✮ ❢♦r❛♠ ❡①❝❧✉í❞♦s✳✬✮❀
126
Casa do Código
Capítulo 10. Cursores
✶✺
✲✲
✶✻
❝♦♠♠✐t❀
✶✼
✲✲
✶✽ ❡♥❞❀
✶✾ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
%isopen
Este atributo é utilizado para verificar se um cursor está ou não aberto.
Ele estará como verdadeiro se o cursor estiver aberto, e falso se estiver fechado. Este atributo só pode ser usado em cursores explícitos. Para cursores
explícitos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷
✹
✱♣♠❣r ♥✉♠❜❡r✮ ✐s
✺
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✻
❢r♦♠ ❡♠♣✱ ❞❡♣t
✼
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✽
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✾
❛♥❞
❡♠♣✳♠❣r
❂ ♣♠❣r❀
✶✵
✲✲
✶✶
r✶ ❝✶✪r♦✇t②♣❡❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
❧♦♦♣
✶✻
✐❢ ❝✶✪✐s♦♣❡♥ t❤❡♥
✶✼
✲✲
✶✽
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✾
✲✲
✷✵
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✷✶
✲✲
✷✷
❝❧♦s❡ ❝✶❀
127
Casa do Código
✷✸
✷✹
✷✺
✷✻
✷✼
❡①✐t❀
✲✲
❡❧s❡
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡❧s❡
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❈✉rs♦r ♥ã♦ ❢♦✐ ❛❜❡rt♦✦✬✮❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❆❜r✐♥❞♦ ❝✉rs♦r✳✳✳✬✮❀
♦♣❡♥ ❝✶✭ ♣♠❣r ❂❃ ✼✻✾✽✱ ♣❞♥❛♠❡ ❂❃ ✬❈❍■❈❆●❖✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❡♥❞❀
✴
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
10.6 Cursores encadeados
10.6. CURSORES ENCADEADOS
Outro recurso dos cursores é a possibilidade de serem usados de forma encadeada, ou seja, podemos ter cursores sendo manipulados dentro de outros
cursores. Veja um exemplo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡
✺
❢r♦♠ ❡♠♣
128
Casa do Código
Capítulo 10. Cursores
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✇❤❡r❡ ❥♦❜ ❂ ✬▼❆◆❆●❊❘✬❀
✲✲
❝✉rs♦r ❝✷✭♣♠❣r ♥✉♠❜❡r✮ ✐s
s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ ❞♥❛♠❡
❢r♦♠ ❡♠♣✱ ❞❡♣t
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❛♥❞
♠❣r
❂ ♣♠❣r❀
✲✲
❜❡❣✐♥
✲✲
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬●❡r❡♥t❡✿ ✬⑤⑤r✶✳❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤r✶✳❡♥❛♠❡✮❀
✶✾
✲✲
✷✵
❢♦r r✷ ✐♥ ❝✷✭r✶✳❡♠♣♥♦✮ ❧♦♦♣
✷✶
✲✲
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬ ❙✉❜♦r❞✐♥❛❞♦✿ ✬⑤⑤r✷✳❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤r✷✳❡♥❛♠❡✮❀
✷✸
✲✲
✷✹
❡♥❞ ❧♦♦♣❀
✷✺
✲✲
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✬✮❀
✷✼
✲✲
✷✽
❡♥❞ ❧♦♦♣❀
✷✾
✲✲
✸✵ ❡♥❞❀
✸✶ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo estamos selecionando todos os empregados gerentes com
seus respectivos subordinados. O primeiro cursor C1 localiza os gerentes.
Para cada gerente encontrado é listado todos os seus subordinados pelo cursor
C2. Note que o cursor C2 recebe como parâmetro o código do gerente vindo
de C1. Para cada linha retornada de C1 são recuperadas todas as linhas de
C2. O for loop se encarrega de abrir e fechar os cursores quantas vezes for
129
Casa do Código
necessário até que a leitura de todos os registros em ambos os cursores chegue
ao fim.
10.7 Cursor com for update
10.7. CURSOR COM FOR UPDATE
Quando queremos atualizar ou excluir linhas de uma tabela, podemos fazer
isto com o auxílio de um cursor for update. Podemos criar um cursor baseado na tabela em questão e utilizar a instrução for update para garantir
que enquanto ele estiver varrendo as linhas da tabela, nenhuma outra sessão
possa estar manipulando os mesmos dados. Isso também acontece mesmo
que você não venha a atualizá-los. O simples fato de estar abrindo um cursor for update já faz com que o acesso seja exclusivo. Veja a seguir um
exemplo de cursor for update.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✽
❢♦r ✉♣❞❛t❡❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
♦♣❡♥ ❝✶✭ ♣❞♥❛♠❡ ❂❃ ✬❉❆▲▲❆❙✬✮❀
✶✹
❧♦♦♣
✶✺
✐❢ ❝✶✪✐s♦♣❡♥ t❤❡♥
✶✻
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✼
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✶✽
❝❧♦s❡ ❝✶❀
✶✾
❡①✐t❀
✷✵
❡❧s❡
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✷
❡♥❞ ✐❢❀
130
Casa do Código
Capítulo 10. Cursores
✷✸
❡❧s❡
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❈✉rs♦r ♥ã♦ ❢♦✐ ❛❜❡rt♦✦✬✮❀
✷✺
❡①✐t❀
✷✻
❡♥❞ ✐❢❀
✷✼
❡♥❞ ❧♦♦♣❀
✷✽ ❡♥❞❀
✷✾ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Utilizando for update, o Oracle realiza um lock nas linhas da tabela garantindo exclusividade para manipulá-las. Após um rollback ou
commit, as linhas voltam a ser liberadas. Este comando pode ser utilizado
de duas formas, sendo acompanhado ou não por nomes de colunas específicas. Quando temos um select com várias tabelas na cláusula from nós
podemos determinar quais, ou qual, tabelas devem ser locadas informando
suas colunas. Caso queira que todas as tabelas sejam locadas use somente
for update. Agora veja o mesmo exemplo, informando as colunas para a
locação da tabela.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❡♥❛♠❡✱ ❞♥❛♠❡❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
♦♣❡♥ ❝✶✭ ♣❞♥❛♠❡ ❂❃ ✬❉❆▲▲❆❙✬✮❀
✶✹
❧♦♦♣
✶✺
✐❢ ❝✶✪✐s♦♣❡♥ t❤❡♥
✶✻
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
131
Casa do Código
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
❝❧♦s❡ ❝✶❀
❡①✐t❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
❡♥❞ ✐❢❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❈✉rs♦r ♥ã♦ ❢♦✐ ❛❜❡rt♦✦✬✮❀
❡①✐t❀
❡♥❞ ✐❢❀
❡♥❞ ❧♦♦♣❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo estamos locando as tabelas EMP e DEPT, pois estamos
informando colunas de ambas às tabelas. Contudo, podemos locar uma única
tabela informando uma ou mais colunas que fazem parte dela. Segue um
exemplo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❡♥❛♠❡❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
♦♣❡♥ ❝✶✭ ♣❞♥❛♠❡ ❂❃ ✬❉❆▲▲❆❙✬✮❀
✶✹
❧♦♦♣
✶✺
✐❢ ❝✶✪✐s♦♣❡♥ t❤❡♥
132
Casa do Código
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
Capítulo 10. Cursores
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
❝❧♦s❡ ❝✶❀
❡①✐t❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
❡♥❞ ✐❢❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❈✉rs♦r ♥ã♦ ❢♦✐ ❛❜❡rt♦✦✬✮❀
❡①✐t❀
❡♥❞ ✐❢❀
❡♥❞ ❧♦♦♣❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Enquanto a tabela estiver em lock qualquer sessão que tentar manipular
seus dados, exceto select, não terá êxito. A sessão ficará esperando a liberação até que o programa que lockou as linhas as libere. Feito isso, qualquer
outra sessão poderá efetuar alterações.
Embora o programa que contém um cursor for update tenha exclusividade de acesso, ele só conseguirá realizar um lock caso as tabelas que
fazem parte deste lock não estejam lockadas por outras sessões. Se isso estiver ocorrendo, o programa também sofrerá uma espera até que outra sessão
libere tais tabelas.
Quando executamos alguma operação em uma determinada tabela, e a
mesma está lockada, acontece uma “espera” pelo recurso. Isso quer dizer que
sua sessão ficará tentando executar os comandos até que o recurso esteja disponível ou caso você cancele a operação.
Quando você estiver utilizando um cursor com for update e não quiser que, ao executá-lo, ele fique esperando por um recurso, por exemplo, uma
tabela que esteja sendo locada por outra sessão, use a diretriz nowait. Feito
isto, o programa não ficará em espera e será disparado uma exception in133
Casa do Código
formando que o recurso em questão está ocupado.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞♥❛♠❡ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❥♦❜✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞♥❛♠❡
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❡♥❛♠❡ ♥♦✇❛✐t❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
♦♣❡♥ ❝✶✭ ♣❞♥❛♠❡ ❂❃ ✬❉❆▲▲❆❙✬✮❀
✶✹
❧♦♦♣
✶✺
✐❢ ❝✶✪✐s♦♣❡♥ t❤❡♥
✶✻
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✼
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✶✽
❝❧♦s❡ ❝✶❀
✶✾
❡①✐t❀
✷✵
❡❧s❡
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜✮❀
✷✷
❡♥❞ ✐❢❀
✷✸
❡❧s❡
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❈✉rs♦r ♥ã♦ ❢♦✐ ❛❜❡rt♦✦✬✮❀
✷✺
❡①✐t❀
✷✻
❡♥❞ ✐❢❀
✷✼
❡♥❞ ❧♦♦♣❀
✷✽ ❡♥❞❀
✷✾ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✶✿
❖❘❆✲✵✵✵✺✹✿ ♦ r❡❝✉rs♦ ❡stá ♦❝✉♣❛❞♦ ❡ é ♦❜t✐❞♦ ❝♦♠ ♦ ◆❖❲❆■❚
❡s♣❡❝✐❢✐❝❛❞♦
❖❘❆✲✵✻✺✶✷✿ ❡♠ ❧✐♥❡ ✹
❖❘❆✲✵✻✺✶✷✿ ❡♠ ❧✐♥❡ ✶✸
134
Casa do Código
Capítulo 10. Cursores
❙◗▲❃
Com o for update para auxiliar na exclusão e atualização das linhas de
uma tabela, é possível utilizar um recurso muito poderoso que traz simplicidade e ótimos ganhos de performance. Quando você estiver executando um
comando update ou delete para atualizar linhas de uma tabela existente
no próprio cursor, use current of. Esta cláusula faz com que o Oracle utilize o rowid da linha, que é o acesso mais direto e rápido ao registro. Observe
o exemplo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❡♣t♥♦ ♥✉♠❜❡r✮ ✐s
✹
s❡❧❡❝t ✯
✺
❢r♦♠ ❡♠♣
✻
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦
✼
❢♦r ✉♣❞❛t❡ ♦❢ s❛❧ ♥♦✇❛✐t❀
✽
✲✲
✾
r✶ ❝✶✪r♦✇t②♣❡❀
✶✵
✲✲
✶✶
✇r❡❣❴❡①❝❧✉✐❞♦s ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
♦♣❡♥ ❝✶✭ ♣❞❡♣t♥♦ ❂❃ ✶✵✮❀
✶✺
❧♦♦♣
✶✻
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✼
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✶✽
✲✲
✶✾
✉♣❞❛t❡ ❡♠♣ s❡t s❛❧ ❂ s❛❧ ✰ ✶✵✵✳✵✵
✷✵
✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✷✶
✲✲
✷✷
✇r❡❣❴❡①❝❧✉✐❞♦s ✿❂ ✇r❡❣❴❡①❝❧✉✐❞♦s ✰ sq❧✪r♦✇❝♦✉♥t❀
✷✸
✲✲
✷✹
❡♥❞ ❧♦♦♣❀
✷✺
✲✲
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❡①❝❧✉✐❞♦s⑤⑤✬
r❡❣✐str♦s ❡①❝❧✉í❞♦s✦✬✮❀
135
Casa do Código
✷✼
✲✲
✷✽ ❡♥❞❀
✷✾ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note no código que, ao utilizar o comando update, não foi preciso informar uma cláusula where baseada em alguma chave da tabela, como por
exemplo, empno. Como os registros estão reservados para o programa, através do for update, podemos atualizar as linhas usando como critério a
referencia da linha do cursor. Dessa forma, o Oracle garante a integridade
dos dados. O mesmo pode ser usado para o comando delete.
Este recurso também funciona para quando estivermos usando mais de
uma tabela na cláusula from. O único ponto de observação é que não podemos deixar de definir as colunas para o for update, tão pouco definir
colunas de diferentes tabelas se quisermos utilizar o current of. Isso porque, nestes casos, o Oracle só pode trabalhar com rowids de uma única
tabela. Veja alguns exemplos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❧♦❝ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞❧♦❝
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❡♠♣✳❡♥❛♠❡✱ ❞❡♣t✳❧♦❝❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷
✇r❡❣❴❛t✉❛❴❞❡♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✸
✇r❡❣❴❡①❝❧❴❡♠♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
♦♣❡♥ ❝✶✭ ♣❞❧♦❝ ❂❃ ✬◆❊❲ ❨❖❘❑✬ ✮❀
✶✼
❧♦♦♣
136
Casa do Código
Capítulo 10. Cursores
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✲✲
✉♣❞❛t❡ ❞❡♣t s❡t ❧♦❝ ❂ ✬❋▲❖❘■❉❆✬ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✲✲
✇r❡❣❴❛t✉❛❴❞❡♣ ✿❂ ✇r❡❣❴❛t✉❛❴❞❡♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✲✲
❞❡❧❡t❡ ❡♠♣ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✲✲
✇r❡❣❴❡①❝❧❴❡♠♣ ✿❂ ✇r❡❣❴❡①❝❧❴❡♠♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❛t✉❛❴❞❡♣⑤⑤✬ r❡❣✐str♦s ❞❡
❞❡♣❛rt❛♠❡♥t♦s ❛t✉❛❧✐③❛❞♦s✦✬✮❀
✸✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❡①❝❧❴❡♠♣⑤⑤✬ r❡❣✐str♦s ❞❡
❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦✬✮❀
✸✸
✲✲
✸✹ ❡♥❞❀
✸✺ ✴
✵ r❡❣✐str♦s ❞❡ ❞❡♣❛rt❛♠❡♥t♦s ❛t✉❛❧✐③❛❞♦s✦
✵ r❡❣✐str♦s ❞❡ ❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo estamos tentando atualizar a tabela DEPT e também excluir registros da tabela EMP. Entretanto, mesmo informando uma coluna
de cada tabela no for update, e o Oracle não apresentando qualquer problema na execução, os registros não sofreram qualquer modificação. Vamos
tentar algo diferente no exemplo a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❧♦❝ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
137
Casa do Código
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞❧♦❝
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❡♠♣✳❡♥❛♠❡✱ ❞❡♣t✳❧♦❝❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷
✇r❡❣❴❛t✉❛❴❞❡♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✸
✇r❡❣❴❡①❝❧❴❡♠♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
♦♣❡♥ ❝✶✭ ♣❞❧♦❝ ❂❃ ✬◆❊❲ ❨❖❘❑✬ ✮❀
✶✼
❧♦♦♣
✶✽
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✾
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✷✵
✲✲
✷✶
❞❡❧❡t❡ ❡♠♣ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✷✷
✲✲
✷✸
✇r❡❣❴❡①❝❧❴❡♠♣ ✿❂ ✇r❡❣❴❡①❝❧❴❡♠♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✷✹
✲✲
✷✺
❡♥❞ ❧♦♦♣❀
✷✻
✲✲
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❡①❝❧❴❡♠♣⑤⑤✬ r❡❣✐str♦s ❞❡
❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦✬✮❀
✷✽
✲✲
✷✾ ❡♥❞❀
✸✵ ✴
✵ r❡❣✐str♦s ❞❡ ❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Mesmo retirando um dos comandos, o Oracle não consegue concretizar
as alterações. Portanto, o problema não está na quantidade ou distinção de
comandos dentro do bloco do cursor e, sim, na sua definição. Vamos deixar
na cláusula for update somente a coluna referente à tabela EMP.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❧♦❝ ✈❛r❝❤❛r✷✮ ✐s
138
Casa do Código
Capítulo 10. Cursores
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡
❢r♦♠ ❡♠♣✱ ❞❡♣t
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞❧♦❝
❢♦r ✉♣❞❛t❡ ♦❢ ❡♠♣✳❡♥❛♠❡❀
✲✲
r✶ ❝✶✪r♦✇t②♣❡❀
✲✲
✇r❡❣❴❛t✉❛❴❞❡♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✇r❡❣❴❡①❝❧❴❡♠♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✲✲
❜❡❣✐♥
♦♣❡♥ ❝✶✭ ♣❞❧♦❝ ❂❃ ✬◆❊❲ ❨❖❘❑✬ ✮❀
❧♦♦♣
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✲✲
❞❡❧❡t❡ ❡♠♣ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✲✲
✇r❡❣❴❡①❝❧❴❡♠♣ ✿❂ ✇r❡❣❴❡①❝❧❴❡♠♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✲✲
❡♥❞ ❧♦♦♣❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❡①❝❧❴❡♠♣⑤⑤✬ r❡❣✐str♦s ❞❡
❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦✬✮❀
✷✽
✲✲
✷✾ ❡♥❞❀
✸✵ ✴
✸ r❡❣✐str♦s ❞❡ ❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Agora nosso comando funcionou com êxito. Foi utilizada mais de uma
tabela na cláusula from, todavia, na cláusula for update definimos apenas
a coluna relacionada à tabela EMP. Lembre-se que nos casos onde o select
possua mais de uma tabela na cláusula from, se não relacionarmos a coluna
na cláusula for update, lockando a tabela, não poderemos utilizar a cláu139
Casa do Código
sula current of. Se isso acontecer, o Oracle dispara uma exception
gerando um erro. Nos casos onde temos apenas uma tabela na cláusula from
podemos utilizar somente for update. Veja os exemplos.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❧♦❝ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡
✺
❢r♦♠ ❡♠♣✱ ❞❡♣t
✻
✇❤❡r❡ ❡♠♣✳❞❡♣t♥♦ ❂ ❞❡♣t✳❞❡♣t♥♦
✼
❛♥❞
❞❡♣t✳❧♦❝ ❂ ♣❞❧♦❝
✽
❢♦r ✉♣❞❛t❡ ♦❢ ❞❡♣t✳❧♦❝❀
✾
✲✲
✶✵
r✶ ❝✶✪r♦✇t②♣❡❀
✶✶
✲✲
✶✷
✇r❡❣❴❛t✉❛❴❞❡♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✸
✇r❡❣❴❡①❝❧❴❡♠♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
♦♣❡♥ ❝✶✭ ♣❞❧♦❝ ❂❃ ✬◆❊❲ ❨❖❘❑✬ ✮❀
✶✼
❧♦♦♣
✶✽
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✾
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✷✵
✲✲
✷✶
❞❡❧❡t❡ ❡♠♣ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✷✷
✲✲
✷✸
✇r❡❣❴❡①❝❧❴❡♠♣ ✿❂ ✇r❡❣❴❡①❝❧❴❡♠♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✷✹
✲✲
✷✺
❡♥❞ ❧♦♦♣❀
✷✻
✲✲
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❡①❝❧❴❡♠♣⑤⑤✬ r❡❣✐str♦s ❞❡
❡♠♣r❡❣❛❞♦s ❡①❝❧✉í❞♦s✦✬✮❀
✷✽
✲✲
✷✾ ❡♥❞❀
✸✵ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✶✿
❖❘❆✲✵✶✹✶✵✿ ❘❖❲■❉ ✐♥✈á❧✐❞♦
140
Casa do Código
Capítulo 10. Cursores
❖❘❆✲✵✻✺✶✷✿ ❡♠ ❧✐♥❡ ✷✶
❙◗▲❃
Aqui tentamos utilizar current of em um delete na tabela EMP,
sendo que em nosso for update definimos uma coluna da tabela DEPT.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶✭ ♣❞❧♦❝ ✈❛r❝❤❛r✷✮ ✐s
✹
s❡❧❡❝t ❞♥❛♠❡
✺
❢r♦♠ ❞❡♣t
✻
✇❤❡r❡ ❞❡♣t✳❧♦❝ ❂ ♣❞❧♦❝
✼
❢♦r ✉♣❞❛t❡❀
✽
✲✲
✾
r✶ ❝✶✪r♦✇t②♣❡❀
✶✵
✲✲
✶✶
✇r❡❣❴❛t✉❛❴❞❡♣ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
♦♣❡♥ ❝✶✭ ♣❞❧♦❝ ❂❃ ✬◆❊❲ ❨❖❘❑✬ ✮❀
✶✺
❧♦♦♣
✶✻
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✶✼
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✶✽
✲✲
✶✾
✉♣❞❛t❡ ❞❡♣t s❡t ❧♦❝ ❂ ✬❋▲❖❘■❉❆✬ ✇❤❡r❡ ❝✉rr❡♥t ♦❢ ❝✶❀
✷✵
✲✲
✷✶
✇r❡❣❴❛t✉❛❴❞❡♣ ✿❂ ✇r❡❣❴❛t✉❛❴❞❡♣ ✰ sq❧✪r♦✇❝♦✉♥t❀
✷✷
✲✲
✷✸
❡♥❞ ❧♦♦♣❀
✷✹
✲✲
✷✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣❴❛t✉❛❴❞❡♣⑤⑤✬ r❡❣✐str♦s ❞❡
❞❡♣❛rt❛♠❡♥t♦s ❛t✉❛❧✐③❛❞♦s✦✬✮❀
✷✻
✲✲
✷✼ ❡♥❞❀
✷✽ ✴
✶ r❡❣✐str♦s ❞❡ ❞❡♣❛rt❛♠❡♥t♦s ❛t✉❛❧✐③❛❞♦s✦
141
Casa do Código
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Aqui o comando foi executado de forma correta e com sucesso. Como o
select do nosso cursor é formado apenas por uma tabela, não foi preciso
especificar colunas na cláusula for update.
142
Capítulo 11
Funções de caracteres e
operadores aritméticos
Funções de caracteres e de cálculos também podem ser usadas nas expressões
SQL. Através delas podem-se modificar os dados, tanto no que diz respeito
aos valores selecionados, como também na forma que são apresentados, por
exemplo, separar informações dentro de uma determinada String, concatenar
caracteres, definir a caixa das letras (maiúsculas, minúsculas e intercaladas)
etc.
Já os operadores aritméticos podem ser utilizados para a inserção de cálculos dentro dos comandos SQL. Cálculos estes referentes à soma, subtração,
divisão e multiplicação. Vale salientar que estas funções e operadores podem
ser utilizados em qualquer cláusula SQL exceto na cláusula from.
11.1. Funções de caracteres
Casa do Código
11.1 Funções de caracteres
• INITCAP: retorna o primeiro caractere de cada palavra em maiúscula.
• LOWER: força caracteres maiúsculos aparecerem em minúsculos.
• UPPER: força caracteres minúsculos aparecerem em maiúsculos.
• SUBSTR: extrai um trecho de uma string, começando por uma posição
inicial e a partir desta posição conta com base na quantidade solicitada.
• to_char: converte um valor numérico para uma string de caracteres.
Também é utilizada para inserir máscara em campos numéricos e de
data.
• INSTR: retorna a posição do primeiro caractere encontrado, passado
como parâmetro.
• LENGTH: traz o tamanho dos caracteres em bytes.
• RPAD: faz alinhamento à esquerda e preenche com caracteres à direita,
até uma determinada posição. Ambos os valores são passados como
parâmetro.
• LPAD: faz alinhamento à direita e preenche com caracteres à esquerda,
até uma determinada posição. Ambos os valores são passados como
parâmetro.
Seguem exemplos do uso destas funções:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇♥♦♠❡✶
✹
✇♥♦♠❡✷
✺
✇♥♦♠❡✸
✻
✲✲
✼ ❜❡❣✐♥
✽
✲✲
✾
✇♥♦♠❡✶
✶✵
✇♥♦♠❡✷
144
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ✬❛♥❛❧✐st❛ ❞❡ s✐st❡♠❛s✬❀
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ✬P❊❉❘❊■❘❖✬❀
✈❛r❝❤❛r✷✭✶✵✵✮ ❞❡❢❛✉❧t ✬♣❛❞❡✐r♦✬❀
✿❂ ✐♥✐t❝❛♣✭✇♥♦♠❡✶✮❀
✿❂ ❧♦✇❡r✭✇♥♦♠❡✷✮❀
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
✶✶
✇♥♦♠❡✸ ✿❂ ✉♣♣❡r✭✇♥♦♠❡✸✮❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇♥♦♠❡✶✮❀
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇♥♦♠❡✷✮❀
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇♥♦♠❡✸✮❀
✶✻
✲✲
✶✼ ❡♥❞❀
✶✽ ✴
❆♥❛❧✐st❛ ❉❡ ❙✐st❡♠❛s
♣❡❞r❡✐r♦
P❆❉❊■❘❖
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções initcap, lower e upper.
Note que os valores iniciais das variáveis wnome1, wnome2 e wnome3 são
alterados conforme a ação de cada função.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ r❡❣✐♦♥s❀
❘❊●■❖◆❴■❉
✲✲✲✲✲✲✲✲✲
✶
✷
✸
✹
❘❊●■❖◆❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❊✉r♦♣❡
❆♠❡r✐❝❛s
❆s✐❛
▼✐❞❞❧❡ ❊❛st ❛♥❞ ❆❢r✐❝❛
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡❣✐♦♥❴♥❛♠❡❴s❤♦rt ✈❛r❝❤❛r✷✭✺✵✵✮❀
✸ ❜❡❣✐♥
✹
✲✲
✺
❢♦r r✶ ✐♥ ✭s❡❧❡❝t r❡❣✐♦♥❴♥❛♠❡ ❢r♦♠ r❡❣✐♦♥s✮ ❧♦♦♣
✻
✲✲
✼
✇r❡❣✐♦♥❴♥❛♠❡❴s❤♦rt ✿❂ ✉♣♣❡r✭s✉❜str✭r✶✳r❡❣✐♦♥❴♥❛♠❡✱✶✱✷✮✮❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇r❡❣✐♦♥❴♥❛♠❡❴s❤♦rt✮❀
✶✵
✲✲
145
11.1. Funções de caracteres
Casa do Código
✶✶
❡♥❞ ❧♦♦♣❀
✶✷
✲✲
✶✸ ❡♥❞❀
✶✹ ✴
❊❯
❆▼
❆❙
▼■
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções substr e upper. O exemplo
retorna os nomes das regiões mostrando apenas parte da string referente a
estes nomes.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❛r✐♦ ✈❛r❝❤❛r✷✭✷✵✵✮❀
✸ ❜❡❣✐♥
✹
✲✲
✺
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡✱ s❛❧ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❝♦♠♠ ✐s
♥✉❧❧✮ ❧♦♦♣
✻
✲✲
✼
✇s❛❧❛r✐♦ ✿❂ ✬❘✩ ✬⑤⑤t♦❴❝❤❛r✭r✶✳s❛❧✱✬❢♠✾✾✾●✾✾✵❉✵✵✬✮❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤✇s❛❧❛r✐♦✮❀
✶✵
✲✲
✶✶
❡♥❞ ❧♦♦♣❀
✶✷
✲✲
✶✸ ❡♥❞❀
✶✹ ✴
◆♦♠❡✿ ❙▼■❚❍ ❙❛❧ár✐♦✿ ❘✩ ✽✵✵✳✵✵
◆♦♠❡✿ ❏❖◆❊❙ ❙❛❧ár✐♦✿ ❘✩ ✷✱✾✼✺✳✵✵
◆♦♠❡✿ ❇▲❆❑❊ ❙❛❧ár✐♦✿ ❘✩ ✷✱✽✺✵✳✵✵
◆♦♠❡✿ ❈▲❆❘❑ ❙❛❧ár✐♦✿ ❘✩ ✷✱✹✺✵✳✵✵
◆♦♠❡✿ ❙❈❖❚❚ ❙❛❧ár✐♦✿ ❘✩ ✸✱✵✵✵✳✵✵
◆♦♠❡✿ ❑■◆● ❙❛❧ár✐♦✿ ❘✩ ✺✱✵✵✵✳✵✵
◆♦♠❡✿ ❆❉❆▼❙ ❙❛❧ár✐♦✿ ❘✩ ✶✱✶✵✵✳✵✵
146
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
◆♦♠❡✿ ❏❆▼❊❙ ❙❛❧ár✐♦✿ ❘✩ ✾✺✵✳✵✵
◆♦♠❡✿ ❋❖❘❉ ❙❛❧ár✐♦✿ ❘✩ ✸✱✵✵✵✳✵✵
◆♦♠❡✿ ▼■▲▲❊❘ ❙❛❧ár✐♦✿ ❘✩ ✶✱✸✵✵✳✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função to_char. A função foi utilizada
para formatar os valores da coluna SAL (salários).
❙◗▲❃ ❞❡❝❧❛r❡
✷
✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
✈❛❧♦r ✿❂ ✐♥str✭✸✼✹✻✷✳✶✷✱✬✻✷✬✮❀
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬P♦s✐çã♦✿ ✬⑤⑤✈❛❧♦r✮❀
✽
✲✲
✾ ❡♥❞❀
✶✵ ✴
P♦s✐çã♦✿ ✹
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função instr.
❙◗▲❃ ❜❡❣✐♥
✷
✲✲
✸
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❢✐rst❴♥❛♠❡ ❢r♦♠ ❡♠♣❧♦②❡❡s ✇❤❡r❡
❧❡♥❣t❤✭❢✐rst❴♥❛♠❡✮ ❃ ✶✵✮ ❧♦♦♣
✹
✲✲
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❢✐rst❴♥❛♠❡✮❀
✻
✲✲
✼
❡♥❞ ❧♦♦♣❀
✽
✲✲
✾ ❡♥❞❀
✶✵ ✴
147
11.1. Funções de caracteres
Casa do Código
◆♦♠❡✿ ❈❤r✐st♦♣❤❡r
◆♦♠❡✿ ❏♦s❡ ▼❛♥✉❡❧
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função length.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❧❛st❴♥❛♠❡ ✈❛r❝❤❛r✷✭✷✵✵✮❀
✸
✇s❛❧❛r②
✈❛r❝❤❛r✷✭✺✵✮❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❧❛st❴♥❛♠❡✱ s❛❧❛r②
✼
❢r♦♠ ❡♠♣❧♦②❡❡s ✇❤❡r❡ ❞❡♣❛rt♠❡♥t❴✐❞ ❂ ✸✵✮ ❧♦♦♣
✽
✲✲
✾
✇❧❛st❴♥❛♠❡ ✿❂ r♣❛❞✭r✶✳❧❛st❴♥❛♠❡✱✶✷✱✬✰✰✰✰✬✮❀
✶✵
✇s❛❧❛r②
✿❂ ❧♣❛❞✭r✶✳s❛❧❛r②✱✼✱✬✵✬✮❀
✶✶
✲✲
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬Ú❧t✐♠♦ ◆♦♠❡✿ ✬⑤⑤✇❧❛st❴♥❛♠❡⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤✇s❛❧❛r②✮❀
✶✸
✲✲
✶✹
❡♥❞ ❧♦♦♣❀
✶✺
✲✲
✶✻ ❡♥❞❀
✶✼ ✴
Ú❧t✐♠♦ ◆♦♠❡✿ ❘❛♣❤❛❡❧②✰✰✰✰ ❙❛❧ár✐♦✿ ✵✵✶✶✵✵✵
Ú❧t✐♠♦ ◆♦♠❡✿ ❑❤♦♦✰✰✰✰✰✰✰✰ ❙❛❧ár✐♦✿ ✵✵✵✸✶✵✵
Ú❧t✐♠♦ ◆♦♠❡✿ ❇❛✐❞❛✰✰✰✰✰✰✰ ❙❛❧ár✐♦✿ ✵✵✵✷✾✵✵
Ú❧t✐♠♦ ◆♦♠❡✿ ❚♦❜✐❛s✰✰✰✰✰✰ ❙❛❧ár✐♦✿ ✵✵✵✷✽✵✵
Ú❧t✐♠♦ ◆♦♠❡✿ ❍✐♠✉r♦✰✰✰✰✰✰ ❙❛❧ár✐♦✿ ✵✵✵✷✻✵✵
Ú❧t✐♠♦ ◆♦♠❡✿ ❈♦❧♠❡♥❛r❡s✰✰ ❙❛❧ár✐♦✿ ✵✵✵✷✺✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções rpad e lpad.
148
Casa do Código
11.2
Capítulo 11. Funções de caracteres e operadores aritméticos
Funções de cálculos
• ROUND: arredonda valores com casas decimais.
• TRUNC: trunca valores com casas decimais.
• MOD: mostra o resto da divisão de dois valores.
• SQRT: retorna a raiz quadrada de um valor.
• POWER: retorna um valor elevado a outro valor.
• ABS: retorna o valor absoluto.
• CEIL: retorna o menor inteiro, maior ou igual a valor.
• FLOOR: retorna o maior inteiro, menor ou igual a valor.
• SIGN: se valor maior que 0 retornar +1. Se valor menor que 0 retornar
-1. Se valor igual a 0 retorna 0.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❝❛❧❝ ♥✉♠❜❡r❀
✸
✇❝♦♠♠
♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
❢♦r r✶ ✐♥ ✭s❡❧❡❝t s❛❧✱ ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡
❞❡♣t♥♦ ❂ ✷✵✮ ❧♦♦♣
✼
✲✲
✽
✇s❛❧❴❝❛❧❝ ✿❂ ✭r✶✳s❛❧ ✴ ✷✳✼✮❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤✇s❛❧❴❝❛❧❝✮❀
✶✶
✲✲
✶✷
❡♥❞ ❧♦♦♣❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✲✬✮❀
✶✺
✲✲
✶✻
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❝♦♠♠✱ ❡♥❛♠❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❝♦♠♠ ✐s
♥♦t ♥✉❧❧✮ ❧♦♦♣
✶✼
✲✲
149
11.2. Funções de cálculos
✶✽
✶✾
✷✵
Casa do Código
✇❝♦♠♠ ✿❂ r♦✉♥❞✭✭r✶✳❝♦♠♠ ✴ ✷✳✼✮✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❈♦♠✐ssã♦✿ ✬⑤⑤✇❝♦♠♠✮❀
✷✶
✲✲
✷✷
❡♥❞ ❧♦♦♣❀
✷✸
✲✲
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✲✬✮❀
✷✺
✲✲
✷✻
❢♦r r✶ ✐♥ ✭s❡❧❡❝t s❛❧✱ ❡♥❛♠❡
✷✼
❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❜❡t✇❡❡♥ ✼✺✵✵ ❛♥❞ ✼✼✵✵✮ ❧♦♦♣
✷✽
✲✲
✷✾
✇s❛❧❴❝❛❧❝ ✿❂ r♦✉♥❞✭✭r✶✳s❛❧ ✴ ✷✳✼✮✱✷✮❀
✸✵
✲✲
✸✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❙❛❧ár✐♦✿ ✬⑤⑤
✸✷
r✶✳s❛❧⑤⑤✬ ❙❛❧ár✐♦ ❈❛❧❝✿ ✬⑤⑤✇s❛❧❴❝❛❧❝✮❀
✸✸
✲✲
✸✹
❡♥❞ ❧♦♦♣❀
✸✺
✲✲
✸✻ ❡♥❞❀
✸✼ ✴
◆♦♠❡✿ ❙▼■❚❍ ❙❛❧ár✐♦✿ ✷✾✻✳✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻✷✾✻
◆♦♠❡✿ ❏❖◆❊❙ ❙❛❧ár✐♦✿ ✶✶✵✶✳✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✶✽✺✷
◆♦♠❡✿ ❙❈❖❚❚ ❙❛❧ár✐♦✿ ✶✶✶✶✳✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶
◆♦♠❡✿ ❆❉❆▼❙ ❙❛❧ár✐♦✿ ✹✵✼✳✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼✹✵✼
◆♦♠❡✿ ❋❖❘❉ ❙❛❧ár✐♦✿ ✶✶✶✶✳✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶✶
✲
◆♦♠❡✿ ❆▲▲❊◆ ❈♦♠✐ssã♦✿ ✶✶✶
◆♦♠❡✿ ❲❆❘❉ ❈♦♠✐ssã♦✿ ✶✽✺
◆♦♠❡✿ ▼❆❘❚■◆ ❈♦♠✐ssã♦✿ ✺✶✾
◆♦♠❡✿ ❚❯❘◆❊❘ ❈♦♠✐ssã♦✿ ✵
✲
◆♦♠❡✿ ❲❆❘❉ ❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❈❛❧❝✿ ✹✻✷✳✾✻
◆♦♠❡✿ ❏❖◆❊❙ ❙❛❧ár✐♦✿ ✷✾✼✺ ❙❛❧ár✐♦ ❈❛❧❝✿ ✶✶✵✶✳✽✺
◆♦♠❡✿ ▼❆❘❚■◆ ❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❈❛❧❝✿ ✹✻✷✳✾✻
◆♦♠❡✿ ❇▲❆❑❊ ❙❛❧ár✐♦✿ ✷✽✺✵ ❙❛❧ár✐♦ ❈❛❧❝✿ ✶✵✺✺✳✺✻
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
150
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
❙◗▲❃
Esse exemplo mostra o uso da função round. No exemplo, são mostradas
diferentes formas de chamada a esta função.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❝❛❧❝ ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❢✐rst❴♥❛♠❡✱ s❛❧❛r②✱ ❥♦❜❴✐❞
✻
❢r♦♠ ❡♠♣❧♦②❡❡s ✇❤❡r❡ ❥♦❜❴✐❞ ❂ ✬▼❑❴▼❆◆✬✮ ❧♦♦♣
✼
✲✲
✽
✇s❛❧❴❝❛❧❝ ✿❂ ✭r✶✳s❛❧❛r② ✴ ✷✳✼✮❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❢✐rst❴♥❛♠❡⑤⑤✬
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✬⑤⑤
✇s❛❧❴❝❛❧❝⑤⑤✬ ❙❛❧ár✐♦✿ ✬⑤⑤r✶✳s❛❧❛r②
✶✶
⑤⑤✬ ❏♦❜✿ ✬⑤⑤r✶✳❥♦❜❴✐❞✮❀
✶✷
✲✲
✶✸
❡♥❞ ❧♦♦♣❀
✶✹
✲✲
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✲✬✮❀
✶✻
✲✲
✶✼
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❧❛st❴♥❛♠❡✱ s❛❧❛r②✱ ❡♠❛✐❧
✶✽
❢r♦♠ ❡♠♣❧♦②❡❡s ✇❤❡r❡ ❡♠❛✐❧ ❂ ✬◆❙❆❘❈❍❆◆✬✮ ❧♦♦♣
✶✾
✲✲
✷✵
✇s❛❧❴❝❛❧❝ ✿❂ tr✉♥❝✭✭r✶✳s❛❧❛r② ✴ ✷✳✼✮✮❀
✷✶
✲✲
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❧❛st❴♥❛♠❡⑤⑤✬
❙❛❧✳ ❈❛❧❝✿ ✬⑤⑤✇s❛❧❴❝❛❧❝⑤⑤
✬ ❙❛❧✳ ✿ ✬⑤⑤r✶✳s❛❧❛r②⑤⑤✬
✷✸
❊♠❛✐❧✳ ✿ ✬⑤⑤r✶✳❡♠❛✐❧✮❀
✷✹
✲✲
✷✺
❡♥❞ ❧♦♦♣❀
✷✻
✲✲
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✲✬✮❀
✷✽
✲✲
✷✾
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❧❛st❴♥❛♠❡✱ s❛❧❛r②
✸✵
❢r♦♠ ❡♠♣❧♦②❡❡s ✇❤❡r❡ ❡♠♣❧♦②❡❡❴✐❞ ❜❡t✇❡❡♥ ✶✵✵
151
Casa do Código
11.2. Funções de cálculos
✸✶
✸✷
✸✸
✸✹
❛♥❞ ✶✵✺✮ ❧♦♦♣
✲✲
✇s❛❧❴❝❛❧❝ ✿❂ tr✉♥❝✭✭r✶✳s❛❧❛r② ✴ ✷✳✼✮✱✷✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❧❛st❴♥❛♠❡⑤⑤✬
❙❛❧✳ ❈❛❧❝✿ ✬⑤⑤✇s❛❧❴❝❛❧❝⑤⑤
✸✺
✬ ❙❛❧✳ ✿ ✬⑤⑤r✶✳s❛❧❛r②✮❀
✸✻
✲✲
✸✼
❡♥❞ ❧♦♦♣❀
✸✽
✲✲
✸✾ ❡♥❞❀
✹✵ ✴
◆♦♠❡✿ ▼✐❝❤❛❡❧ ❙❛❧ár✐♦ ❈❛❧❝✳✿
✹✽✶✹✳✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✹✽✶✺ ❙❛❧ár✐♦✿
✶✸✵✵✵ ❏♦❜✿ ▼❑❴▼❆◆
✲
◆♦♠❡✿ ❙❛r❝❤❛♥❞ ❙❛❧✳ ❈❛❧❝✿ ✶✺✺✺ ❙❛❧✳ ✿ ✹✷✵✵ ❊♠❛✐❧✳ ✿ ◆❙❆❘❈❍❆◆
✲
◆♦♠❡✿ ❑✐♥❣ ❙❛❧✳ ❈❛❧❝✿ ✽✽✽✽✳✽✽ ❙❛❧✳ ✿ ✷✹✵✵✵
◆♦♠❡✿ ❑♦❝❤❤❛r ❙❛❧✳ ❈❛❧❝✿ ✻✷✾✻✳✷✾ ❙❛❧✳ ✿ ✶✼✵✵✵
◆♦♠❡✿ ❉❡ ❍❛❛♥ ❙❛❧✳ ❈❛❧❝✿ ✻✷✾✻✳✷✾ ❙❛❧✳ ✿ ✶✼✵✵✵
◆♦♠❡✿ ❍✉♥♦❧❞ ❙❛❧✳ ❈❛❧❝✿ ✸✸✸✸✳✸✸ ❙❛❧✳ ✿ ✾✵✵✵
◆♦♠❡✿ ❊r♥st ❙❛❧✳ ❈❛❧❝✿ ✷✷✷✷✳✷✷ ❙❛❧✳ ✿ ✻✵✵✵
◆♦♠❡✿ ❆✉st✐♥ ❙❛❧✳ ❈❛❧❝✿ ✶✼✼✼✳✼✼ ❙❛❧✳ ✿ ✹✽✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função trunc. No exemplo, são mostradas
diferentes formas de chamada a esta função.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
✇r❡s ✿❂ ♠♦❞✭✶✵✱✷✮❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✼
✲✲
152
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
✽
✇r❡s ✿❂ sqrt✭✻✹✮❀
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✵
✲✲
✶✶
✇r❡s ✿❂ ♣♦✇❡r✭✽✱✷✮❀
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❘❡s✉❧t❛❞♦✿ ✵
❘❡s✉❧t❛❞♦✿ ✽
❘❡s✉❧t❛❞♦✿ ✻✹
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções mod, sqrt e power.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
✇r❡s ✿❂ ❛❜s✭✲✷✵✮❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✼
✲✲
✽
✇r❡s ✿❂ ❝❡✐❧✭✶✵✳✷✮❀
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✵
✲✲
✶✶
✇r❡s ✿❂ ❢❧♦♦r✭✶✵✳✷✮❀
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❘❡s✉❧t❛❞♦✿ ✷✵
❘❡s✉❧t❛❞♦✿ ✶✶
❘❡s✉❧t❛❞♦✿ ✶✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
153
11.3. Operadores aritméticos
Casa do Código
Nesse exemplo é mostrado o uso das funções abs, ceil e floor.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✲✲
✺
✇r❡s ✿❂ s✐❣♥✭✲✷✵✵✵✮❀
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✼
✲✲
✽
✇r❡s ✿❂ s✐❣♥✭✷✵✵✵✮❀
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✵
✲✲
✶✶
✇r❡s ✿❂ s✐❣♥✭✵✮❀
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✬⑤⑤✇r❡s✮❀
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❘❡s✉❧t❛❞♦✿ ✲✶
❘❡s✉❧t❛❞♦✿ ✶
❘❡s✉❧t❛❞♦✿ ✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função sign. No exemplo, são mostrados
diferentes parâmetros na chamada desta função.
11.3
Operadores aritméticos
• * Multiplicação
• / Divisão
• + Adição
• - Subtração
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❝❛❧❝ ♥✉♠❜❡r❀
154
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
✸ ❜❡❣✐♥
✹
✲✲
✺
❢♦r r✶ ✐♥ ✭s❡❧❡❝t s❛❧ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❝♦♠♠ ✐s ♥♦t ♥✉❧❧✮ ❧♦♦♣
✻
✲✲
✼
✇s❛❧❴❝❛❧❝ ✿❂ ✭r✶✳s❛❧✯✷✴✸✮❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙❛❧ár✐♦ ❈❛❧❝✳✿ ✬⑤⑤✇s❛❧❴❝❛❧❝⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤r✶✳s❛❧✮❀
✶✵
✲✲
✶✶
❡♥❞ ❧♦♦♣❀
✶✷
✲✲
✶✸ ❡♥❞❀
✶✹ ✴
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✶✵✻✻✳✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✻✼
❙❛❧ár✐♦✿ ✶✻✵✵
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✽✸✸✳✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸
❙❛❧ár✐♦✿ ✶✷✺✵
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✽✸✸✳✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸✸
❙❛❧ár✐♦✿ ✶✷✺✵
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✶✵✵✵ ❙❛❧ár✐♦✿ ✶✺✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções aritméticas de multiplicação e
divisão.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇s❛❧❴❝❛❧❝ ♥✉♠❜❡r❀
✹
✲✲
✺ ❜❡❣✐♥
✻
✲✲
✼
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡✱ s❛❧
✽
❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✸✵✮ ❧♦♦♣
✾
✲✲
✶✵
✇s❛❧❴❝❛❧❝ ✿❂ r♦✉♥❞✭✭r✶✳s❛❧✯✷✮✴✸✰✶✵✵✳✵✵✱✷✮❀
✶✶
✲✲
155
11.3. Operadores aritméticos
Casa do Código
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❙❛❧ár✐♦ ❈❛❧❝✳✿ ✬⑤⑤
✇s❛❧❴❝❛❧❝⑤⑤✬ ❙❛❧ár✐♦✿ ✬⑤⑤r✶✳s❛❧✮❀
✶✸
✶✹
✲✲
✶✺
❡♥❞ ❧♦♦♣❀
✶✻
✲✲
✶✼ ❡♥❞❀
✶✽ ✴
◆♦♠❡✿ ❆▲▲❊◆ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✶✶✻✻✳✻✼ ❙❛❧ár✐♦✿ ✶✻✵✵
◆♦♠❡✿ ❲❆❘❉ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✾✸✸✳✸✸ ❙❛❧ár✐♦✿ ✶✷✺✵
◆♦♠❡✿ ▼❆❘❚■◆ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✾✸✸✳✸✸ ❙❛❧ár✐♦✿ ✶✷✺✵
◆♦♠❡✿ ❇▲❆❑❊ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✷✵✵✵ ❙❛❧ár✐♦✿ ✷✽✺✵
◆♦♠❡✿ ❚❯❘◆❊❘ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✶✶✵✵ ❙❛❧ár✐♦✿ ✶✺✵✵
◆♦♠❡✿ ❏❆▼❊❙ ❙❛❧ár✐♦ ❈❛❧❝✳✿ ✼✸✸✳✸✸ ❙❛❧ár✐♦✿ ✾✺✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções aritméticas de multiplicação, divisão e soma.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❞t❴❡♠✐ss❛♦ ♥✉♠❜❡r❀
✹
✇♣r❡♠✐❛❝❛♦ ♥✉♠❜❡r❀
✺
✲✲
✻
❝✉rs♦r ❝✶ ✐s
✼
s❡❧❡❝t ❡♥❛♠❡
✽
✱❞♥❛♠❡
✾
✱❤✐r❡❞❛t❡
✶✵
✱s❛❧
✶✶
❢r♦♠ ❡♠♣ ❡
✶✷
✱❞❡♣t ❞
✶✸
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✶✹
❛♥❞
tr✉♥❝✭✭s②s❞❛t❡ ✲ ❤✐r❡❞❛t❡✮ ✴ ✸✻✺✮ ❂ ✸✵❀
✶✺
✲✲
✶✻ ❜❡❣✐♥
✶✼
✲✲
156
Casa do Código
Capítulo 11. Funções de caracteres e operadores aritméticos
✶✽
✶✾
✷✵
✷✶
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
✇❞t❴❡♠✐ss❛♦ ✿❂ tr✉♥❝✭✭s②s❞❛t❡ ✲ r✶✳❤✐r❡❞❛t❡✮ ✴ ✸✻✺✮❀
✇♣r❡♠✐❛❝❛♦ ✿❂
✭r✶✳s❛❧✴✶✵✯tr✉♥❝✭✭s②s❞❛t❡ ✲ r✶✳❤✐r❡❞❛t❡✮ ✴ ✸✻✺✮✮❀
✷✷
✲✲
✷✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❉t✳ ❊♠✐ssã♦✿ ✬⑤⑤
✇❞t❴❡♠✐ss❛♦⑤⑤✬ Pr❡♠✐❛çã♦✿
✷✹
✬⑤⑤✇♣r❡♠✐❛❝❛♦✮❀
✷✺
✲✲
✷✻
❡♥❞ ❧♦♦♣❀
✷✼
✲✲
✷✽ ❡♥❞❀
✷✾ ✴
◆♦♠❡✿ ❑■◆● ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✶✺✵✵✵
◆♦♠❡✿ ❈▲❆❘❑ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✼✸✺✵
◆♦♠❡✿ ❋❖❘❉ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✾✵✵✵
◆♦♠❡✿ ❏❖◆❊❙ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✽✾✷✺
◆♦♠❡✿ ❙▼■❚❍ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✷✹✵✵
◆♦♠❡✿ ❏❆▼❊❙ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✷✽✺✵
◆♦♠❡✿ ❚❯❘◆❊❘ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✹✺✵✵
◆♦♠❡✿ ❇▲❆❑❊ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✽✺✺✵
◆♦♠❡✿ ▼❆❘❚■◆ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✸✼✺✵
◆♦♠❡✿ ❲❆❘❉ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✸✼✺✵
◆♦♠❡✿ ❆▲▲❊◆ ❉t✳ ❊♠✐ssã♦✿ ✸✵ Pr❡♠✐❛çã♦✿ ✹✽✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso das funções aritméticas de multiplicação, divisão e subtração.
157
Capítulo 12
Funções de agregação (grupo)
As funções de agregação são responsáveis por agrupar vários valores e retornar somente um único valor para um determinado grupo. As funções de
agregação, também chamadas de funções de grupo, são especificadas no comando select de uma coluna e são seguidas pela coluna à qual se aplicam. A utilização das funções de agregação pode implicar no uso da cláusula
group by. Isso acontece porque, ao informarmos colunas com funções e colunas sem funções em um mesmo select, precisamos agrupar as colunas
que não estão sendo afetadas pelo agrupamento causado pelas funções. Veja
a ilustração:
Casa do Código
Fig. 12.1: Dados de empregados
Nesta ilustração, temos alguns empregados, departamentos e valores de
salário. Nosso objetivo aqui é tentar de alguma forma somar todos os salários
por departamento, ou seja, ver quanto de salário temos para os empregados
referentes aos departamentos RESEARCH, SALES e ACCOUNTING. Da forma
como os dados estão dispostos, não conseguimos visualizar isto, pois se tentarmos agrupar departamento, não conseguiremos, visto que o agrupamento
consiste em selecionar dados que possuem o mesmo valor e torná-lo único
para cada conjunto de dados.
Por exemplo, temos os departamentos RESEARCH, SALES e
ACCOUNTING aparecendo diversas vezes. Se agruparmos, teremos um
único registro para o departamento RESEARCH, outro para SALES, e
outro para ACCOUNTING. Entretanto, também estamos selecionando os
nomes dos empregados e, na maioria dos casos, cada um possui um nome
deferente, impossibilitando que os agrupemos. Se não conseguimos agrupar
os empregados, logo não conseguimos agrupar os departamentos. É como se
fosse uma sequência. Quando usamos funções de grupo nas colunas de um
select, temos que agrupar todas as outras, sendo através de uma função de
agregação ou sendo pelo uso do group by.
Já vimos que se nós quisermos a somatória de todos os salários por departamento não podemos selecionar os empregados, ou melhor, os nomes deles.
160
Casa do Código
Capítulo 12. Funções de agregação (grupo)
Logo, a coluna Empregado não poderá aparecer no nosso select. Caso
contrário, estaríamos incluindo também por empregados, o que nos daria um
agrupamento inútil, tendo em vista que cada nome de empregado é diferente.
Sempre quando trabalhamos com agrupamentos, temos que ter em mente
a seguinte situação: vai haver colunas que estarão sobre o efeito das funções
de agregação, por exemplo, funções de somatória ou de média, e colunas que
não estarão sobre o efeito destas funções, mas que precisarão ser agrupadas
para que juntas possam formar um conjunto de dados.
Veja a próxima ilustração:
Fig. 12.2: Dados agrupados parcialmente
Nessa outra ilustração, temos dois grupos. Um grupo formado pelas colunas Empregado e Departamento, que sofrerão a ação do group by,
e outro grupo formado apenas pela coluna Salário, que sofrerá a ação da
nossa função de agregação. Vale ressaltar que nosso objetivo aqui é agrupar
os salários por departamento.
Pois bem, como pode ser visto na ilustração, neste caso, não conseguimos montar o agrupamento. Note que na coluna de departamento é possível
161
Casa do Código
agrupar os valores, mas na coluna de empregados isso não é possível. Como a
coluna de empregados faz parte do select, ela acaba comprometendo todo
nosso agrupamento. Atenção a um detalhe – o fato de a coluna Empregado
estar sendo visualizada primeiro não quer dizer que seja a causa de não conseguirmos agrupar por departamento. A ordem das colunas não altera o resultado. Vamos retirá-la do nosso select.
Fig. 12.3: Processo de agrupamento de salários por departamento
Agora sim. Tiramos a coluna de empregados e ficamos apenas com as
colunas Departamento e Salário.
Veja como ficou nosso agrupamento:
162
Casa do Código
Capítulo 12. Funções de agregação (grupo)
Fig. 12.4: Dados agrupados - Salários x Departamento
Fazendo desta forma conseguiremos alcançar nosso objetivo. Resumindo:
• Devemos saber que para obter sucesso em nossos agrupamentos, as
colunas que não estão sendo agrupadas pelas funções de agrupamento
devem ser agrupadas pelo group by;
• Também podemos agrupar determinadas colunas, mesmo que elas não
estejam presentes na cláusula select;
• Somente vamos precisar agrupar colunas através do group by
quando desejarmos mostrar um resultado com base em outro. Exemplo: valores de salário por departamento, quantidades de empregados
por departamento e assim por diante. Se quisermos apenas saber a somatória de todos os valores de salário independente do departamento
ou de qualquer outra informação, não precisaremos utilizar o group
by;
• Funções de agregação, no geral, ignoram valores nulos;
• Para realizar o agrupamento de informações o Oracle poderá ordenar
ou não as colunas. Caso a coluna que está sobre a ação da função for
uma coluna com índice, o banco poderá utilizar este índice. Como os
163
Casa do Código
índices são ordenados, não será necessário ordenar os dados para o
agrupamento. Caso contrário, ele vai realizar a ordenação, primeiro, e
depois agrupa. Nem todas as funções permitem usar índices.
Agora vamos ver estes conceitos na prática.
Primeiramente, visualizamos o nome de todos os empregados, os nomes
dos seus departamentos e seus respectivos salários.
❙◗▲❃
✷
✸
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡✱ s❛❧
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
♦r❞❡r ❜② ❡♥❛♠❡❀
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❆❉❆▼❙
❆▲▲❊◆
❇▲❆❑❊
❈▲❆❘❑
❋❖❘❉
❏❆▼❊❙
❏❖❍◆
❏❖◆❊❙
❑■◆●
▼❆❘❚■◆
▼■▲▲❊❘
❙❈❖❚❚
❙▼■❚❍
❚❯❘◆❊❘
❲❆❘❉
❉◆❆▼❊
❙❆▲
✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲
❘❊❙❊❆❘❈❍
✶✶✵✵
❙❆▲❊❙
✶✻✵✵
❙❆▲❊❙
✷✽✺✵
❆❈❈❖❯◆❚■◆●
✷✹✺✵
❘❊❙❊❆❘❈❍
✸✵✵✵
❙❆▲❊❙
✾✺✵
❘❊❙❊❆❘❈❍
✶✵✵✵
❘❊❙❊❆❘❈❍
✷✾✼✺
❆❈❈❖❯◆❚■◆●
✺✵✵✵
❙❆▲❊❙
✶✷✺✵
❆❈❈❖❯◆❚■◆●
✶✸✵✵
❘❊❙❊❆❘❈❍
✸✵✵✵
❘❊❙❊❆❘❈❍
✽✵✵
❙❆▲❊❙
✶✺✵✵
❙❆▲❊❙
✶✷✺✵
✶✺ r♦✇s s❡❧❡❝t❡❞✳
❙◗▲❃
Através de um programa PL/SQL selecionamos os mesmos dados do
select anterior, mas agora sumarizando os salários. Note que continuamos
selecionando as colunas nome do empregado e departamento do empregado.
O objetivo do programa é mostrar a soma dos salários por departamento.
164
Casa do Código
Capítulo 12. Funções de agregação (grupo)
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡✱ s✉♠✭s❛❧✮ s♦♠❛❴s❛❧
✺
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✻
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✼
♦r❞❡r ❜② ❡♥❛♠❡❀
✽
✲✲
✾ ❜❡❣✐♥
✶✵
✲✲
✶✶
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
✶✹
r✶✳❞♥❛♠❡⑤⑤✬
❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧✮❀
✶✺
✲✲
✶✻
❡♥❞ ❧♦♦♣❀
✶✼
✲✲
✶✽ ❡♥❞❀
✶✾ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✵✾✸✼✿ ♥♦t ❛ s✐♥❣❧❡✲❣r♦✉♣ ❣r♦✉♣ ❢✉♥❝t✐♦♥
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✶✶
❙◗▲❃
Ao executar o programa, surgiu um erro que, em linhas gerais, quer dizer
que o comando select, contido no cursor, está tentando utilizar uma função de grupo, juntamente com outras colunas não agrupadas, sem utilizar a
cláusula de agrupamento. Como visto nos conceitos apresentados anteriormente, isso não é permitido. Dessa forma, devemos agrupar as colunas que
não estão associadas a funções de agrupamento. Veja a seguir como ficou.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
165
Casa do Código
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
❝✉rs♦r ❝✶ ✐s
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡✱ s✉♠✭s❛❧✮ s♦♠❛❴s❛❧
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
❣r♦✉♣ ❜② ❡♥❛♠❡✱ ❞♥❛♠❡
♦r❞❡r ❜② ❡♥❛♠❡❀
✲✲
❜❡❣✐♥
✲✲
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
r✶✳❞♥❛♠❡⑤⑤✬
✶✺
❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧✮❀
✶✻
✲✲
✶✼
❡♥❞ ❧♦♦♣❀
✶✽
✲✲
✶✾ ❡♥❞❀
✷✵ ✴
◆♦♠❡✿ ❆❉❆▼❙ ❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✶✶✵✵
◆♦♠❡✿ ❆▲▲❊◆ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✻✵✵
◆♦♠❡✿ ❇▲❆❑❊ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✷✽✺✵
◆♦♠❡✿ ❈▲❆❘❑ ❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✷✹✺✵
◆♦♠❡✿ ❋❖❘❉ ❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✸✵✵✵
◆♦♠❡✿ ❏❆▼❊❙ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✾✺✵
◆♦♠❡✿ ❏❖◆❊❙ ❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✷✾✼✺
◆♦♠❡✿ ❑■◆● ❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✺✵✵✵
◆♦♠❡✿ ▼❆❘❚■◆ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✷✺✵
◆♦♠❡✿ ▼■▲▲❊❘ ❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✶✸✵✵
◆♦♠❡✿ ❙❈❖❚❚ ❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✸✵✵✵
◆♦♠❡✿ ❙▼■❚❍ ❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✽✵✵
◆♦♠❡✿ ❚❯❘◆❊❘ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✺✵✵
◆♦♠❡✿ ❲❆❘❉ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✷✺✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
166
Casa do Código
Capítulo 12. Funções de agregação (grupo)
Feitos os agrupamentos necessários, voltamos a executar o programa. O
resultado foi apresentado logo em seguida. No entanto, veja que algo não saiu
como deveria. Os salários não foram sumarizados por departamento e, sim,
por empregado. Seria a mesma coisa que não sumarizar. Vamos alterar o
comando retirando a coluna nome do empregado do comando SQL.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞♥❛♠❡✱ s✉♠✭s❛❧✮ s♦♠❛❴s❛❧
✺
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✻
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✼
❣r♦✉♣ ❜② ❡♥❛♠❡✱ ❞♥❛♠❡
✽
♦r❞❡r ❜② ❡♥❛♠❡❀
✾
✲✲
✶✵ ❜❡❣✐♥
✶✶
✲✲
✶✷
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
✶✺
r✶✳❞♥❛♠❡⑤⑤✬ ❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧✮❀
✶✻
✲✲
✶✼
❡♥❞ ❧♦♦♣❀
✶✽
✲✲
✶✾ ❡♥❞❀
✷✵ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✶✶✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✻✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✷✽✺✵
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✷✹✺✵
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✸✵✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✾✺✵
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✷✾✼✺
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✺✵✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✷✺✵
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✶✸✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✸✵✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✽✵✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✺✵✵
167
Casa do Código
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✶✷✺✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Ao retirar a coluna, o erro persiste. Isso acontece pois não adianta retirar
apenas da seleção, mas também é necessário retirar do agrupamento. Veja
que na linha 7 ainda consta a coluna ename. Veja a seguir, como deve ficar o
select, para que o programa consiga atingir o objetivo proposto.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞♥❛♠❡✱ s✉♠✭s❛❧✮ s♦♠❛❴s❛❧
✺
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✻
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✼
❣r♦✉♣ ❜② ❞♥❛♠❡❀
✽
✲✲
✾ ❜❡❣✐♥
✶✵
✲✲
✶✶
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
✶✹
r✶✳❞♥❛♠❡⑤⑤✬ ❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧✮❀
✶✺
✲✲
✶✻
❡♥❞ ❧♦♦♣❀
✶✼
✲✲
✶✽ ❡♥❞❀
✶✾ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❙♦♠❛ ❙❛❧✳✿ ✽✼✺✵
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❙♦♠❛ ❙❛❧✳✿ ✶✵✽✼✺
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❙♦♠❛ ❙❛❧✳✿ ✾✹✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Selecionando apenas a coluna referente ao nome do departamento e su168
Casa do Código
Capítulo 12. Funções de agregação (grupo)
marizando os salários, através da função de agregação sum, temos como resultado a soma dos salários por departamento.
Segue as funções de agregação mais utilizadas:
• count: retorna a quantidade de incidências de registros.
• sum: exibe a soma dos valores dos registros.
• avg: exibe a média dos valores de uma determinada coluna.
• min: exibe o menor valor de uma coluna.
• max: retorna o maior valor de uma coluna.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❝♦✉♥t✭❡♠♣❧♦②❡❡❴✐❞✮ ❝♦♥t❴❡♠♣✱ ❝♦✉♥tr②❴♥❛♠❡
✺
❢r♦♠ ❡♠♣❧♦②❡❡s ❡
✻
✱❞❡♣❛rt♠❡♥ts ❞
✼
✱❧♦❝❛t✐♦♥s ❧
✽
✱❝♦✉♥tr✐❡s ❝
✾
✇❤❡r❡ ❡✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✶✵
❛♥❞
❞✳❧♦❝❛t✐♦♥❴✐❞ ❂ ❧✳❧♦❝❛t✐♦♥❴✐❞
✶✶
❛♥❞
❧✳❝♦✉♥tr②❴✐❞ ❂ ❝✳❝♦✉♥tr②❴✐❞
✶✷
❣r♦✉♣ ❜② ❝♦✉♥tr②❴♥❛♠❡
✶✸
♦r❞❡r ❜② ❝♦✉♥tr②❴♥❛♠❡❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
✲✲
✶✼
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✽
✲✲
✶✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✬⑤⑤
r✶✳❝♦♥t❴❡♠♣⑤⑤✬ ❈✐❞❛❞❡✿ ✬⑤⑤r✶✳❝♦✉♥tr②❴♥❛♠❡✮❀
✷✵
✷✶
✲✲
✷✷
❡♥❞ ❧♦♦♣❀
✷✸
✲✲
✷✹ ❡♥❞❀
✷✺ ✴
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✷ ❈✐❞❛❞❡✿ ❈❛♥❛❞❛
169
Casa do Código
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✶ ❈✐❞❛❞❡✿ ●❡r♠❛♥②
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✸✺ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❑✐♥❣❞♦♠
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✻✽ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s ♦❢ ❆♠❡r✐❝❛
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função: count. No exemplo, o objetivo é
selecionar a quantidade de empregados por país.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❝♦✉♥t✭✯✮ ❝♦♥t❴❡♠♣✱ ❝♦✉♥tr②❴♥❛♠❡
✺
❢r♦♠ ❡♠♣❧♦②❡❡s ❡
✻
✱❞❡♣❛rt♠❡♥ts ❞
✼
✱❧♦❝❛t✐♦♥s ❧
✽
✱❝♦✉♥tr✐❡s ❝
✾
✇❤❡r❡ ❡✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✶✵
❛♥❞
❞✳❧♦❝❛t✐♦♥❴✐❞ ❂ ❧✳❧♦❝❛t✐♦♥❴✐❞
✶✶
❛♥❞
❧✳❝♦✉♥tr②❴✐❞ ❂ ❝✳❝♦✉♥tr②❴✐❞
✶✷
❣r♦✉♣ ❜② ❝♦✉♥tr②❴♥❛♠❡
✶✸
♦r❞❡r ❜② ❝♦✉♥tr②❴♥❛♠❡❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
✲✲
✶✼
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✽
✲✲
✶✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✬⑤⑤
r✶✳❝♦♥t❴❡♠♣⑤⑤✬ ❈✐❞❛❞❡✿ ✬⑤⑤r✶✳❝♦✉♥tr②❴♥❛♠❡✮❀
✷✵
✷✶
✲✲
✷✷
❡♥❞ ❧♦♦♣❀
✷✸
✲✲
✷✹ ❡♥❞❀
✷✺ ✴
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✷ ❈✐❞❛❞❡✿ ❈❛♥❛❞❛
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✶ ❈✐❞❛❞❡✿ ●❡r♠❛♥②
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✸✺ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❑✐♥❣❞♦♠
170
Casa do Código
Capítulo 12. Funções de agregação (grupo)
◗t❞❡✳ ❊♠♣r❡❣❛❞♦s✿ ✻✽ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s ♦❢ ❆♠❡r✐❝❛
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo é quase igual ao anterior, apenas por um detalhe. Note que
como conhecemos a tabela employees e sabemos que existe apenas um registro para cada empregado, podemos usar a função count de outra forma,
utilizando asterisco ( *) no lugar da coluna employee_id.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞♥❛♠❡✱ ♠❛①✭❤✐r❡❞❛t❡✮ ❞t❴❛❞♠✐ss❛♦
✺
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✻
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✼
❣r♦✉♣ ❜② ❞♥❛♠❡
✽
♦r❞❡r ❜② ✷ ❞❡s❝❀
✾
✲✲
✶✵ ❜❡❣✐♥
✶✶
✲✲
✶✷
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
r✶✳❞♥❛♠❡⑤⑤✬ ❉t✳ ❆❞♠✐ssã♦✿ ✬⑤⑤r✶✳❞t❴❛❞♠✐ss❛♦✮❀
✶✺
✶✻
✲✲
✶✼
❡♥❞ ❧♦♦♣❀
✶✽
✲✲
✶✾ ❡♥❞❀
✷✵ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ❘❊❙❊❆❘❈❍ ❉t✳ ❆❞♠✐ssã♦✿ ✶✷✲❏❆◆✲✽✸
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ❉t✳ ❆❞♠✐ssã♦✿ ✷✸✲❏❆◆✲✽✷
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ❉t✳ ❆❞♠✐ssã♦✿ ✵✸✲❉❊❈✲✽✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função: max. No exemplo, o objetivo é
171
Casa do Código
selecionar a maior data de admissão de cada departamento.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡s ❞❛t❡❀
✸ ❜❡❣✐♥
✹
s❡❧❡❝t ♠✐♥✭❤✐r❡❴❞❛t❡✮ ❤✐r❡❴❞❛t❡❴♠✐♥ ✐♥t♦ ✇r❡s
❢r♦♠ ❡♠♣❧♦②❡❡s❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬▼❡♥♦r ❉t✳ ❊♠✐ssã♦✿ ✬⑤⑤✇r❡s✮❀
✼
✲✲
✽ ❡♥❞❀
✾ ✴
▼❡♥♦r ❉t✳ ❊♠✐ssã♦✿ ✶✼✲❏❯◆✲✽✼
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostra o uso da função: min. O objetivo é selecionar a
menor data de admissão entre todos os empregados.
Além das funções de agregação e do uso do group by, também podemos contar com o having, para nos ajudar a restringir registros com base
nos valores retornados pelas funções de agregação. O having existe pois não
podemos utilizar funções de agregação na cláusula where.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❝♦✉♥t✭❡♠♣❧♦②❡❡❴✐❞✮ ❝♦♥t❴❡♠♣✱ s✉♠✭s❛❧❛r②✮
s♦♠❛❴s❛❧❛r✐♦✱ ❞❡♣❛rt♠❡♥t❴♥❛♠❡
✺
❢r♦♠ ❡♠♣❧♦②❡❡s ❡
✻
✱❞❡♣❛rt♠❡♥ts ❞
✼
✇❤❡r❡ ❡✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✽
❤❛✈✐♥❣ ❝♦✉♥t✭❡♠♣❧♦②❡❡❴✐❞✮ ❃ ✺
✾
❣r♦✉♣ ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡
✶✵
♦r❞❡r ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
✲✲
172
Casa do Código
Capítulo 12. Funções de agregação (grupo)
✶✹
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✺
✲✲
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗t❞❡✳ ❊♠♣r❡❣❛❞♦✿ ✬⑤⑤
✶✼
r✶✳❝♦♥t❴❡♠♣⑤⑤✬ ❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧❛r✐♦⑤⑤
✬ ❉❡♣t♦✳✿ ✬⑤⑤r✶✳❞❡♣❛rt♠❡♥t❴♥❛♠❡✮❀
✶✽
✶✾
✲✲
✷✵
❡♥❞ ❧♦♦♣❀
✷✶
✲✲
✷✷ ❡♥❞❀
✷✸ ✴
◗t❞❡✳ ❊♠♣r❡❣❛❞♦✿ ✻ ❙♦♠❛ ❙❛❧✳✿ ✺✶✻✵✵ ❉❡♣t♦✳✿ ❋✐♥❛♥❝❡
◗t❞❡✳ ❊♠♣r❡❣❛❞♦✿ ✻ ❙♦♠❛ ❙❛❧✳✿ ✷✹✾✵✵ ❉❡♣t♦✳✿ P✉r❝❤❛s✐♥❣
◗t❞❡✳ ❊♠♣r❡❣❛❞♦✿ ✸✹ ❙♦♠❛ ❙❛❧✳✿ ✸✵✹✺✵✵ ❉❡♣t♦✳✿ ❙❛❧❡s
◗t❞❡✳ ❊♠♣r❡❣❛❞♦✿ ✹✺ ❙♦♠❛ ❙❛❧✳✿ ✶✺✻✹✵✵ ❉❡♣t♦✳✿ ❙❤✐♣♣✐♥❣
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, é mostrado o uso da cláusula having. O objetivo é selecionar a quantidade de empregados e a soma dos salários, agrupados por
departamento, onde a quantidade de empregados é maior que 5. Observe que
a cláusula having atua somente após o agrupamento das linhas. Por isso,
não seria possível utilizar a cláusula where, pois ela atua no momento em
que as linhas estão sendo selecionadas, ou seja, antes do agrupamento.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞❡♣❛rt♠❡♥t❴♥❛♠❡✱ s✉♠✭s❛❧❛r②✮ s♦♠❛❴s❛❧✱
❝♦✉♥tr②❴♥❛♠❡
✺
❢r♦♠ ❡♠♣❧♦②❡❡s ❡
✻
✱❞❡♣❛rt♠❡♥ts ❞
✼
✱❧♦❝❛t✐♦♥s ❧
✽
✱❝♦✉♥tr✐❡s ❝
✾
✇❤❡r❡ ❡✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✶✵
❛♥❞
❞✳❧♦❝❛t✐♦♥❴✐❞ ❂ ❧✳❧♦❝❛t✐♦♥❴✐❞
✶✶
❛♥❞
❧✳❝♦✉♥tr②❴✐❞ ❂ ❝✳❝♦✉♥tr②❴✐❞
✶✷
❤❛✈✐♥❣ s✉♠✭s❛❧❛r②✮ ❃ ✭s❡❧❡❝t ❛✈❣✭❡♠✳s❛❧❛r②✮
173
Casa do Código
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
❡♠♣❧♦②❡❡s ❡♠
✱❞❡♣❛rt♠❡♥ts ❞♠
✱❧♦❝❛t✐♦♥s ❧♠
✱❝♦✉♥tr✐❡s ❝♠
✇❤❡r❡ ❡♠✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❞♠✳❞❡♣❛rt♠❡♥t❴✐❞
❛♥❞
❞♠✳❧♦❝❛t✐♦♥❴✐❞ ❂ ❧♠✳❧♦❝❛t✐♦♥❴✐❞
❛♥❞
❧♠✳❝♦✉♥tr②❴✐❞ ❂ ❝♠✳❝♦✉♥tr②❴✐❞
❛♥❞
❝♠✳❝♦✉♥tr②❴✐❞ ❂ ❝✳❝♦✉♥tr②❴✐❞✮
❣r♦✉♣ ❜② ❝✳❝♦✉♥tr②❴✐❞
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡
✱❝♦✉♥tr②❴♥❛♠❡
♦r❞❡r ❜② ❝♦✉♥tr②❴♥❛♠❡
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
✲✲
❜❡❣✐♥
✲✲
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤
r✶✳❞❡♣❛rt♠❡♥t❴♥❛♠❡⑤⑤✬
❙♦♠❛ ❙❛❧✳✿ ✬⑤⑤r✶✳s♦♠❛❴s❛❧⑤⑤
✸✸
✬ ❈✐❞❛❞❡✿ ✬⑤⑤r✶✳❝♦✉♥tr②❴♥❛♠❡✮❀
✸✹
✲✲
✸✺
❡♥❞ ❧♦♦♣❀
✸✻
✲✲
✸✼ ❡♥❞❀
✸✽ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ▼❛r❦❡t✐♥❣ ❙♦♠❛ ❙❛❧✳✿ ✶✾✵✵✵ ❈✐❞❛❞❡✿ ❈❛♥❛❞❛
❉❡♣❛rt❛♠❡♥t♦✿ ❙❛❧❡s ❙♦♠❛ ❙❛❧✳✿ ✸✵✹✺✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❑✐♥❣❞♦♠
❉❡♣❛rt❛♠❡♥t♦✿ ❆❝❝♦✉♥t✐♥❣ ❙♦♠❛ ❙❛❧✳✿ ✷✵✸✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
❉❡♣❛rt❛♠❡♥t♦✿ ❊①❡❝✉t✐✈❡ ❙♦♠❛ ❙❛❧✳✿ ✺✽✵✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
❉❡♣❛rt❛♠❡♥t♦✿ ❋✐♥❛♥❝❡ ❙♦♠❛ ❙❛❧✳✿ ✺✶✻✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
❉❡♣❛rt❛♠❡♥t♦✿ ■❚ ❙♦♠❛ ❙❛❧✳✿ ✷✽✽✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
❉❡♣❛rt❛♠❡♥t♦✿ P✉r❝❤❛s✐♥❣ ❙♦♠❛ ❙❛❧✳✿ ✷✹✾✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
174
❢r♦♠
Casa do Código
Capítulo 12. Funções de agregação (grupo)
❉❡♣❛rt❛♠❡♥t♦✿ ❙❤✐♣♣✐♥❣ ❙♦♠❛ ❙❛❧✳✿ ✶✺✻✹✵✵ ❈✐❞❛❞❡✿ ❯♥✐t❡❞ ❙t❛t❡s
♦❢ ❆♠❡r✐❝❛
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Já nesse outro exemplo, o objetivo é selecionar a soma dos salários, agrupados por departamento e país, cuja seja maior que a média dos salários por
país.
175
Capítulo 13
Funções de data
Funções de data são utilizadas para manipularmos valores do tipo date,
como aplicar formatações para uma visualização mais refinada, ou extrair
partes de uma data, como as horas, dia do mês ou somente o ano. Seguem
algumas delas:
• add_months: adiciona meses em uma determinada data.
• months_between: retorna a quantidade de meses entre duas datas.
• next_day: procura o próximo dia após uma data informada.
• last_day: retorna o último dia do mês com base em uma data informada.
• trunc: trunca uma data passada por parâmetro. O trunc pode ser
feito por dia e mês, utilizando o parâmetro FMT (formato).
Casa do Código
• sysdate: retorna a data corrente com base no servidor do banco de
dados.
• sessiontimezone: mostra o fuso horário com base na sessão aberta
no banco de dados, mediante sua localização. Vale lembrar que os fusos
horários são calculados com base no meridiano de Greenwich.
• current_date: mostra a data corrente com base na zona de tempo
da sessão do usuário. A zona de tempo é afetada em relação ao Meridiano. Caso não haja mudanças de zona, esta função terá o mesmo valor
que sysdate. sysdate busca a hora do servidor do banco de dados; mesmo que a sessão tenha sido aberta em uma zona diferente da
qual o servidor encontra-se, ele refletirá o horário da zona onde está o
servidor. Já o current_date refletirá a zona onde foi aberta a sessão.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❞t❴❛❞♠✐ss❛♦ ❞❛t❡❀
✹
✇s❡①t❛
❞❛t❡❀
✺
✲✲
✻
❝✉rs♦r ❝✶ ✐s
✼
s❡❧❡❝t ❢✐rst❴♥❛♠❡
✽
✱❤✐r❡❴❞❛t❡
✾
❢r♦♠ ❡♠♣❧♦②❡❡s
✶✵
✇❤❡r❡ t♦❴❝❤❛r✭❤✐r❡❴❞❛t❡✱✬♠♠✬✮ ❂ t♦❴❝❤❛r✭s②s❞❛t❡✱✬♠♠✬✮
✶✶
♦r❞❡r ❜② ✷❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✻
✲✲
✶✼
✇❞t❴❛❞♠✐ss❛♦ ✿❂ t♦❴❞❛t❡✭t♦❴❝❤❛r✭
r✶✳❤✐r❡❴❞❛t❡✱✬❞❞✴♠♠✬✮⑤⑤✬✴✬⑤⑤
✶✽
t♦❴❝❤❛r✭s②s❞❛t❡✱✬rrrr✬✮✱✬❞❞✴♠♠✴rrrr✬✮❀
✶✾
✇s❡①t❛
✿❂ ♥❡①t❴❞❛②✭t♦❴❞❛t❡✭
t♦❴❝❤❛r✭r✶✳❤✐r❡❴❞❛t❡✱✬❞❞✴♠♠✬✮⑤⑤✬✴✬
✷✵
⑤⑤t♦❴❝❤❛r✭s②s❞❛t❡✱✬rrrr✬✮✱✬❞❞✴♠♠✴rrrr✬✮
✱✬❋❘■❉❆❨✬✮❀
178
Casa do Código
Capítulo 13. Funções de data
✷✶
✷✷
✷✸
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤
r✶✳❢✐rst❴♥❛♠❡⑤⑤✬
❉t✳ ❆❞♠✐ssã♦✿ ✬⑤⑤✇❞t❴❛❞♠✐ss❛♦⑤⑤
✬ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✬⑤⑤✇s❡①t❛✮❀
✷✹
✷✺
✲✲
✷✻
❡♥❞ ❧♦♦♣❀
✷✼
✲✲
✷✽ ❡♥❞❀
✷✾ ✴
◆♦♠❡✿ ❈❧❛r❛ ❉t✳ ❆❞♠✐ssã♦✿ ✶✶✲◆❖❱✲✶✶ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✶✽✲◆❖❱✲✶✶
◆♦♠❡✿ ❙❛r❛t❤ ❉t✳ ❆❞♠✐ssã♦✿ ✵✸✲◆❖❱✲✶✶ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✵✹✲◆❖❱✲✶✶
◆♦♠❡✿ ●✉② ❉t✳ ❆❞♠✐ssã♦✿ ✶✺✲◆❖❱✲✶✶ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✶✽✲◆❖❱✲✶✶
◆♦♠❡✿ ❑❡✈✐♥ ❉t✳ ❆❞♠✐ssã♦✿ ✶✻✲◆❖❱✲✶✶ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✶✽✲◆❖❱✲✶✶
◆♦♠❡✿ ❖❧✐✈❡r ❉t✳ ❆❞♠✐ssã♦✿ ✷✸✲◆❖❱✲✶✶ ❙❡①t❛ ❞❡ ❋♦❧❣❛✿ ✷✺✲◆❖❱✲✶✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo foi mostrado o uso da função next_day, onde selecionamos os empregados que têm como mês de admissão o mês corrente. Através
dessa função é calculada qual a primeira sexta-feira logo em seguida ao dia
da admissão de cada empregado. Este dia será o dia da folga dele.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❞t❴t❡r♠✐♥♦❴❡①♣
❞❛t❡❀
✹
✇qt❴♠❡s❡s❴tr❛❜❛❧❤♦ ♥✉♠❜❡r❀
✺
✲✲
✻
❝✉rs♦r ❝✶ ✐s
✼
s❡❧❡❝t ❡♥❛♠❡✱ ❞♥❛♠❡
✽
✱❤✐r❡❞❛t❡
✾
❢r♦♠ ❡♠♣ ❡✱ ❞❡♣t ❞
✶✵
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
✶✶
❛♥❞ ❛❞❞❴♠♦♥t❤s✭❤✐r❡❞❛t❡✱✸✺✵✮ ❃❂ s②s❞❛t❡❀
✶✷
✶✸
✲✲
✶✹ ❜❡❣✐♥
179
Casa do Código
✶✺
✶✻
✶✼
✶✽
✶✾
✲✲
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
✇❞t❴t❡r♠✐♥♦❴❡①♣
✿❂ ❛❞❞❴♠♦♥t❤s✭r✶✳❤✐r❡❞❛t❡✱✸✮❀
✇qt❴♠❡s❡s❴tr❛❜❛❧❤♦ ✿❂ t♦❴❝❤❛r✭♠♦♥t❤s❴❜❡t✇❡❡♥✭
s②s❞❛t❡✱r✶✳❤✐r❡❞❛t❡✮✱✬✾✾✵❉✵✵✬✮❀
✷✵
✲✲
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ✬⑤⑤
✬❉❡♣t♦✿ ✬⑤⑤r✶✳❞♥❛♠❡⑤⑤✬ ✬⑤⑤
✷✷
✷✸
✬❉t✳ ❆❞♠✐ssã♦✿ ✬⑤⑤r✶✳❤✐r❡❞❛t❡⑤⑤✬ ✬⑤⑤
✬❚ér♠✐♥♦ ❊①♣✳✿ ✬⑤⑤✇❞t❴t❡r♠✐♥♦❴❡①♣⑤⑤✬ ✬⑤⑤
✷✹
✷✺
✬◗t❞❡✳ ▼❡s❡s ❚r❛❜✳✿ ✬⑤⑤✇qt❴♠❡s❡s❴tr❛❜❛❧❤♦
✷✻
✮❀
✷✼
✲✲
✷✽
❡♥❞ ❧♦♦♣❀
✷✾
✲✲
✸✵ ❡♥❞❀
✸✶ ✴
◆♦♠❡✿ ❆❉❆▼❙ ❉❡♣t♦✿ ❘❊❙❊❆❘❈❍ ❉t✳ ❆❞♠✐ssã♦✿ ✶✷✲❏❆◆✲✽✸ ❚ér♠✐♥♦
❊①♣✳✿ ✶✷✲❆P❘✲✽✸
◗t❞❡✳ ▼❡s❡s ❚r❛❜✳✿ ✸✹✻✳✻✶
◆♦♠❡✿ ❙❈❖❚❚ ❉❡♣t♦✿ ❘❊❙❊❆❘❈❍ ❉t✳ ❆❞♠✐ssã♦✿ ✵✾✲❉❊❈✲✽✷ ❚ér♠✐♥♦
❊①♣✳✿ ✵✾✲▼❆❘✲✽✸
◗t❞❡✳ ▼❡s❡s ❚r❛❜✳✿ ✸✹✼✳✼✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo foi mostrado o uso das funções add_months e
months_between. O exemplo seleciona os empregados e suas respectivas
datas de término de experiência do cargo. Note que limitamos o número de
empregados no select, através da função add_months, para evitar o retorno de todas as linhas da tabela.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❡ss✐♦♥t✐♠❡③♦♥❡ ✈❛r❝❤❛r✭✶✵✮❀
✸
✇❝✉rr❡♥t❴❞❛t❡
❞❛t❡❀
✹
✇s②s❞❛t❡
❞❛t❡❀
180
Casa do Código
Capítulo 13. Funções de data
✺ ❜❡❣✐♥
✻
✇s❡ss✐♦♥t✐♠❡③♦♥❡ ✿❂ s❡ss✐♦♥t✐♠❡③♦♥❡❀
✼
✇❝✉rr❡♥t❴❞❛t❡
✿❂ ❝✉rr❡♥t❴❞❛t❡❀
✽
✇s②s❞❛t❡
✿❂ s②s❞❛t❡❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❋✉s♦ ❍♦rár✐♦✿ ✬⑤⑤✇s❡ss✐♦♥t✐♠❡③♦♥❡⑤⑤✬ ✬⑤⑤
✬❉❛t❛ ❈♦rr❡♥t❡✿ ✬⑤⑤✇❝✉rr❡♥t❴❞❛t❡⑤⑤✬ ✬⑤⑤
✶✶
✬❉❛t❛ ❆t✉❛❧✿ ✬⑤⑤✇s②s❞❛t❡✮❀
✶✷
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❋✉s♦ ❍♦rár✐♦✿ ✲✵✸✿✵✵ ❉❛t❛ ❈♦rr❡♥t❡✿ ✸✵✲◆❖❱✲✶✶ ❉❛t❛ ❆t✉❛❧✿
✸✵✲◆❖❱✲✶✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo foi mostrado o uso das funções sessiontimezone,
current_date e sysdate.Exibimos o fuso horário, a data corrente local e
data atual do servidor.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❧❛st ❞❛t❡❀
✹
✇r♦✉♥❞ ❞❛t❡❀
✺
✇tr✉♥❝ ❞❛t❡❀
✻
✲✲
✼
❝✉rs♦r ❝✶ ✐s
✽
s❡❧❡❝t ❡♥❛♠❡
✾
✱❤✐r❡❞❛t❡
✶✵
❢r♦♠ ❡♠♣
✶✶
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
✶✷
✲✲
✶✸ ❜❡❣✐♥
✶✹
✲✲
✶✺
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✻
✲✲
181
Casa do Código
✶✼
✇❧❛st ✿❂ ❧❛st❴❞❛②✭r✶✳❤✐r❡❞❛t❡✮❀
✶✽
✇r♦✉♥❞ ✿❂ r♦✉♥❞✭r✶✳❤✐r❡❞❛t❡✱ ✬❨❊❆❘✬✮❀
✶✾
✇tr✉♥❝ ✿❂ tr✉♥❝✭r✶✳❤✐r❡❞❛t❡✱ ✬❨❊❆❘✬✮❀
✷✵
✲✲
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ✬⑤⑤
✷✷
✬❉t✳ ❆❞♠✐ssã♦✿ ✬⑤⑤r✶✳❤✐r❡❞❛t❡⑤⑤✬ ✬⑤⑤
✷✸
✬Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿ ✬⑤⑤✇❧❛st⑤⑤✬ ✬⑤⑤
✬❆rr❡❞♦♥❞❛ ❆♥♦ ❆❞♠✐ssã♦✳✿ ✬⑤⑤✇r♦✉♥❞⑤⑤✬ ✬⑤⑤
✷✹
✬tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✬⑤⑤✇tr✉♥❝
✷✺
✷✻
✮❀
✷✼
✲✲
✷✽
❡♥❞ ❧♦♦♣❀
✷✾
✲✲
✸✵ ❡♥❞❀
✸✶ ✴
◆♦♠❡✿ ❙▼■❚❍ ❉t✳ ❆❞♠✐ssã♦✿ ✶✼✲❉❊❈✲✽✵ Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿
✸✶✲❉❊❈✲✽✵ ❆rr❡❞♦♥❞❛
❆♥♦ ❆❞♠✐ssã♦✳✿ ✵✶✲❏❆◆✲✽✶ tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✵✶✲❏❆◆✲✽✵
◆♦♠❡✿ ❏❖◆❊❙ ❉t✳ ❆❞♠✐ssã♦✿ ✵✷✲❆P❘✲✽✶ Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿
✸✵✲❆P❘✲✽✶ ❆rr❡❞♦♥❞❛
❆♥♦ ❆❞♠✐ssã♦✳✿ ✵✶✲❏❆◆✲✽✶ tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✵✶✲❏❆◆✲✽✶
◆♦♠❡✿ ❙❈❖❚❚ ❉t✳ ❆❞♠✐ssã♦✿ ✵✾✲❉❊❈✲✽✷ Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿
✸✶✲❉❊❈✲✽✷ ❆rr❡❞♦♥❞❛
❆♥♦ ❆❞♠✐ssã♦✳✿ ✵✶✲❏❆◆✲✽✸ tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✵✶✲❏❆◆✲✽✷
◆♦♠❡✿ ❆❉❆▼❙ ❉t✳ ❆❞♠✐ssã♦✿ ✶✷✲❏❆◆✲✽✸ Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿
✸✶✲❏❆◆✲✽✸ ❆rr❡❞♦♥❞❛
❆♥♦ ❆❞♠✐ssã♦✳✿ ✵✶✲❏❆◆✲✽✸ tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✵✶✲❏❆◆✲✽✸
◆♦♠❡✿ ❋❖❘❉ ❉t✳ ❆❞♠✐ssã♦✿ ✵✸✲❉❊❈✲✽✶ Ú❧t✐♠♦ ❞✐❛ ▼ês ❆❞♠✐ssã♦✿
✸✶✲❉❊❈✲✽✶ ❆rr❡❞♦♥❞❛
❆♥♦ ❆❞♠✐ssã♦✳✿ ✵✶✲❏❆◆✲✽✷ tr✉♥❝ ❆♥♦ ❆❞♠✐ssã♦✿ ✵✶✲❏❆◆✲✽✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo foi mostrado o uso das funções last_day, round e
trunc. Perceba várias formas de usar as funções para extrair ou manipular
determinadas informações, por exemplo arredondar e truncar datas.
182
Capítulo 14
Funções de conversão
Em muitos casos, precisamos converter um determinado dado de um tipo
para outro. A Oracle disponibiliza funções de conversão para este trabalho.
Essas funções, embora sejam simples de serem usadas, ajudam em muito no
momento de converter ou formatar dados provenientes dos seus comandos
SQL ou programas PL/SQL.
• to_date: converte uma string ( char ou varchar2) de caractere
para uma data;
• to_number: converte uma string ( char ou varchar2) de caractere
para um número;
• to_char: converte um número ou uma data para uma string de caractere.
14.1. to_date
Casa do Código
Cada função possui suas características e é utilizada para cumprir um objetivo diferente. O que elas possuem em comum é o número de parâmetros.
O primeiro parâmetro está relacionado ao valor que deve ser convertido, o
segundo corresponde ao formato que você deseja aplicar e, por último e opcional, o parâmetro de linguagem. Trata-se de funções muito utilizadas no dia
a dia, e é de fundamental importância conhecê-las e entender como se comportam. Além das mencionadas na lista, a Oracle disponibiliza várias outras
funções para as mais diversas situações. Contudo, essas três são as que mais
comumente utilizamos na escrita de nossos programas. Para saber mais sobre
outras funções de conversão, consulte a documentação disponível no site da
Oracle.
14.1
to_date
Esta função é bem interessante. Com um pouco de treino e criatividade, podemos realizar várias conversões que podem ajudar muito no momento de
formatar, selecionar ou criticar os dados retornados de um comando SQL.
Ela funciona basicamente da seguinte forma: você vai passar um valor caractere para função, juntamente com um formato, que deve ser compatível
com o conjunto de caracteres que você passou. Qualquer incompatibilidade,
o Oracle gera um erro de conversão.
Exemplo: to_date(‘21/05/2009’,’dd/mm’). Esta conversão vai
gerar um erro, pois você está informando dia, mês e ano, como caractere, mas
na máscara só mencionou dia e mês. Quando o Oracle vai fazer a conversão,
ele analisa o formato que você está passando como parâmetro e verifica o que
é elemento de função e o que é caractere. Neste caso, ele sabe que dd e mm são
elementos conhecidos de dia e mês, e que / é um caractere que serve como
uma espécie de separador. Depois desta identificação, ele pega cada caractere
informado e vai convertendo conforme o formato. 2=d, 1=d,/=/,0=m,5=m etc.
Mas quando ele chega à segunda / vê que não há formato para o caractere,
pois terminou no elemento m. Logo, é gerado um erro de conversão. Veja a
execução:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❛ ❞❛t❡❀
184
Casa do Código
Capítulo 14. Funções de conversão
✸ ❜❡❣✐♥
✹
✇❞❛t❛ ✿❂ t♦❴❞❛t❡✭✬✷✶✴✵✺✴✷✵✵✾✬✱✬❞❞✴♠♠✬✮❀
✺ ❡♥❞❀
✻ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✶✽✸✵✿ ❞❛t❡ ❢♦r♠❛t ♣✐❝t✉r❡ ❡♥❞s ❜❡❢♦r❡ ❝♦♥✈❡rt✐♥❣ ❡♥t✐r❡
✐♥♣✉t str✐♥❣
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
O contrário também gera outro erro:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❛ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❛ ✿❂ t♦❴❞❛t❡✭✬✷✶✴✵✺✬✱✬❞❞✴♠♠✴②②②②✬✮❀
✺ ❡♥❞❀
✻ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✶✽✹✵✿ ✐♥♣✉t ✈❛❧✉❡ ♥♦t ❧♦♥❣ ❡♥♦✉❣❤ ❢♦r ❞❛t❡ ❢♦r♠❛t
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Seguem exemplos do uso do to_date:
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡
✸
✱❤✐r❡❞❛t❡
✹
❢r♦♠ ❡♠♣
✺
✇❤❡r❡ ❤✐r❡❞❛t❡ ❃ t♦❴❞❛t❡✭✬✵✶✵✶✽✷✬✱✬❞❞♠♠rr✬✮✮ ❧♦♦♣
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤
185
14.1. to_date
Casa do Código
✽
✬ ✲ ❉❛t❛ ❞❡ ❆❞♠✐ssã♦✿ ✬⑤⑤r✶✳❤✐r❡❞❛t❡✮❀
✾
✲✲
✶✵
❡♥❞ ❧♦♦♣❀
✶✶ ❡♥❞❀
✶✷ ✴
❊♠♣r❡❣❛❞♦✿ ❙❈❖❚❚ ✲ ❉❛t❛ ❞❡ ❆❞♠✐ssã♦✿ ✵✾✲❉❊❈✲✽✷
❊♠♣r❡❣❛❞♦✿ ❆❉❆▼❙ ✲ ❉❛t❛ ❞❡ ❆❞♠✐ssã♦✿ ✶✷✲❏❆◆✲✽✸
❊♠♣r❡❣❛❞♦✿ ▼■▲▲❊❘ ✲ ❉❛t❛ ❞❡ ❆❞♠✐ssã♦✿ ✷✸✲❏❆◆✲✽✷
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo mostrou como é possível converter strings em datas válidas.
Veja que na linha 5 do programa temos a função convertendo a string 010182
para uma data utilizando o formato DDMMRR.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✷✶✳✵✺✳✷✵✵✾✬✱✬❞❞✳♠♠✳②②②②✬✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✷✶✲▼❆❨✲✵✾
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Já nesse outro exemplo, também utilizando to_date, note que na linha
4 do programa, temos a função convertendo outra string em uma data, utilizando um formato diferente.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬❆♣r✐❧ ✷✶✬✱✬♠♦♥t❤ ❞❞✬✱
186
Casa do Código
Capítulo 14. Funções de conversão
✬♥❧s❴❞❛t❡❴❧❛♥❣✉❛❣❡❂❛♠❡r✐❝❛♥✬✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✷✶✲❆P❘✲✶✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Podemos também adicionar à chamada da função aspectos referentes à
linguagem. Nesse último exemplo, estamos convertendo uma string por extenso em data, utilizando o formato americano.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬❆❜r✐❧ ✷✶✬✱✬♠♦♥t❤ ❞❞✬✱
✺
✬♥❧s❴❞❛t❡❴❧❛♥❣✉❛❣❡❂✬✬❇❘❆❩■▲■❆◆ P❖❘❚❯●❯❊❙❊✬✬✬✮❀
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✽ ❡♥❞❀
✾ ✴
❉❛t❛✿ ✷✶✲❆P❘✲✶✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Contudo, como pôde ser visto no exemplo anterior, a visualização continua sendo no formato americano, embora estejamos convertendo a string
para data utilizando o formato brasileiro. Lembre-se, conversão não necessariamente, tem a ver com a forma com que o dado será impresso na tela.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬❆❜r✐❧ ✷✶✬✱✬♠♦♥t❤ ❳❳✬✱
187
14.1. to_date
Casa do Código
✺
✬♥❧s❴❞❛t❡❴❧❛♥❣✉❛❣❡❂✬✬❇❘❆❩■▲■❆◆ P❖❘❚❯●❯❊❙❊✬✬✬✮❀
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✽ ❡♥❞❀
✾ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✶✽✷✶✿ ❞❛t❡ ❢♦r♠❛t ♥♦t r❡❝♦❣♥✐③❡❞
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Esse exemplo, mostra que devemos informar formatos válidos, ou melhor, formatos conhecidos da linguagem. Caso contrário, a conversão não é
realizada e erros ocorrerão.
A seguir, algumas limitações com relação a função to_date:
• A String a ser passada para a conversão não pode conter mais de 220
caracteres;
• Existem vários formatos de máscara disponíveis para a utilização.
Qualquer máscara diferente das permitidas pela Oracle gerará um erro
de conversão;
• Não pode haver confronto de máscaras. Exemplo: caso você queira
utilizar a máscara HH24 e também solicitar que seja mostrado AM
(indicador de antemeridiano para manhã) ou PM (indicador de pósmeridiano para noite).
• Não é permitido especificar elementos de conversão duplicados. Exemplo: ‘DD-MM-MM’. Neste caso, o formato para mês aparece duas vezes.
Veja alguns elementos de formatação que podem ser usados:
• CC: adiciona 1 aos dois primeiros dígitos do ano (YYYY).
• SCC: igual CC, prefixando datas BC com um sinal negativo.
188
Casa do Código
Capítulo 14. Funções de conversão
• YY: representa o ano com duas casas.
• YYYY: representa o ano com quatro casas.
• RR: representa os dois últimos dígitos do ano, mas obedecendo à seguinte regra: soma 1 aos dois primeiros dígitos de CC se ano for < 50
e os últimos 2 dígitos do ano corrente forem >= 50. Subtrai 1 de CC
se ano >= 50 e os últimos dois dígitos do ano corrente forem < 50.
• RRRR: representa o ano. Aceita 2 ou 4 dígitos. Se ano informado com 2
dígitos, segue as mesmas regras de RR.
• YEAR: escreve o ano por extenso.
• MM: número do mês de 01 a 12. 01 = Janeiro, 02 = Fevereiro etc.
• MONTH: nome do mês.
• MON: representa o nome do mês abreviado com três caracteres.
• DD: dia do mês de 1 a 31.
• DDD: representa o dia do ano de 1 a 366.
• DAY: representa o nome do dia por extenso.
• HH, HH12, HH24: HH e HH12, horas de 1 a 12. HH24, horas de 0 a 23.
• MI: equivale aos minutos de 0 a 59.
• SS: equivale aos segundos de 0 a 59.
• SP: converte o número para seu formato escrito. Disponível apenas
para a escrita no idioma inglês.
• SPTH: mostra os números de maneira ordinal. 1 = First, 2 = Second etc.
• FM: retira espaços em branco proveniente da ausência de caracteres em
um formato.
189
14.1. to_date
Casa do Código
Nota: estes elementos também são utilizados na conversão do tipo
date para String.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✷✵✵✽✬✱✬②②②②✬✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✵✶✲◆❖❱✲✵✽
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
A função to_date, pode converter não só strings representando datas
completas, como também strings representando partes de uma data. Esse
exemplo mostra a função realizando a conversão da string 2008 em data.
Note que, ao ser impresso o valor da variável, a qual recebeu o dado convertido, ele recebeu a atribuição da data atual, modificado apenas pelo ano
convertido.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✷✵✵✱✬❞❞❞✬✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✶✾✲❏❯▲✲✶✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
190
Casa do Código
Capítulo 14. Funções de conversão
Esse exemplo é similar ao anterior. Aqui está sendo realizada a conversão
com base na representação numérica do dia referente ao total de dias do ano.
Uso de YYYY e RRRR
Sabemos que a máscara YYYY representa os quatro dígitos do ano. Opcionalmente, pode-se utilizar YY para mostrar apenas os dois últimos dígitos.
Contudo, para corrigir problemas de compatibilidade com a virada do século,
a Oracle criou as máscaras RR e RRRR. Veja a aplicação a seguir:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ✈❛r❝❤❛r✷✭✺✵✮❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❝❤❛r✭s②s❞❛t❡✱✬❞❞✴♠♠✴②②②②✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✻
✲✲
✼
✇❞❛t❡ ✿❂ t♦❴❝❤❛r✭
t♦❴❞❛t❡✭✬✵✶✴✵✶✴✹✾✬✱✬❞❞✴♠♠✴②②✬✮✱✬❞❞✴♠♠✴②②②②✬✮❀
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✾
✲✲
✶✵
✇❞❛t❡ ✿❂ t♦❴❝❤❛r✭t♦❴❞❛t❡✭
✬✵✶✴✵✶✴✺✵✬✱✬❞❞✴♠♠✴②②✬✮✱✬❞❞✴♠♠✴②②②②✬✮❀
✶✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✶✷
✲✲
✶✸
✇❞❛t❡ ✿❂ t♦❴❝❤❛r✭
t♦❴❞❛t❡✭✬✵✶✴✵✶✴✹✾✬✱✬❞❞✴♠♠✴rr✬✮✱✬❞❞✴♠♠✴rrrr✬✮❀
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✶✺
✲✲
✶✻
✇❞❛t❡ ✿❂ t♦❴❝❤❛r✭
t♦❴❞❛t❡✭✬✵✶✴✵✶✴✺✵✬✱✬❞❞✴♠♠✴rr✬✮✱✬❞❞✴♠♠✴rrrr✬✮❀
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✶✽
✲✲
✶✾ ❡♥❞❀
✷✵ ✴
❉❛t❛✿ ✸✵✴✶✶✴✷✵✶✶
❉❛t❛✿ ✵✶✴✵✶✴✷✵✹✾
❉❛t❛✿ ✵✶✴✵✶✴✷✵✺✵
❉❛t❛✿ ✵✶✴✵✶✴✷✵✹✾
❉❛t❛✿ ✵✶✴✵✶✴✶✾✺✵
191
14.2. to_number
Casa do Código
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, vemos formatações de datas utilizando a função
to_char, juntamente com os elementos de formatação YY e RR. Note que
podemos ter datas diferentes ao converter utilizando RR e YY, dependendo
do ano da data informada. Para mais detalhes e compreensão desse exemplo,
consulte as regras do uso do formato RR na lista de elementos de formatação
vista anteriormente.
14.2
to_number
Muito semelhante à função to_date, esta função também tem o papel de
converter determinados valores. Seu objetivo, no entanto, é fazer a conversão
de caracteres para numéricos.
Quando falamos na função to_date, foi mencionado que o valor do caractere que está sendo informado como parâmetro deve ser compatível com o
formato. Pois bem, quando trabalhamos com to_number, o mesmo também
acontece. Ao informarmos um valor caractere para a função to_number, ele
deve ser compatível com o formato que estamos passando para a função. Todavia, existe uma particularidade quanto ao formato para casas decimais e de
grupo (milhar, por exemplo).
Para cálculos internos do Oracle, sempre será usado ponto ( .) como separador decimal e vírgula ( ,) para separador de grupo, como padrão americano. Para atribuições de variáveis do tipo caractere ou para visualização, o Oracle pegará a formatação conforme estiver configurado na variável
nls_numeric_characters.
Uma das razões de o Oracle utilizar esta premissa talvez seja pelo fato de a
vírgula ser utilizada para a separação de valores ou colunas em um comando
SQL. Veja o exemplo:
Fazendo um select do número 111,1 utilizando vírgula como separador
decimal.
192
Casa do Código
Capítulo 14. Funções de conversão
❙◗▲❃ s❡❧❡❝t ✶✶✶✱✶ ❢r♦♠ ❞✉❛❧❀
✶✶✶
✶
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✶✶✶
✶
❙◗▲❃
Agora, executando o mesmo select, mas utilizando o ponto como separador decimal.
❙◗▲❃ s❡❧❡❝t ✶✶✶✳✶ ❢r♦♠ ❞✉❛❧❀
✶✶✶✳✶
✲✲✲✲✲✲✲✲✲✲
✶✶✶✳✶
❙◗▲❃
No primeiro exemplo, o comando SQL acabou entendendo que 111 era um
dado e 1 era outro. O mesmo não aconteceu quando, em vez de separarmos
por vírgula, separamos por ponto.
Vejamos o exemplo a seguir. Nele estamos tentando converter um valor
onde temos como separador de decimais a vírgula ( ,), e para milhar, o ponto
( .). Pois bem, já sabemos que para cálculos de conversões internas o Oracle
utiliza o ponto como decimal. Logo, o comando SQL a seguir gera um erro.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✳✺✻✾✳✾✵✵✱✽✼✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✻✺✵✷✿ P▲✴❙◗▲✿ ♥✉♠❡r✐❝ ♦r ✈❛❧✉❡ ❡rr♦r✿ ❝❤❛r❛❝t❡r t♦ ♥✉♠❜❡r
193
Casa do Código
14.2. to_number
❝♦♥✈❡rs✐♦♥ ❡rr♦r
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Ok! O erro acontece porque onde há vírgula deveria ser ponto e onde há
ponto deveria ser vírgula. Pois bem, vejamos o select a seguir:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✱✺✻✾✱✾✵✵✳✽✼✬✮ ❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✻✺✵✷✿ P▲✴❙◗▲✿ ♥✉♠❡r✐❝ ♦r ✈❛❧✉❡ ❡rr♦r✿ ❝❤❛r❛❝t❡r t♦ ♥✉♠❜❡r
❝♦♥✈❡rs✐♦♥ ❡rr♦r
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Agora você deve estar se perguntando: “Mas por que o erro, sendo que
tudo indica que agora o formato foi informado corretamente, ponto para decimais e vírgula para milhares?”. Pois bem, veja o select a seguir:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
194
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✼✾✵✷ ✶✼✲❉❊❈✲✽✵
✽✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✵✲❋❊❇✲✽✶
✶✻✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✷✲❋❊❇✲✽✶
✶✷✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✷✲❆P❘✲✽✶
✸✷✼✷✳✺
Casa do Código
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✽✵✵✵
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
❏❖❍◆
Capítulo 14. Funções de conversão
❙❆▲❊❙▼❆◆
▼❆◆❆●❊❘
▼❆◆❆●❊❘
❆◆❆▲❨❙❚
P❘❊❙■❉❊◆❚
❱❊◆❉❊❉❖❘
❈▲❊❘❑
❈▲❊❘❑
❆◆❆▲❨❙❚
❈▲❊❘❑
❈▲❊❘❑
✼✻✾✽
✼✽✸✾
✼✽✸✾
✼✺✻✻
✼✻✾✽
✼✼✽✽
✼✻✾✽
✼✺✻✻
✼✼✽✷
✼✾✵✷
✷✽✲❙❊P✲✽✶
✵✶✲▼❆❨✲✽✶
✵✾✲❏❯◆✲✽✶
✵✾✲❉❊❈✲✽✷
✶✼✲◆❖❱✲✽✶
✵✽✲❙❊P✲✽✶
✶✷✲❏❆◆✲✽✸
✵✸✲❉❊❈✲✽✶
✵✸✲❉❊❈✲✽✶
✷✸✲❏❆◆✲✽✷
✸✵✲▼❆❘✲✶✶
✶✷✺✵
✷✽✺✵
✷✹✺✵
✸✵✵✵
✺✵✵✵
✶✺✵✵
✶✶✵✵
✾✺✵
✸✵✵✵
✶✸✵✵
✶✵✵✵
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲
✷✵
✸✵✵
✸✵
✺✵✵
✸✵
✷✵
✶✹✵✵
✸✵
✸✵
✶✵
✷✵
✶✵
✵
✸✵
✷✵
✸✵
✷✵
✶✵
✷✵✵
✷✵
✶✺ r♦✇s s❡❧❡❝t❡❞✳
❙◗▲❃
Observe a coluna SAL, mais precisamente o registro EMPNO=7566. Veja
que o valor do salário está aparecendo como 3272.5. Este número possui como
separador de decimais o caractere ponto, mas não possui separador de grupo
de milhar.
Isso nos leva à conclusão de que, além de sabermos as regras para pontos
195
14.2. to_number
Casa do Código
e vírgulas, também devemos estar cientes de como está definida a sessão do
Oracle. No Oracle, a formatação de milhar não aparece, a menos que seja
aplicada para tal. Vamos voltar ao exemplo anterior, agora com a formatação:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✳✺✻✾✳✾✵✵✱✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✻✺✵✷✿ P▲✴❙◗▲✿ ♥✉♠❡r✐❝ ♦r ✈❛❧✉❡ ❡rr♦r
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Ainda sim o erro persiste. Também pudera, vimos no registro
EMPNO=7566 que, na sessão do Oracle, está definido como casa decimal o
ponto, e não a vírgula. Vamos trocar:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✱✺✻✾✱✾✵✵✳✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❱❛❧♦r✿ ✹✺✻✾✾✵✵✳✽✼
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
196
Casa do Código
Capítulo 14. Funções de conversão
Bingo! Este comando select funcionou por duas razões. Primeira: o
valor passado no formato caractere possui um número válido que contém
como separador de casas decimais o mesmo definido na sessão do Oracle.
Segundo: foi definido um formato onde estipulamos que neste conjunto de
caracteres há separadores de grupo o qual representamos com o elemento de
função G. Utilizando desta forma, o Oracle entende que o ponto é o separador
de decimal e a vírgula é o de milhar. Para provar nossa tese, vamos mudar os
separadores na sessão e vamos executar o mesmo select anterior:
❙◗▲❃ ❛❧t❡r s❡ss✐♦♥ s❡t ♥❧s❴♥✉♠❡r✐❝❴❝❤❛r❛❝t❡rs❂✬✳✱✬❀
❙❡ss✐♦♥ ❛❧t❡r❡❞✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✳✺✻✾✳✾✵✵✱✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✻✺✵✷✿ P▲✴❙◗▲✿ ♥✉♠❡r✐❝ ♦r ✈❛❧✉❡ ❡rr♦r
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
197
14.2. to_number
Casa do Código
Nota: além das alterações referentes aos separadores numéricos, também podemos alterar as sessões para definir um novo formato de data e
também para a definição de linguagens. Exemplos:
❛❧t❡r s❡ss✐♦♥ s❡t ♥❧s❴❧❛♥❣✉❛❣❡ ❂ ✬❇❘❆❩■▲■❆◆ P❖❘❚❯●❯❊❙❊✬❀
❛❧t❡r s❡ss✐♦♥ s❡t ♥❧s❴❞❛t❡❴❧❛♥❣✉❛❣❡ ❂ ✬P❖❘❚❯●❯❊❙❊✬❀
❛❧t❡r s❡ss✐♦♥ s❡t ♥❧s❴❞❛t❡❴❢♦r♠❛t ❂ ✬❉❉✴▼▼✴❘❘❘❘✬❀
Agora vamos trocar os caracteres de lugar:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✱✺✻✾✱✾✵✵✳✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❱❛❧♦r✿ ✹✺✻✾✾✵✵✳✽✼
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Funcionou. Mas espere um momento. Além de converter, preciso saber
como está definido na sessão do Oracle? Não. Não é necessário se você especificar, além do formato, quais caracteres devem ser utilizados para a separação
de decimais e grupos. Vejamos novamente o penúltimo exemplo. Nele, definimos que o ponto seria a decimal, e vírgula o grupo. Contudo, isso gerou um
erro ao executar nosso select onde estava justamente definido ao contrário
da parametrização feita.
❙◗▲❃ ❛❧t❡r s❡ss✐♦♥ s❡t ♥❧s❴♥✉♠❡r✐❝❴❝❤❛r❛❝t❡rs❂✬✳✱✬❀
❙❡ss✐♦♥ ❛❧t❡r❡❞✳
198
Casa do Código
Capítulo 14. Funções de conversão
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✳✺✻✾✳✾✵✵✱✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
❖❘❆✲✵✻✺✵✷✿ P▲✴❙◗▲✿ ♥✉♠❡r✐❝ ♦r ✈❛❧✉❡ ❡rr♦r
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Utilizando o parâmetro nls, aquele terceiro parâmetro da função que é
opcional, nós conseguimos, em vez de alterar a sessão do Oracle, validar estes
caracteres apenas no nosso comando. Vamos executar novamente o select
anterior, mas agora incorporando o terceiro parâmetro:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇✈❛❧♦r ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇✈❛❧♦r ✿❂ t♦❴♥✉♠❜❡r✭✬✹✳✺✻✾✳✾✵✵✱✽✼✬✱✬✾●✾✾✾●✾✾✾❉✵✵✬✱
✬♥❧s❴♥✉♠❡r✐❝❴❝❤❛r❛❝t❡rs❂✱✳✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❱❛❧♦r✿ ✬⑤⑤✇✈❛❧♦r✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❱❛❧♦r✿ ✹✺✻✾✾✵✵✳✽✼
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Funcionou perfeitamente. Embora pareça complicado no início, você vai
se acostumando com as características e logo pega a lógica. Vale salientar que
199
Casa do Código
14.2. to_number
esta questão da sessão também é válida para o to_date. Veja o select,
agora observando a coluna HIREDATE.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✽✵✵✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
❏❖❍◆
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲
✷✵
✸✵✵
✸✵
✺✵✵
✸✵
✷✵
✶✹✵✵
✸✵
✸✵
✶✵
✷✵
✶✵
✵
✸✵
✷✵
✸✵
✷✵
✶✵
200
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✼✾✵✷ ✶✼✲❉❊❈✲✽✵
✽✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✵✲❋❊❇✲✽✶
✶✻✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✷✲❋❊❇✲✽✶
✶✷✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✷✲❆P❘✲✽✶
✸✷✼✷✳✺
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✽✲❙❊P✲✽✶
✶✷✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✶✲▼❆❨✲✽✶
✷✽✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✾✲❏❯◆✲✽✶
✷✹✺✵
❆◆❆▲❨❙❚
✼✺✻✻ ✵✾✲❉❊❈✲✽✷
✸✵✵✵
P❘❊❙■❉❊◆❚
✶✼✲◆❖❱✲✽✶
✺✵✵✵
❱❊◆❉❊❉❖❘
✼✻✾✽ ✵✽✲❙❊P✲✽✶
✶✺✵✵
❈▲❊❘❑
✼✼✽✽ ✶✷✲❏❆◆✲✽✸
✶✶✵✵
❈▲❊❘❑
✼✻✾✽ ✵✸✲❉❊❈✲✽✶
✾✺✵
❆◆❆▲❨❙❚
✼✺✻✻ ✵✸✲❉❊❈✲✽✶
✸✵✵✵
❈▲❊❘❑
✼✼✽✷ ✷✸✲❏❆◆✲✽✷
✶✸✵✵
❈▲❊❘❑
✼✾✵✷ ✸✵✲▼❆❘✲✶✶
✶✵✵✵
Casa do Código
✷✵✵
Capítulo 14. Funções de conversão
✷✵
✶✺ r♦✇s s❡❧❡❝t❡❞✳
❙◗▲❃
Para o registro EMPNO=7566, o valor da coluna HIREDATE é 02-APR-81.
Logo, este é o formato definido na sessão. Vamos olhar o próximo select.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✵✷✲❆P❘✲✽✶✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✵✷✲❆P❘✲✽✶
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nota-se que no select anterior não foi gerado erro, mesmo não sendo
informado o formato. Isso aconteceu porque o valor de caractere informado
como string está no mesmo formato da sessão do Oracle. Veja o que acontece
quando colocamos a string em outro formato:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✵✺✴✷✶✴✷✵✵✾✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❞❡❝❧❛r❡
✯
❊❘❘❖❘ ❛t ❧✐♥❡ ✶✿
201
14.2. to_number
Casa do Código
❖❘❆✲✵✶✽✹✸✿ ♥♦t ❛ ✈❛❧✐❞ ♠♦♥t❤
❖❘❆✲✵✻✺✶✷✿ ❛t ❧✐♥❡ ✹
❙◗▲❃
Para consertar isso devemos informar um formato compatível com o conjunto de caracteres passado ou trocar o formato da sessão do Oracle. Informando um formato compatível:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✵✺✴✷✶✴✷✵✵✾✬✱✬♠♠✴❞❞✴②②②②✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✷✶✲▼❆❨✲✵✾
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Alterando a sessão do Oracle:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❡ ❞❛t❡❀
✸ ❜❡❣✐♥
✹
✇❞❛t❡ ✿❂ t♦❴❞❛t❡✭✬✵✺✴✷✶✴✷✵✵✾✬✮❀
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❛t❛✿ ✬⑤⑤✇❞❛t❡✮❀
✻
✲✲
✼ ❡♥❞❀
✽ ✴
❉❛t❛✿ ✵✺✴✷✶✴✷✵✵✾
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
202
Casa do Código
Capítulo 14. Funções de conversão
Veja alguns elementos de formatação que podem ser usados:
• 9: cada nove representa um caractere que será substituído pelo caractere referente ao valor numérico passado como parâmetro. Os zeros na
frente são tratados como espaços em branco.
• 0: adicionando 0 como um prefixo ou sufixo ao número, todos os zeros iniciais ou finais são tratados e exibidos como zeros em vez de um
espaço em branco.
• $: prefixo do símbolo de moeda impresso na primeira posição.
• S: exibe um sinal de + inicial ou final quando o valor for positivo e um
sinal de - inicial ou final quando o valor for negativo.
• D: localização do ponto decimal. Os noves de ambos os lados refletem
o número máximo de dígitos permitidos.
• G: especifica um separador de grupo (milhar, por exemplo) como uma
vírgula.
• L: especifica a localização do símbolo de moeda local (tal como $).
• ,: coloca uma vírgula na posição especificada, independentemente do
separador de grupo.
• .: especifica a localização do ponto decimal, independentemente do
separador decimal.
• FM: remove os espaços em branco inicial e final.
Há uma confusão muito comum com o uso do to_date e do
to_number no que diz respeito ao resultado mostrado pelo select quando
são utilizadas estas duas funções. Embora estejamos informando um formato,
o Oracle não apresenta o resultado do SQL baseado nele. Isso acontece porque
o formato no uso destas funções é apenas para a conversão e não para a visualização. Par visualizarmos o resultado com base no formato que queremos,
utilizamos o to_char.
203
14.3. to_char
Casa do Código
14.3 to_char
Função utilizada para converter tipos de dados numéricos e datas para caracteres. Além da conversão, ele é muito utilizado para formatação visual de
dados. Seguem exemplos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧ ✈❛r❝❤❛r✷✭✺✵✮❀
✸ ❜❡❣✐♥
✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡
✺
✱s❛❧
✻
❢r♦♠ ❡♠♣✮ ❧♦♦♣
✼
✲✲
✽
✇s❛❧ ✿❂ t♦❴❝❤❛r✭r✶✳s❛❧✱✬✾●✾✾✾●✾✾✾❉✵✵✬✱
✬♥❧s❴♥✉♠❡r✐❝❴❝❤❛r❛❝t❡rs❂✬✬✳✱✬✬✬✮❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤✇s❛❧✮❀
✶✶
✲✲
✶✷
❡♥❞ ❧♦♦♣❀
✶✸ ❡♥❞❀
✶✹ ✴
◆♦♠❡✿ ❙▼■❚❍ ❙❛❧ár✐♦✿ ✽✵✵✳✵✵
◆♦♠❡✿ ❆▲▲❊◆ ❙❛❧ár✐♦✿ ✶✱✻✵✵✳✵✵
◆♦♠❡✿ ❲❆❘❉ ❙❛❧ár✐♦✿ ✶✱✷✺✵✳✵✵
◆♦♠❡✿ ❏❖◆❊❙ ❙❛❧ár✐♦✿ ✷✱✾✼✺✳✵✵
◆♦♠❡✿ ▼❆❘❚■◆ ❙❛❧ár✐♦✿ ✶✱✷✺✵✳✵✵
◆♦♠❡✿ ❇▲❆❑❊ ❙❛❧ár✐♦✿ ✷✱✽✺✵✳✵✵
◆♦♠❡✿ ❈▲❆❘❑ ❙❛❧ár✐♦✿ ✷✱✹✺✵✳✵✵
◆♦♠❡✿ ❙❈❖❚❚ ❙❛❧ár✐♦✿ ✸✱✵✵✵✳✵✵
◆♦♠❡✿ ❑■◆● ❙❛❧ár✐♦✿ ✺✱✵✵✵✳✵✵
◆♦♠❡✿ ❚❯❘◆❊❘ ❙❛❧ár✐♦✿ ✶✱✺✵✵✳✵✵
◆♦♠❡✿ ❆❉❆▼❙ ❙❛❧ár✐♦✿ ✶✱✶✵✵✳✵✵
◆♦♠❡✿ ❏❆▼❊❙ ❙❛❧ár✐♦✿ ✾✺✵✳✵✵
◆♦♠❡✿ ❋❖❘❉ ❙❛❧ár✐♦✿ ✸✱✵✵✵✳✵✵
◆♦♠❡✿ ▼■▲▲❊❘ ❙❛❧ár✐♦✿ ✶✱✸✵✵✳✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
204
Casa do Código
Capítulo 14. Funções de conversão
❙◗▲❃
Neste exemplo são selecionados todos os nomes dos empregados e seus
respectivos salários. Foi utilizada a função to_char para formatar os valores do salário, com o elemento de formatação para casas decimais e milhar.
Note que aqui usamos o parâmetro nls_numeric_characters, para definir quais caracteres devem ser utilizados para cada separador do elemento.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❝♦✉♥t✭✯✮ qt❴❛❞♠✐t✐❞♦s
✸
✱t♦❴❝❤❛r✭❤✐r❡❞❛t❡✱✬♠♠✬✮ ▼❊❙
✹
❢r♦♠ ❡♠♣
✺
❣r♦✉♣ ❜② t♦❴❝❤❛r✭❤✐r❡❞❛t❡✱✬♠♠✬✮✮ ❧♦♦♣
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❆❞♠✐t✐❞♦s✿ ✬⑤⑤r✶✳qt❴❛❞♠✐t✐❞♦s⑤⑤✬
▼ês✿ ✬⑤⑤r✶✳♠❡s✮❀
✽
✲✲
✾
❡♥❞ ❧♦♦♣❀
✶✵ ❡♥❞❀
✶✶ ✴
❆❞♠✐t✐❞♦s✿ ✶ ▼ês✿ ✵✹
❆❞♠✐t✐❞♦s✿ ✷ ▼ês✿ ✵✾
❆❞♠✐t✐❞♦s✿ ✹ ▼ês✿ ✶✷
❆❞♠✐t✐❞♦s✿ ✶ ▼ês✿ ✶✶
❆❞♠✐t✐❞♦s✿ ✷ ▼ês✿ ✵✶
❆❞♠✐t✐❞♦s✿ ✷ ▼ês✿ ✵✷
❆❞♠✐t✐❞♦s✿ ✶ ▼ês✿ ✵✺
❆❞♠✐t✐❞♦s✿ ✶ ▼ês✿ ✵✻
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Aqui a função to_char foi utilizada para formatar a data de admissão do
empregado, mostrando apenas o mês referente esta data. O select agrupa
e apresenta quantos empregados foram admitidos em cada mês.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❛❴❡①t❡♥s♦ ✈❛r❝❤❛r✷✭✶✵✵✮❀
205
14.3. to_char
Casa do Código
✸ ❜❡❣✐♥
✹
✇❞❛t❛❴❡①t❡♥s♦ ✿❂ ✬✷✷ ❞❡ ❛❣♦st♦ ❞❡ ✷✵✵✾ s❡rá ♦ ❞✐❛ ✬⑤⑤
t♦❴❝❤❛r✭t♦❴❞❛t❡✭✬✷✷✴✵✽✴✷✵✵✾✬✱✬❞❞✴♠♠✴②②②②✬✮✱✬❞❞❞✬✮⑤⑤
✺
✻
✬ ❞♦ ❛♥♦✬❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇❞❛t❛❴❡①t❡♥s♦✮❀
✾
✲✲
✶✵ ❡♥❞❀
✶✶ ✴
✷✷ ❞❡ ❛❣♦st♦ ❞❡ ✷✵✵✾ s❡rá ♦ ❞✐❛ ✷✸✹ ❞♦ ❛♥♦
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Outro exemplo com to_char, usado na formatação de datas. Nesse programa, são impressos uma data e o número do dia que ela representa no ano.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞✐❛❴s❡♠❛♥❛ ✈❛r❝❤❛r✷✭✺✵✮❀
✸ ❜❡❣✐♥
✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡✱ ❤✐r❡❞❛t❡ ❢r♦♠ ❡♠♣✮ ❧♦♦♣
✺
✲✲
✻
✇❞✐❛❴s❡♠❛♥❛ ✿❂ t♦❴❝❤❛r✭r✶✳❤✐r❡❞❛t❡✱✬❞❛②✬✮❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❆❞♠✐ssã♦✿ ✬⑤⑤
✾
r✶✳❤✐r❡❞❛t❡⑤⑤✬ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ✬⑤⑤✇❞✐❛❴s❡♠❛♥❛✮❀
✶✵
✲✲
✶✶
❡♥❞ ❧♦♦♣❀
✶✷ ❡♥❞❀
✶✸ ✴
◆♦♠❡✿ ❙▼■❚❍ ❆❞♠✐ssã♦✿ ✶✷✴✶✼✴✶✾✽✵ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ✇❡❞♥❡s❞❛②
◆♦♠❡✿ ❆▲▲❊◆ ❆❞♠✐ssã♦✿ ✵✷✴✷✵✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ❢r✐❞❛②
◆♦♠❡✿ ❲❆❘❉ ❆❞♠✐ssã♦✿ ✵✷✴✷✷✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ s✉♥❞❛②
◆♦♠❡✿ ❏❖◆❊❙ ❆❞♠✐ssã♦✿ ✵✹✴✵✷✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t❤✉rs❞❛②
◆♦♠❡✿ ▼❆❘❚■◆ ❆❞♠✐ssã♦✿ ✵✾✴✷✽✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ♠♦♥❞❛②
◆♦♠❡✿ ❇▲❆❑❊ ❆❞♠✐ssã♦✿ ✵✺✴✵✶✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ❢r✐❞❛②
◆♦♠❡✿ ❈▲❆❘❑ ❆❞♠✐ssã♦✿ ✵✻✴✵✾✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t✉❡s❞❛②
◆♦♠❡✿ ❙❈❖❚❚ ❆❞♠✐ssã♦✿ ✶✷✴✵✾✴✶✾✽✷ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t❤✉rs❞❛②
206
Casa do Código
◆♦♠❡✿
◆♦♠❡✿
◆♦♠❡✿
◆♦♠❡✿
◆♦♠❡✿
◆♦♠❡✿
Capítulo 14. Funções de conversão
❑■◆● ❆❞♠✐ssã♦✿ ✶✶✴✶✼✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t✉❡s❞❛②
❚❯❘◆❊❘ ❆❞♠✐ssã♦✿ ✵✾✴✵✽✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t✉❡s❞❛②
❆❉❆▼❙ ❆❞♠✐ssã♦✿ ✵✶✴✶✷✴✶✾✽✸ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ ✇❡❞♥❡s❞❛②
❏❆▼❊❙ ❆❞♠✐ssã♦✿ ✶✷✴✵✸✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t❤✉rs❞❛②
❋❖❘❉ ❆❞♠✐ssã♦✿ ✶✷✴✵✸✴✶✾✽✶ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ t❤✉rs❞❛②
▼■▲▲❊❘ ❆❞♠✐ssã♦✿ ✵✶✴✷✸✴✶✾✽✷ ❉✐❛ ❞❛ ❙❡♠❛♥❛✿ s❛t✉r❞❛②
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, são mostrados dados referentes à admissão do empregado: nome do empregado, data de admissão e dia da semana. Este último,
formatado através da função to_char.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇❞❛t❛❴❡①t❡♥s♦ ✈❛r❝❤❛r✷✭✶✵✵✮❀
✸ ❜❡❣✐♥
✹
✇❞❛t❛❴❡①t❡♥s♦ ✿❂
✬❏♦✐♥✈✐❧❧❡✱ ✬⑤⑤t♦❴❝❤❛r✭s②s❞❛t❡✱✬❞❞✬✮⑤⑤✬ ❞❡ ✬⑤⑤
✺
✐♥✐t❝❛♣✭t♦❴❝❤❛r✭s②s❞❛t❡✱ ✬❢♠♠♦♥t❤✬✮✮⑤⑤✬ ❞❡ ✬
✻
⑤⑤t♦❴❝❤❛r✭s②s❞❛t❡✱✬②②②②✬✮⑤⑤✬✳✬❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✇❞❛t❛❴❡①t❡♥s♦✮❀
✾
✲✲
✶✵ ❡♥❞❀
✶✶ ✴
❏♦✐♥✈✐❧❧❡✱ ✸✵ ❞❡ ◆♦✈❡♠❜❡r ❞❡ ✷✵✶✶✳
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, usamos to_char para imprimir em tela a data por extenso.
❙◗▲❃ ❜❡❣✐♥
✷
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❡♥❛♠❡
✸
✱❤✐r❡❞❛t❡
207
Casa do Código
14.3. to_char
✹
✺
✻
✼
❢r♦♠ ❡♠♣
✇❤❡r❡ t♦❴❝❤❛r✭❤✐r❡❞❛t❡✱✬②②②②✬✮ ❂ ✬✶✾✽✷✬✮ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ❆❞♠✐ssã♦✿ ✬⑤⑤r✶✳❤✐r❡❞❛t❡✮❀
✽
✲✲
✾
❡♥❞ ❧♦♦♣❀
✶✵ ❡♥❞❀
✶✶ ✴
◆♦♠❡✿ ❙❈❖❚❚ ❆❞♠✐ssã♦✿ ✶✷✴✵✾✴✶✾✽✷
◆♦♠❡✿ ▼■▲▲❊❘ ❆❞♠✐ssã♦✿ ✵✶✴✷✸✴✶✾✽✷
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Aqui utilizamos a função
to_char para restringir dados em um
select.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❢♦r♠❛t❛❞♦ ✈❛r❝❤❛r✷✭✺✵✮❀
✸ ❜❡❣✐♥
✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t s❛❧ ❢r♦♠ ❡♠♣✮ ❧♦♦♣
✺
✲✲
✻
✇s❛❧❴❢♦r♠❛t❛❞♦ ✿❂
✬❘✩ ✬⑤⑤t♦❴❝❤❛r✭r✶✳s❛❧✱✬❢♠✾●✾✾✾●✾✾✵❉✵✵✬✮❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙❛❧ár✐♦✿ ✬⑤⑤r✶✳s❛❧⑤⑤✬
❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✬⑤⑤✇s❛❧❴❢♦r♠❛t❛❞♦✮❀
✾
✲✲
✶✵
❡♥❞ ❧♦♦♣❀
✶✶ ❡♥❞❀
✶✷ ✴
❙❛❧ár✐♦✿ ✽✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✽✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✻✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✻✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✷✺✵✳✵✵
❙❛❧ár✐♦✿ ✷✾✼✺ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✷✱✾✼✺✳✵✵
❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✷✺✵✳✵✵
❙❛❧ár✐♦✿ ✷✽✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✷✱✽✺✵✳✵✵
208
Casa do Código
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
❙❛❧ár✐♦✿
Capítulo 14. Funções de conversão
✷✹✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✷✱✹✺✵✳✵✵
✸✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✸✱✵✵✵✳✵✵
✺✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✺✱✵✵✵✳✵✵
✶✺✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✺✵✵✳✵✵
✶✶✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✶✵✵✳✵✵
✾✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✾✺✵✳✵✵
✸✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✸✱✵✵✵✳✵✵
✶✸✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ❘✩ ✶✱✸✵✵✳✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❢♦r♠❛t❛❞♦ ✈❛r❝❤❛r✷✭✺✵✮❀
✸ ❜❡❣✐♥
✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t s❛❧ ❢r♦♠ ❡♠♣✮ ❧♦♦♣
✺
✲✲
✻
✇s❛❧❴❢♦r♠❛t❛❞♦ ✿❂ t♦❴❝❤❛r✭r✶✳s❛❧✱✬❢♠▲✾●✾✾✾●✾✾✵❉✵✵✬✮❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙❛❧ár✐♦✿ ✬⑤⑤r✶✳s❛❧⑤⑤✬
❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✬⑤⑤✇s❛❧❴❢♦r♠❛t❛❞♦✮❀
✾
✲✲
✶✵
❡♥❞ ❧♦♦♣❀
✶✶ ❡♥❞❀
✶✷ ✴
❙❛❧ár✐♦✿ ✽✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✽✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✻✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✻✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✷✺✵✳✵✵
❙❛❧ár✐♦✿ ✷✾✼✺ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✷✱✾✼✺✳✵✵
❙❛❧ár✐♦✿ ✶✷✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✷✺✵✳✵✵
❙❛❧ár✐♦✿ ✷✽✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✷✱✽✺✵✳✵✵
❙❛❧ár✐♦✿ ✷✹✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✷✱✹✺✵✳✵✵
❙❛❧ár✐♦✿ ✸✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✸✱✵✵✵✳✵✵
❙❛❧ár✐♦✿ ✺✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✺✱✵✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✺✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✺✵✵✳✵✵
❙❛❧ár✐♦✿ ✶✶✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✶✵✵✳✵✵
❙❛❧ár✐♦✿ ✾✺✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✾✺✵✳✵✵
❙❛❧ár✐♦✿ ✸✵✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✸✱✵✵✵✳✵✵
209
14.3. to_char
Casa do Código
❙❛❧ár✐♦✿ ✶✸✵✵ ❙❛❧ár✐♦ ❋♦r♠❛t❛❞♦✿ ✩✶✱✸✵✵✳✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo se parece com o anterior. Contudo, aqui estamos utilizando
os elementos de formatação FM e L. O primeiro retira os espaços em branco,
onde algum elemento de formatação não tenha sido preenchido, por ausência
de valores. O segundo mostra a moeda configurada na sessão do usuário,
onde o programa está sendo executado.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇♣♦s✐t✐✈♦ ✈❛r❝❤❛r✷✭✶✵✵✮❀
✸
✇♥❡❣❛t✐✈♦ ✈❛r❝❤❛r✷✭✶✵✵✮❀
✹ ❜❡❣✐♥
✺
✇♣♦s✐t✐✈♦ ✿❂ t♦❴❝❤❛r✭✶✼✹✾✽✹✷✽✸✳✼✺✱✬❢♠✾✾✾✱✾✾✾✱✾✾✾✳✵✵❙✬✮❀
✻
✇♥❡❣❛t✐✈♦ ✿❂ t♦❴❝❤❛r✭✶✵✵✲✶✵✵✵✱✬❢♠✾✾✾✱✾✾✾✱✾✾✾✳✵✵❙✬✮❀
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬P♦s✐t✐✈♦✿ ✬⑤⑤✇♣♦s✐t✐✈♦⑤⑤✬ ✲
◆❡❣❛t✐✈♦✿ ✬⑤⑤✇♥❡❣❛t✐✈♦✮❀
✾
✲✲
✶✵ ❡♥❞❀
✶✶ ✴
P♦s✐t✐✈♦✿ ✶✼✹✱✾✽✹✱✷✽✸✳✼✺✰ ✲ ◆❡❣❛t✐✈♦✿ ✾✵✵✳✵✵✲
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Já nesse exemplo, utilizamos o elemento de formatação S, que indica o
sinal referente ao valor formatado. Note que no valor positivo foi impresso,
atrás do número, o sinal de positivo ( +), quanto para o valor negativo é impresso o sinal de negativo ( -).
210
Capítulo 15
Funções condicionais
O Oracle disponibiliza outros tipos de funções, dentre as quais as funções
condicionais. Elas são utilizadas tanto na seleção de dados pela cláusula
select como também no uso de cláusulas where. Seu uso é bastante difundido e bem flexível.
• decode: esta estrutura funciona como uma estrutura if-else dentro de uma cláusula select. É muito utilizada principalmente para
visualização de dados onde é preciso realizar algum teste para saber se
estes dados podem ou não aparecer.
• nullif: são passados dois parâmetros para esta função. Ela compara
os dois, se forem iguais é retornado Null. Caso contrário, ela retorna
o primeiro parâmetro.
Casa do Código
• nvl: para esta função são passados dois parâmetros. Se o primeiro for
nulo, ele retorna o segundo, caso contrário, retorna o primeiro.
• case: muito parecido com o decode. Seu objetivo também é permitir a utilização de uma estrutura tipo if-else dentro do comando
SQL. Ao contrário do decode sua aplicação e visualização são mais
inteligíveis (padrão ANSI).
• greatest: retorna a maior expressão de uma lista de valores passada
como parâmetro. Todas as expressões após a primeira são convertidas
para o tipo de dado da primeira antes da comparação ser realizada.
• least: funciona o inverso da greatest. Esta traz a menor expressão.
Veja alguns exemplos:
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❥♦❜✱
✹
s✉♠✭❝❛s❡
✺
✇❤❡♥ ❞❡♣t♥♦ ❂ ✶✵ t❤❡♥ s❛❧
✻
❡❧s❡
✼
✵
❡♥❞✮ ❞❡♣❛rt❴✶✵✱
✽
✾
s✉♠✭❝❛s❡
✶✵
✇❤❡♥ ❞❡♣t♥♦ ❂ ✷✵ t❤❡♥ s❛❧
✶✶
❡❧s❡
✶✷
✵
❡♥❞✮ ❞❡♣❛rt❴✷✵✱
✶✸
✶✹
s✉♠✭❝❛s❡
✶✺
✇❤❡♥ ❞❡♣t♥♦ ❂ ✸✵ t❤❡♥ s❛❧
✶✻
❡❧s❡
✶✼
✵
✶✽
❡♥❞✮ ❞❡♣❛rt❴✸✵✱
✶✾
s✉♠✭s❛❧✮ t♦t❛❧❴❥♦❜
✷✵
❢r♦♠ ❡♠♣
✷✶
❣r♦✉♣ ❜② ❥♦❜❀
✷✷
✲✲
✷✸ ❜❡❣✐♥
212
Casa do Código
Capítulo 15. Funções condicionais
✷✹
✷✺
✷✻
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭r✶✳❥♦❜⑤⑤✬ ✲ ❉❡♣❛rt✳ ✶✵✿ ✬
⑤⑤r✶✳❞❡♣❛rt❴✶✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✷✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✷✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✸✵✿ ✬⑤⑤
✷✼
r✶✳❞❡♣❛rt❴✸✵⑤⑤✬ ✲ ❚♦t❛❧✿ ✬⑤⑤
✷✽
r✶✳t♦t❛❧❴❥♦❜✮❀
✷✾
✲✲
✸✵
❡♥❞ ❧♦♦♣❀
✸✶ ❡♥❞❀
✸✷ ✴
❈▲❊❘❑ ✲ ❉❡♣❛rt✳ ✶✵✿ ✶✸✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✶✾✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✾✺✵ ✲
❚♦t❛❧✿ ✹✶✺✵
❙❆▲❊❙▼❆◆ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✺✻✵✵ ✲
❚♦t❛❧✿ ✺✻✵✵
P❘❊❙■❉❊◆❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✺✵✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✺✵✵✵
▼❆◆❆●❊❘ ✲ ❉❡♣❛rt✳ ✶✵✿ ✷✹✺✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✷✾✼✺ ✲ ❉❡♣❛rt✳ ✸✵✿
✷✽✺✵ ✲ ❚♦t❛❧✿ ✽✷✼✺
❆◆❆▲❨❙❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✻✵✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✻✵✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, utilizamos a função case, para somar todos os salários
por departamento, agrupando por cargo.
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❥♦❜
✹
✱s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✶✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✶✵
✺
✱s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✷✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✷✵
✻
✱s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✸✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✸✵
✼
✱s✉♠✭s❛❧✮ t♦t❛❧❴❥♦❜
✽
❢r♦♠ ❡♠♣
✾
❣r♦✉♣ ❜② ❥♦❜❀
✶✵
✲✲
213
Casa do Código
✶✶ ❜❡❣✐♥
✶✷
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭r✶✳❥♦❜⑤⑤✬ ✲ ❉❡♣❛rt✳ ✶✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✶✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✷✵✿ ✬⑤⑤
✶✺
r✶✳❞❡♣❛rt❴✷✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✸✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✸✵⑤⑤✬ ✲ ❚♦t❛❧✿ ✬⑤⑤
r✶✳t♦t❛❧❴❥♦❜✮❀
✶✻
✶✼
✲✲
✶✽
❡♥❞ ❧♦♦♣❀
✶✾ ❡♥❞❀
✷✵ ✴
❈▲❊❘❑ ✲ ❉❡♣❛rt✳ ✶✵✿ ✶✸✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✶✾✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✾✺✵ ✲
❚♦t❛❧✿ ✹✶✺✵
❙❆▲❊❙▼❆◆ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✺✻✵✵ ✲
❚♦t❛❧✿ ✺✻✵✵
P❘❊❙■❉❊◆❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✺✵✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✺✵✵✵
▼❆◆❆●❊❘ ✲ ❉❡♣❛rt✳ ✶✵✿ ✷✹✺✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✷✾✼✺ ✲ ❉❡♣❛rt✳ ✸✵✿ ✷✽✺✵
✲ ❚♦t❛❧✿ ✽✷✼✺
❆◆❆▲❨❙❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✻✵✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✻✵✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Esse exemplo é idêntico ao anterior. Apenas trocamos a função case pela
função decode. Vale lembrar que case é do padrão SQL ANSI e decode
é do padrão Oracle.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
214
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✼✾✵✷ ✶✷✴✶✼✴✶✾✽✵
✽✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✵✷✴✷✵✴✶✾✽✶
✶✻✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✵✷✴✷✷✴✶✾✽✶
✶✷✺✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✹✴✵✷✴✶✾✽✶
✷✾✼✺
Casa do Código
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
Capítulo 15. Funções condicionais
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
❙❆▲❊❙▼❆◆
▼❆◆❆●❊❘
▼❆◆❆●❊❘
❆◆❆▲❨❙❚
P❘❊❙■❉❊◆❚
❙❆▲❊❙▼❆◆
❈▲❊❘❑
❈▲❊❘❑
❆◆❆▲❨❙❚
❈▲❊❘❑
✼✻✾✽
✼✽✸✾
✼✽✸✾
✼✺✻✻
✼✻✾✽
✼✼✽✽
✼✻✾✽
✼✺✻✻
✼✼✽✷
✵✾✴✷✽✴✶✾✽✶
✵✺✴✵✶✴✶✾✽✶
✵✻✴✵✾✴✶✾✽✶
✶✷✴✵✾✴✶✾✽✷
✶✶✴✶✼✴✶✾✽✶
✵✾✴✵✽✴✶✾✽✶
✵✶✴✶✷✴✶✾✽✸
✶✷✴✵✸✴✶✾✽✶
✶✷✴✵✸✴✶✾✽✶
✵✶✴✷✸✴✶✾✽✷
✶✷✺✵
✷✽✺✵
✷✹✺✵
✸✵✵✵
✺✵✵✵
✶✺✵✵
✶✶✵✵
✾✺✵
✸✵✵✵
✶✸✵✵
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✷✵
✸✵✵
✸✵
✺✵✵
✸✵
✷✵
✶✹✵✵
✸✵
✸✵
✶✵
✷✵
✶✵
✵
✸✵
✷✵
✸✵
✷✵
✶✵
✶✹ r♦✇s s❡❧❡❝t❡❞✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇s❛❧❴❝♦♠♠✶ ♥✉♠❜❡r❀
✸
✇s❛❧❴❝♦♠♠✷ ♥✉♠❜❡r❀
✹ ❜❡❣✐♥
✺
✲✲
✻
s❡❧❡❝t s✉♠✭s❛❧✰❝♦♠♠✮ ✐♥t♦ ✇s❛❧❴❝♦♠♠✶ ❢r♦♠ ❡♠♣❀
✼
✲✲
✽
s❡❧❡❝t s✉♠✭s❛❧✰♥✈❧✭❝♦♠♠✱✵✮✮ ✐♥t♦ ✇s❛❧❴❝♦♠♠✷ ❢r♦♠ ❡♠♣❀
✾
✲✲
215
Casa do Código
✶✵
✶✶
✶✷
✶✸
❙❛❧✳
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙❛❧✳ ❈♦♠♠✶✿ ✬⑤⑤✇s❛❧❴❝♦♠♠✶⑤⑤✬ ✲
❙❛❧✳ ❈♦♠♠✷✿ ✬⑤⑤✇s❛❧❴❝♦♠♠✷✮❀
✲✲
❡♥❞❀
✴
❈♦♠♠✶✿ ✼✽✵✵ ✲ ❙❛❧✳ ❈♦♠♠✷✿ ✸✶✷✷✺
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo estamos utilizando a função nvl. Note que quando realizamos cálculos com valores nulos (linha 6) o Oracle não executa tal operação.
O Oracle sempre considera como falso quando existem valores NULL (nulo)
em cálculos aritméticos ou no uso de restrição de dados, como, por exemplo,
em cláusulas where. Quando isso ocorre, ele ignora a ação, mas não gera
erros.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇♠❛✐♦r❴❧❡tr❛ ✈❛r❝❤❛r✷✭✶✮❀
✸
✇♠❡♥♦r❴❧❡tr❛ ✈❛r❝❤❛r✷✭✶✮❀
✹ ❜❡❣✐♥
✺
✲✲
✻
s❡❧❡❝t ❣r❡❛t❡st✭✬❜✬✱✬①✬✱✬t✬✱✬✉✬✱✬❛✬✮ ✐♥t♦ ✇♠❛✐♦r❴❧❡tr❛
❢r♦♠ ❞✉❛❧❀
✼
✲✲
✽
s❡❧❡❝t ❧❡❛st✭✬❜✬✱✬①✬✱✬t✬✱✬✉✬✱✬❛✬✮ ✐♥t♦ ✇♠❡♥♦r❴❧❡tr❛
❢r♦♠ ❞✉❛❧❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬▼❛✐♦r ▲❡tr❛✿ ✬⑤⑤✇♠❛✐♦r❴❧❡tr❛⑤⑤✬ ✲
▼❡♥♦r ▲❡tr❛✿ ✬⑤⑤✇♠❡♥♦r❴❧❡tr❛✮❀
✶✶
✲✲
✶✷ ❡♥❞❀
✶✸ ✴
▼❛✐♦r ▲❡tr❛✿ ① ✲ ▼❡♥♦r ▲❡tr❛✿ ❛
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
216
Casa do Código
Capítulo 15. Funções condicionais
Nesse exemplo, temos o uso das funções greatest e least.
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝♦♠♣❛r❛❝❛♦✶ ✈❛r❝❤❛r✷✭✶✵✵✮❀
✸
❝♦♠♣❛r❛❝❛♦✷ ✈❛r❝❤❛r✷✭✶✵✵✮❀
✹ ❜❡❣✐♥
✺
✲✲
✻
s❡❧❡❝t ❞❡❝♦❞❡✭♥✉❧❧✐❢✭✬❛❜❛❝❛①✐✬✱✬❛❜❛❝❛①✐✬✮✱♥✉❧❧✱
✬sã♦ ✐❣✉❛✐s✬✱✬sã♦ ❞✐❢❡r❡♥t❡s✬✮
✼
✐♥t♦ ❝♦♠♣❛r❛❝❛♦✶ ❢r♦♠ ❞✉❛❧❀
✽
✲✲
✾
s❡❧❡❝t ❞❡❝♦❞❡✭♥✉❧❧✐❢✭✬❛❜❛❝❛①✐✬✱✬♠♦r❛♥❣♦✬✮✱♥✉❧❧✱
✬sã♦ ✐❣✉❛✐s✬✱✬sã♦ ❞✐❢❡r❡♥t❡s✬✮
✶✵
✐♥t♦ ❝♦♠♣❛r❛❝❛♦✷ ❢r♦♠ ❞✉❛❧❀
✶✶
✲✲
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈♦♠♣❛r❛çã♦ ✶✿ ✬⑤⑤❝♦♠♣❛r❛❝❛♦✶⑤⑤✬
❈♦♠♣❛r❛çã♦ ✷✿ ✬⑤⑤❝♦♠♣❛r❛❝❛♦✷✮❀
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❈♦♠♣❛r❛çã♦ ✶✿ sã♦ ✐❣✉❛✐s ✲ ❈♦♠♣❛r❛çã♦ ✷✿ sã♦ ❞✐❢❡r❡♥t❡s
✲
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Nesse exemplo, temos o uso da função nullif.
15.1
decode vs. case
Dos comandos condicionais vistos anteriormente, o decode é o mais utilizado. Ele funciona como uma espécie de condição SE ( if) para a linguagem
SQL. Este comando é exclusivo do Oracle, entretanto, no padrão ANSI da linguagem SQL existe um comando similar, o case. Você pode usar qualquer
um deles. Porém, o uso do case só é permitido nas versões mais novas do
banco de dados Oracle. A Oracle, nas versões mais recentes, vem inserindo
comandos padrões ANSI enquanto seus comandos específicos mantêm suas
217
15.1. decode vs. case
Casa do Código
características para questões de compatibilidade. Veja comparações entre estes dois comandos.
Exemplo 1
Padrão ANSI (também suportado pelo Oracle nas versões mais novas do
banco de dados):
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❥♦❜✱
✹
s✉♠✭❝❛s❡
✺
✇❤❡♥ ❞❡♣t♥♦ ❂ ✶✵ t❤❡♥ s❛❧
✻
❡❧s❡
✼
✵
❡♥❞✮ ❞❡♣❛rt❴✶✵✱
✽
✾
s✉♠✭❝❛s❡
✶✵
✇❤❡♥ ❞❡♣t♥♦ ❂ ✷✵ t❤❡♥ s❛❧
✶✶
❡❧s❡
✶✷
✵
✶✸
❡♥❞✮ ❞❡♣❛rt❴✷✵✱
✶✹
s✉♠✭❝❛s❡
✶✺
✇❤❡♥ ❞❡♣t♥♦ ❂ ✸✵ t❤❡♥ s❛❧
✶✻
❡❧s❡
✶✼
✵
❡♥❞✮ ❞❡♣❛rt❴✸✵✱
✶✽
✶✾
s✉♠✭s❛❧✮ t♦t❛❧❴❥♦❜
✷✵
❢r♦♠ ❡♠♣
✷✶
❣r♦✉♣ ❜② ❥♦❜❀
✷✷
✲✲
✷✸ ❜❡❣✐♥
✷✹
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✷✺
✲✲
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭r✶✳❥♦❜⑤⑤✬ ✲ ❉❡♣❛rt✳ ✶✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✶✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✷✵✿ ✬⑤⑤
✷✼
r✶✳❞❡♣❛rt❴✷✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✸✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✸✵⑤⑤✬ ✲ ❚♦t❛❧✿ ✬⑤⑤
✷✽
r✶✳t♦t❛❧❴❥♦❜✮❀
✷✾
✲✲
218
Casa do Código
Capítulo 15. Funções condicionais
✸✵
❡♥❞ ❧♦♦♣❀
✸✶ ❡♥❞❀
✸✷ ✴
❈▲❊❘❑ ✲ ❉❡♣❛rt✳ ✶✵✿ ✶✸✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✶✾✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✾✺✵ ✲
❚♦t❛❧✿ ✹✶✺✵
❙❆▲❊❙▼❆◆ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✺✻✵✵ ✲
❚♦t❛❧✿ ✺✻✵✵
P❘❊❙■❉❊◆❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✺✵✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✺✵✵✵
▼❆◆❆●❊❘ ✲ ❉❡♣❛rt✳ ✶✵✿ ✷✹✺✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✷✾✼✺ ✲ ❉❡♣❛rt✳ ✸✵✿ ✷✽✺✵
✲ ❚♦t❛❧✿ ✽✷✼✺
❆◆❆▲❨❙❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✻✵✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✻✵✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Padrão Oracle:
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❥♦❜✱
✹
s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✶✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✶✵✱
✺
s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✷✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✷✵✱
✻
s✉♠✭❞❡❝♦❞❡✭❞❡♣t♥♦✱ ✸✵✱ s❛❧✱ ✵✮✮ ❞❡♣❛rt❴✸✵✱
✼
s✉♠✭s❛❧✮ t♦t❛❧❴❥♦❜
✽
❢r♦♠ ❡♠♣
✾
❣r♦✉♣ ❜② ❥♦❜❀
✶✵
✲✲
✶✶ ❜❡❣✐♥
✶✷
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭r✶✳❥♦❜⑤⑤✬ ✲ ❉❡♣❛rt✳ ✶✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✶✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✷✵✿ ✬⑤⑤
✶✺
r✶✳❞❡♣❛rt❴✷✵⑤⑤✬ ✲ ❉❡♣❛rt✳ ✸✵✿ ✬⑤⑤
r✶✳❞❡♣❛rt❴✸✵⑤⑤✬ ✲ ❚♦t❛❧✿ ✬⑤⑤
r✶✳t♦t❛❧❴❥♦❜✮❀
✶✻
✶✼
✲✲
✶✽
❡♥❞ ❧♦♦♣❀
219
Casa do Código
15.1. decode vs. case
✶✾ ❡♥❞❀
✷✵ ✴
❈▲❊❘❑ ✲ ❉❡♣❛rt✳ ✶✵✿ ✶✸✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✶✾✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✾✺✵ ✲
❚♦t❛❧✿ ✹✶✺✵
❙❆▲❊❙▼❆◆ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✺✻✵✵ ✲
❚♦t❛❧✿ ✺✻✵✵
P❘❊❙■❉❊◆❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✺✵✵✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✺✵✵✵
▼❆◆❆●❊❘ ✲ ❉❡♣❛rt✳ ✶✵✿ ✷✹✺✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✷✾✼✺ ✲ ❉❡♣❛rt✳ ✸✵✿ ✷✽✺✵
✲ ❚♦t❛❧✿ ✽✷✼✺
❆◆❆▲❨❙❚ ✲ ❉❡♣❛rt✳ ✶✵✿ ✵ ✲ ❉❡♣❛rt✳ ✷✵✿ ✻✵✵✵ ✲ ❉❡♣❛rt✳ ✸✵✿ ✵ ✲
❚♦t❛❧✿ ✻✵✵✵
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Exemplo 2
Padrão ANSI (também suportado pelo Oracle nas versões mais novas do
banco de dados):
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❡♥❛♠❡
✹
✱ ❥♦❜
✺
✱ ♠❣r
✻
✱
✼
❝❛s❡
✽
✇❤❡♥ ♠❣r ❂
✾
✇❤❡♥ ♠❣r ❂
✶✵
✇❤❡♥ ♠❣r ❂
✶✶
✇❤❡♥ ♠❣r ❂
✶✷
❡❧s❡
✶✸
✬❖❯❚❘❖❙✬
✶✹
❡♥❞ t✐♣♦
✶✺
❢r♦♠ ❡♠♣❀
✶✻
✶✼
✲✲
220
✼✾✵✷
✼✾✵✷
✼✽✸✾
✼✺✻✻
t❤❡♥
t❤❡♥
t❤❡♥
t❤❡♥
✬▼❊◆❙❆▲■❙❚❆✬
✬▼❊◆❙❆▲■❙❚❆✬
✬❈❖▼■❙❙■❖◆❆❉❖✬
✬▼❊◆❙❆▲✴❍❖❘■❙❚❆✬
Casa do Código
Capítulo 15. Funções condicionais
✶✽ ❜❡❣✐♥
✶✾
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✷✵
✲✲
✷✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ✲ ❈❛r❣♦✿
✬⑤⑤r✶✳❥♦❜⑤⑤✬ ✲ ●❡r❡♥t❡✿ ✬⑤⑤
✷✷
r✶✳♠❣r⑤⑤✬ ✲ ❚✐♣♦✿ ✬⑤⑤r✶✳t✐♣♦✮❀
✷✸
✲✲
✷✹
❡♥❞ ❧♦♦♣❀
✷✺ ❡♥❞❀
✷✻ ✴
◆♦♠❡✿ ❙▼■❚❍ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✾✵✷ ✲ ❚✐♣♦✿ ▼❊◆❙❆▲■❙❚❆
◆♦♠❡✿ ❆▲▲❊◆ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❲❆❘❉ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❏❖◆❊❙ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ▼❆❘❚■◆ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❇▲❆❑❊ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ❈▲❆❘❑ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ❙❈❖❚❚ ✲ ❈❛r❣♦✿ ❆◆❆▲❨❙❚ ✲ ●❡r❡♥t❡✿ ✼✺✻✻ ✲ ❚✐♣♦✿
▼❊◆❙❆▲✴❍❖❘■❙❚❆
◆♦♠❡✿ ❑■◆● ✲ ❈❛r❣♦✿ P❘❊❙■❉❊◆❚ ✲ ●❡r❡♥t❡✿ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❚❯❘◆❊❘ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❆❉❆▼❙ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✼✽✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❏❆▼❊❙ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❋❖❘❉ ✲ ❈❛r❣♦✿ ❆◆❆▲❨❙❚ ✲ ●❡r❡♥t❡✿ ✼✺✻✻ ✲ ❚✐♣♦✿
▼❊◆❙❆▲✴❍❖❘■❙❚❆
◆♦♠❡✿ ▼■▲▲❊❘ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✼✽✷ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
Padrão Oracle:
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❡♥❛♠❡
✹
✱❥♦❜
✺
✱♠❣r
✻
✱❞❡❝♦❞❡✭♠❣r✱✼✾✵✷✱✬▼❊◆❙❆▲■❙❚❆✬
✼
✱✼✽✸✾✱✬❈❖▼■❙❙■❖◆❆❉❖✬
221
15.1. decode vs. case
Casa do Código
✽
✱✼✺✻✻✱✬▼❊◆❙❆▲✴❍❖❘■❙❚❆✬
✾
✱✬❖❯❚❘❖❙✬✮ t✐♣♦
✶✵
❢r♦♠ ❡♠♣❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✶✹
✲✲
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡✿ ✬⑤⑤r✶✳❡♥❛♠❡⑤⑤✬ ✲
❈❛r❣♦✿ ✬⑤⑤r✶✳❥♦❜⑤⑤✬ ✲
●❡r❡♥t❡✿ ✬⑤⑤
r✶✳♠❣r⑤⑤✬ ✲ ❚✐♣♦✿ ✬⑤⑤r✶✳t✐♣♦✮❀
✶✻
✶✼
✲✲
✶✽
❡♥❞ ❧♦♦♣❀
✶✾ ❡♥❞❀
✷✵ ✴
◆♦♠❡✿ ❙▼■❚❍ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✾✵✷ ✲ ❚✐♣♦✿ ▼❊◆❙❆▲■❙❚❆
◆♦♠❡✿ ❆▲▲❊◆ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❲❆❘❉ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❏❖◆❊❙ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ▼❆❘❚■◆ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❇▲❆❑❊ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ❈▲❆❘❑ ✲ ❈❛r❣♦✿ ▼❆◆❆●❊❘ ✲ ●❡r❡♥t❡✿ ✼✽✸✾ ✲ ❚✐♣♦✿ ❈❖▼■❙❙■❖◆❆❉❖
◆♦♠❡✿ ❙❈❖❚❚ ✲ ❈❛r❣♦✿ ❆◆❆▲❨❙❚ ✲ ●❡r❡♥t❡✿ ✼✺✻✻ ✲ ❚✐♣♦✿
▼❊◆❙❆▲✴❍❖❘■❙❚❆
◆♦♠❡✿ ❑■◆● ✲ ❈❛r❣♦✿ P❘❊❙■❉❊◆❚ ✲ ●❡r❡♥t❡✿ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❚❯❘◆❊❘ ✲ ❈❛r❣♦✿ ❙❆▲❊❙▼❆◆ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❆❉❆▼❙ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✼✽✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❏❆▼❊❙ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✻✾✽ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
◆♦♠❡✿ ❋❖❘❉ ✲ ❈❛r❣♦✿ ❆◆❆▲❨❙❚ ✲ ●❡r❡♥t❡✿ ✼✺✻✻ ✲ ❚✐♣♦✿
▼❊◆❙❆▲✴❍❖❘■❙❚❆
◆♦♠❡✿ ▼■▲▲❊❘ ✲ ❈❛r❣♦✿ ❈▲❊❘❑ ✲ ●❡r❡♥t❡✿ ✼✼✽✷ ✲ ❚✐♣♦✿ ❖❯❚❘❖❙
P▲✴❙◗▲ ♣r♦❝❡❞✉r❡ s✉❝❝❡ss❢✉❧❧② ❝♦♠♣❧❡t❡❞✳
❙◗▲❃
A opção entre usar um ou outro vai depender da abrangência dos seus
programas. Se eles forem específicos para o uso em Oracle, o decode pode
222
Casa do Código
Capítulo 15. Funções condicionais
ser usado sem problemas. Inclusive, como pôde ser visto nos exemplos, ele
pode se tornar visualmente mais claro para o entendimento do código. Já,
se suas aplicações forem abrangentes no que diz respeito a operar em vários
bancos de dados, você terá que usar o padrão ANSI, ou seja, usar o case para
que eles funcionem em qualquer banco de dados, ou pelo menos naqueles que
seguem este padrão.
223
Capítulo 16
Programas armazenados
Até aqui, construímos programas em blocos chamados blocos anônimos.
Caso quiséssemos guardá-los, teríamos que salvá-los em um ou mais arquivos
em algum diretório no computador para não perdê-los. Quando quiséssemos
executá-los novamente, teríamos que resgatá-los do computador para então
executá-los em uma ferramenta, por exemplo, no SQL*Plus. Pois bem, agora
vamos aprender como gravar estes programas no banco de dados. isso nos
traz muitos benefícios e abre muitas possibilidades. A seguir vemos algumas
delas:
• Reaproveitamento de códigos: podemos escrever procedimentos e
funções que podem servir como base para as demais partes de um sistema. Por exemplo, podemos criar uma função para validação de números de CPF que possa ser utilizada em vários módulos do sistema,
16.1. procedures e functions
Casa do Código
como no módulo de RH ou de compras, ou seja, podemos ter um programa gravado no banco de dados ao qual todos podem ter acesso.
• Rapidez: tendo o programa armazenado no banco de dados, podemos
acessá-lo rapidamente, sem ter que utilizar chamadas externas a arquivos. outro ponto interessante é que as ferramentas de desenvolvimento
e análise do Oracle enxergam de forma nativa estes objetos armazenados.
• Controle de alterações: um programa armazenado no banco de dados
é muito mais fácil de ser alterado. É possível abri-lo e alterá-lo de forma
mais rápida, compilando e em seguida efetivando as alterações. Como
o programa está em um único lugar, os demais sistemas que o utilizam
enxergarão todas as alterações realizadas.
• Controle de acesso: através de concessões é possível limitar os acessos
a estes programas, permitindo-os a apenas alguns usuários.
• Modularização: veremos mais adiante que, pelo fato de estarem armazenados em um banco de dados, os programas podem ser agrupados
dentro de pacotes, o que permite que nós os organizemos e estruturemos de acordo com seus escopos, viabilizando a modularização do
sistema.
Os programas armazenados podem ser de três tipos: procedimentos (
procedures), funções ( functions) e pacotes ( packages). A escolha
de um ou de outro vai depender da necessidade ou da característica do programa. Trataremos neste capítulo de procedures e functions. Falaremos
sobre packages no capítulo a seguir.
16.1
procedures e functions
Para que um programa seja armazenado em um banco de dados, ele precisa
receber um nome único, chamado de identificador, que será sua identificação
dentro do banco de dados. É por ele que vamos manipulá-lo, localizá-lo no
banco de dados, ou executá-lo. A nomenclatura utilizada para nomear este
226
Casa do Código
Capítulo 16. Programas armazenados
identificador segue as mesmas regras dos identificadores de variáveis e constantes vistos em capítulos anteriores: ele pode ter um tamanho máximo de
30 caracteres, que se restringem a alguns caracteres especiais, na sua maioria,
caracteres alfanuméricos; e deve iniciar por uma letra.
Depois de criados, os programas armazenados podem ser executados
através de ferramentas tais como SQL*Plus, Oracle Forms, Oracle Reports
etc., bem como podem ser chamados por outros programas armazenados ou
por blocos PL/SQL anônimos.
Também temos a opção de criar procedures e functions dentro de
blocos PL/SQL anônimos ou dentro de outras procedures, functions,
triggers ou packages. Contudo, suas definições não ficam armazenadas
dentro do dicionário de objetos do Oracle, apenas dentro do objeto onde estão
sendo criadas.
Conforme dito anteriormente, a escolha do tipo no momento de criar um
programa armazenado depende da necessidade, ou melhor, do escopo em
que se encaixa. Por exemplo, quando queremos que um programa retorne
uma informação, podemos criá-lo como function. Este tipo de programa
armazenado, além de executar alguma ação, pode ainda retornar um tipo de
informação para o programa chamador ou para a ferramenta que o executou.
Um exemplo seria uma função que retornasse se o número de CPF é válido
ou não.
Caso não seja necessário retornar uma informação, podemos criar o programa como sendo uma procedure. Neste caso, ela executa suas ações
como um programa qualquer, mas não retorna nada (veremos mais adiante
que é possível, sim, ter retorno através de procedures). O que deve ficar claro é
que funções sempre devem retornar um valor, já procedimentos não possuem
esta obrigatoriedade. Veja a seguir um exemplo de procedure.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ❝❛❧❝
✷
✲✲
✸
①✶ ♥✉♠❜❡r
✿❂
✹
①✷ ♥✉♠❜❡r
✿❂
✺
♦♣ ✈❛r❝❤❛r✷✭✶✮ ✿❂
✻
r❡s ♥✉♠❜❡r❀
✼
✲✲
✽ ❜❡❣✐♥
✐s
✶✵❀
✺❀
✬✰✬❀
227
16.1. procedures e functions
Casa do Código
✾
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
✶✶
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
✶✷
r❡s ✿❂ ①✶ ✯ ①✷❀
✶✸
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✶✹
✐❢ ①✷ ❂ ✵ t❤❡♥
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
✶✻
❡❧s❡
✶✼
r❡s ✿❂ ①✶ ✴ ①✷❀
✶✽
❡♥❞ ✐❢❀
✶✾
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
✷✵
r❡s ✿❂ ①✶ ✲ ①✷❀
✷✶
✐❢ r❡s ❂ ✵ t❤❡♥
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
✷✸
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
✷✺
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
✷✼
❡♥❞ ✐❢❀
✷✽
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
✷✾
r❡s ✿❂ ①✶ ✰ ①✷❀
✸✵
❡❧s❡
✸✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
✸✷
❡♥❞ ✐❢❀
✸✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✸✹ ❡♥❞❀
✸✺ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
O procedimento anterior tem o objetivo de realizar cálculos numéricos.
Note que basicamente, o que muda de uma procedure para um bloco anônimo é que nela temos um cabeçalho onde informamos um identificador,
neste caso, calc, que precede o comando create procedure e antecede
o comando is que indica o início do procedimento. Após isso, temos basicamente um bloco PL/SQL comum ao que já vimos até aqui. O mesmo acontece
228
Casa do Código
Capítulo 16. Programas armazenados
com a criação de funções.
Agora vejamos um exemplo de function.
❙◗▲❃ ❝r❡❛t❡ ❢✉♥❝t✐♦♥ ✈❛❧✐❞❛❴❝♣❢ r❡t✉r♥ ✈❛r❝❤❛r✷ ✐s
✷
✲✲
✸
♠❴t♦t❛❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✹
♠❴❞✐❣✐t♦ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✺
❝♣❢
✈❛r❝❤❛r✷✭✺✵✮ ❞❡❢❛✉❧t ✬✵✷✹✶✶✽✹✽✹✸✵✬❀
✻
✲✲
✼ ❜❡❣✐♥
✽
❢♦r ✐ ✐♥ ✶✳✳✾ ❧♦♦♣
✾
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✶ ✲ ✐✮❀
✶✵
❡♥❞ ❧♦♦♣❀
✶✶
✲✲
✶✷
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
✶✸
✲✲
✶✹
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✶✺
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✶✻
❡♥❞ ✐❢❀
✶✼
✲✲
✶✽
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✵✱ ✶✮ t❤❡♥
✶✾
r❡t✉r♥ ✬■✬❀
✷✵
❡♥❞ ✐❢❀
✷✶
✲✲
✷✷
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✷✸
♠❴t♦t❛❧ ✿❂ ✵❀
✷✹
✲✲
✷✺
❢♦r ✐ ✐♥ ✶✳✳✶✵ ❧♦♦♣
✷✻
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✷ ✲ ✐✮❀
✷✼
❡♥❞ ❧♦♦♣❀
✷✽
✲✲
✷✾
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
✸✵
✲✲
✸✶
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✸✷
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✸✸
❡♥❞ ✐❢❀
✸✹
✲✲
✸✺
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✶✱ ✶✮ t❤❡♥
✸✻
r❡t✉r♥ ✬■✬❀
229
16.1. procedures e functions
Casa do Código
✸✼
❡♥❞ ✐❢❀
✸✽
✲✲
✸✾
r❡t✉r♥ ✬❱✬❀
✹✵
✲✲
✹✶ ❡♥❞ ✈❛❧✐❞❛❴❝♣❢❀
✹✷ ✴
❋✉♥çã♦ ❝r✐❛❞❛✳
❙◗▲❃
Essa função tem o objetivo de validar um número de CPF e retornar falso
ou verdadeiro, dependendo da validação. Igualmente às procedures, têm-se
um cabeçalho onde definimos um identificador para a função, neste exemplo, valida_cpf, que precede o comando create function e antecede
os comandos return, seguido pelo tipo de dado a ser retornado, e is indicando o início da função. Logo após, temos a codificação da função dentro
de um bloco PL/SQL.
Como comentamos anteriormente, procedures e functions também podem ser criadas dentro de blocos PL/SQL anônimos ou dentro de objetos. A seguir, utilizamos os mesmos objetos dos exemplos anteriores para
mostrar como isso é feito.
Procedure criada no bloco:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
♣r♦❝❡❞✉r❡ ❝❛❧❝ ✐s
✹
✲✲
✺
①✶
♥✉♠❜❡r
✿❂ ✶✵❀
✻
①✷
♥✉♠❜❡r
✿❂ ✺❀
✼
♦♣
✈❛r❝❤❛r✷✭✶✮ ✿❂ ✬✰✬❀
✽
r❡s ♥✉♠❜❡r❀
✾
✲✲
✶✵
❜❡❣✐♥
✶✶
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
✶✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
✶✸
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
✶✹
r❡s ✿❂ ①✶ ✯ ①✷❀
230
Casa do Código
Capítulo 16. Programas armazenados
✶✺
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✶✻
✐❢ ①✷ ❂ ✵ t❤❡♥
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
✶✽
❡❧s❡
✶✾
r❡s ✿❂ ①✶ ✴ ①✷❀
✷✵
❡♥❞ ✐❢❀
✷✶
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
✷✷
r❡s ✿❂ ①✶ ✲ ①✷❀
✷✸
✐❢ r❡s ❂ ✵ t❤❡♥
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
✷✺
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
✷✼
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✷✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
✷✾
❡♥❞ ✐❢❀
✸✵
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
✸✶
r❡s ✿❂ ①✶ ✰ ①✷❀
✸✷
❡❧s❡
✸✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
✸✹
❡♥❞ ✐❢❀
✸✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✸✻
❡♥❞❀
✸✼
✲✲
✸✽ ❜❡❣✐♥
✸✾
❝❛❧❝❀
✹✵ ❡♥❞❀
✹✶ ✴
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Nesse exemplo, é possível verificar que a procedure foi criada no nível
do bloco, ou seja, ele existe apenas dentro do bloco e não está armazenada
no banco de dados. Logo, caso seja de nossa vontade utilizá-la novamente,
teremos que salvar todo o código do bloco em um arquivo externo. Desta
forma, também não é possível que outros programas usem-na. Note também
que nestes casos não usamos o comando create. Começamos direto pelo
231
16.1. procedures e functions
Casa do Código
tipo do programa, a procedure.
Function criada em uma procedure.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
r❡s ✈❛r❝❤❛r✷✭✶✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✹
✲✲
✺
❢✉♥❝t✐♦♥ ✈❛❧✐❞❛❴❝♣❢ r❡t✉r♥ ✈❛r❝❤❛r✷ ✐s
✻
✲✲
✼
♠❴t♦t❛❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✽
♠❴❞✐❣✐t♦ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✾
❝♣❢
✈❛r❝❤❛r✷✭✺✵✮ ❞❡❢❛✉❧t ✬✵✷✹✶✶✽✹✽✹✸✵✬❀
✶✵
✲✲
✶✶
❜❡❣✐♥
✶✷
❢♦r ✐ ✐♥ ✶✳✳✾ ❧♦♦♣
✶✸
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✶ ✲ ✐✮❀
✶✹
❡♥❞ ❧♦♦♣❀
✶✺
✲✲
✶✻
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
✶✼
✲✲
✶✽
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✶✾
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✷✵
❡♥❞ ✐❢❀
✷✶
✲✲
✷✷
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✵✱ ✶✮ t❤❡♥
✷✸
r❡t✉r♥ ✬■✬❀
✷✹
❡♥❞ ✐❢❀
✷✺
✲✲
✷✻
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✷✼
♠❴t♦t❛❧ ✿❂ ✵❀
✷✽
✲✲
✷✾
❢♦r ✐ ✐♥ ✶✳✳✶✵ ❧♦♦♣
✸✵
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✷ ✲ ✐✮❀
✸✶
❡♥❞ ❧♦♦♣❀
✸✷
✲✲
✸✸
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
✸✹
✲✲
✸✺
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✸✻
♠❴❞✐❣✐t♦ ✿❂ ✵❀
232
Casa do Código
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
✺✷
✺✸
✺✹
✺✺
✺✻
✺✼
❈P❋
Capítulo 16. Programas armazenados
❡♥❞ ✐❢❀
✲✲
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✶✱ ✶✮ t❤❡♥
r❡t✉r♥ ✬■✬❀
❡♥❞ ✐❢❀
✲✲
r❡t✉r♥ ✬❱✬❀
✲✲
❡♥❞ ✈❛❧✐❞❛❴❝♣❢❀
✲✲
❜❡❣✐♥
r❡s ✿❂ ✈❛❧✐❞❛❴❝♣❢❀
✲✲
✐❢ r❡s ❂ ✬❱✬ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✈á❧✐❞♦✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✐♥✈á❧✐❞♦✬✮❀
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
✐♥✈á❧✐❞♦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
O mesmo acontece aqui com o exemplo desta função. Como ela está criada no nível do bloco, ela não se encontra armazenada no banco de dados.
Note também que nestes casos não usamos o comando create. Começamos direto pelo tipo do programa, a function.
Uma procedure pode ser chamada de dentro de um bloco PL/SQL, de
dentro de programas em Oracle Forms, Oracle Reports etc. Entretanto, elas
não podem ser chamadas através de um comando SQL. Já as functions
podem ser chamadas também de dentro de comandos SQL, pelo fato de elas
retornarem um valor. Contudo, há algumas restrições, por exemplo, ela não
pode ter em sua composição comandos DML, DDL e DCL, apenas selects.
outra característica das functions é a recursividade, com a qual podemos
233
16.1. procedures e functions
Casa do Código
criar uma função que chama ela mesma.
Os procedimentos podem ser chamados de duas formas. Se estivermos trabalhando com SQL*Plus podemos chamá-la através do comando
execute, e através de um bloco PL/SQL anônimo ou programa armazenado.
Veja os dois exemplos de chamada a seguir.
❙◗▲❃ ❡①❡❝✉t❡ ❝❛❧❝❀
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
❙◗▲❃ ❜❡❣✐♥
✷
❝❛❧❝❀
✸ ❡♥❞❀
✹ ✴
❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✶✺
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Assim como nos procedimentos, as funções também podem ser chamadas de duas formas. Uma através de blocos PL/SQL anônimos ou programas
armazenados, e através de comandos SQL ( select, insert, delete ou
update). Vale ressaltar que para chamadas via comando SQL existem algumas restrições. Veja os dois exemplos de chamada a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
r❡s ✈❛r❝❤❛r✷✭✶✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✹
✲✲
✺ ❜❡❣✐♥
✻
r❡s ✿❂ ✈❛❧✐❞❛❴❝♣❢❀
✼
✲✲
✽
✐❢ r❡s ❂ ✬❱✬ t❤❡♥
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✈á❧✐❞♦✬✮❀
✶✵
❡❧s❡
234
Casa do Código
Capítulo 16. Programas armazenados
✶✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✐♥✈á❧✐❞♦✬✮❀
✶✷
❡♥❞ ✐❢❀
✶✸
✲✲
✶✹ ❡♥❞❀
✶✺ ✴
❈P❋ ✐♥✈á❧✐❞♦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
❙◗▲❃ s❡❧❡❝t ❞❡❝♦❞❡✭✈❛❧✐❞❛❴❝♣❢✱✬❱✬✱✬❱á❧✐❞♦✬✱✬✐♥✈á❧✐❞♦✬✮ ❈P❋
❢r♦♠ ❞✉❛❧❀
❈P❋
✲✲✲✲✲✲✲✲✲
✐♥✈á❧✐❞♦
❙◗▲❃
Concedendo acesso a procedures e functions
Uma vantagem no uso de procedures e functions está relacionada à
restrição de acesso. Objetos criados no banco de dados precisam de permissão
para acesso, caso quem os queira acessar não seja o dono ou DBA do sistema.
Para dar acesso a procedures e functions utilizamos o comando grant
execute.
❙◗▲❃ ❣r❛♥t ❡①❡❝✉t❡ ♦♥ ❝❛❧❝ t♦ ♣✉❜❧✐❝❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃ ❣r❛♥t ❡①❡❝✉t❡ ♦♥ ✈❛❧✐❞❛❴❝♣❢ t♦ ❚❙◗▲✷❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃
Também é possível criarmos sinônimos para facilitar o acesso. Os sinônimos podem ser específicos a um usuário ou público. Vale ressaltar que eles
235
16.2. Uso do comando replace
Casa do Código
não dão acesso, apenas permitem criar um alias para o objeto.
❙◗▲❃ ❝r❡❛t❡ ♣✉❜❧✐❝ s②♥♦♥②♠ ❝❛❧❝❴✈❛❧♦r❡s ❢♦r tsq❧✳❝❛❧❝❀
❙✐♥ô♥✐♠♦ ❝r✐❛❞♦✳
❙◗▲❃ ❝r❡❛t❡ s②♥♦♥②♠ tsq❧✷✳✈❛❧✐❞❛❴❝♣❢ ❢♦r tsq❧✳✈❛❧✐❞❛❴❝♣❢❀
❙✐♥ô♥✐♠♦ ❝r✐❛❞♦✳
❙◗▲❃
Note que podemos dar grants e criar sinônimos para o usuário
public. Quando fazemos desta forma, todos os usuários do banco de dados terão acesso ao referido objeto.
16.2
Uso do comando replace
Quando precisamos dar manutenção em procedures e functions, podemos utilizar a cláusula replace para garantir que algumas definições sejam preservadas. Como esses objetos possuem um identificador único, não
é possível criar outro com o mesmo nome. Logo, para recriarmos um objeto
como este nós podemos utilizar a cláusula replace. Caso contrário, seria
necessário excluir o objeto existente e criá-lo novamente. Com isto, informações referentes a permissões de acesso seriam excluídas também. Já com o
comando replace, este tipo de informação permanece, assim como a marcação de objetos dependentes para recompilação.
Com relação à dependência de objetos, da qual falaremos mais à frente,
só para um entendimento prévio, é comum termos programas que chamam
outros programas, acabando por criar dependências entre eles, o que pode
invalidar todo um conjunto de objetos caso um seja excluído ou invalidado.
Em alguns casos, o Oracle poderá recompilar objetos, automaticamente (dependendo do nível de dependência), quando são recriados, e não excluídos e
criados logo em seguida.
outra vantagem do comando replace é a possibilidade de criar objetos mesmo com erros de sintaxe em seus códigos. Nesse caso, eles perma236
Casa do Código
Capítulo 16. Programas armazenados
necem inválidos enquanto tais erros existirem. A seguir o uso do comando
replace.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ❝❛❧❝ ✐s
✲✲
①✶ ♥✉♠❜❡r
✿❂ ✶✵❀
①✷ ♥✉♠❜❡r
✿❂ ✺❀
♦♣ ✈❛r❝❤❛r✷✭✶✮ ✿❂ ✬✰✬❀
r❡s ♥✉♠❜❡r❀
✲✲
❜❡❣✐♥
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
r❡s ✿❂ ①✶ ✯ ①✷❀
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✐❢ ①✷ ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
❡❧s❡
r❡s ✿❂ ①✶ ✴ ①✷❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
r❡s ✿❂ ①✶ ✲ ①✷❀
✐❢ r❡s ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
r❡s ✿❂ ①✶ ✰ ①✷❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
❡♥❞ ✐❢❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
❡♥❞❀
✴
237
16.3. Recompilando programas armazenados
Casa do Código
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
16.3
Recompilando programas armazenados
Quando alteramos uma procedure ou function no banco de dados, pode
acontecer de termos que compilá-la novamente. Para isso, utilizamos o comando alter. Veja os exemplos:
❙◗▲❃ ❛❧t❡r ♣r♦❝❡❞✉r❡ ❝❛❧❝ ❝♦♠♣✐❧❡❀
Pr♦❝❡❞✐♠❡♥t♦ ❛❧t❡r❛❞♦✳
❙◗▲❃ ❛❧t❡r ❢✉♥❝t✐♦♥ ✈❛❧✐❞❛❴❝♣❢ ❝♦♠♣✐❧❡❀
❋✉♥çã♦ ❛❧t❡r❛❞❛✳
❙◗▲❃
16.4 Recuperando informações
Para visualizar informações referentes a procedures e functions utilize
as views user_objects, all_objects ou dba_objects. Nesta view
constam informações como STATUS e data de criação do objeto.
❙◗▲❃ s❡❧❡❝t ♦✇♥❡r✱ ♦❜❥❡❝t❴t②♣❡✱ st❛t✉s✱ ❝r❡❛t❡❞✱ ❧❛st❴❞❞❧❴t✐♠❡
✷ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts ✇❤❡r❡ ♦❜❥❡❝t❴♥❛♠❡ ❂ ✬❈❆▲❈✬❀
❖❲◆❊❘
❖❇❏❊❈❚❴❚❨P❊
❙❚❆❚❯❙
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲
❚❙◗▲
♣r♦❝❡❞✉r❡
❱❆▲■❉
❝r❡❛t❡❉ ▲❆❙❚❴❉❉▲
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲
✷✺✴✶✶✴✶✶ ✷✺✴✶✶✴✶✶
❙◗▲❃
238
Casa do Código
Capítulo 16. Programas armazenados
Outra forma de recuperar dados referentes a procedures e functions
é utilizando o comando describe. Este comando mostra informações referentes a estes objetos, como dados do cabeçalho e parâmetros existentes.
❙◗▲❃ ❞❡s❝ ❝❛❧❝
♣r♦❝❡❞✉r❡ ❝❛❧❝
◆♦♠❡ ❞♦ ❆r❣✉♠❡♥t♦
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❳✶
❳✷
❖P
❘❊❙
❚✐♣♦
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
◆❯▼❇❊❘
◆❯▼❇❊❘
❱❆❘❈❍❆❘✷
❱❆❘❈❍❆❘✷
✐♥✴♦✉t ❉❡❢❛✉❧t❄
✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲
✐♥
✐♥
✐♥
♦✉t
❙◗▲❃
16.5 Recuperando códigos
Já para visualizar o código dos objetos armazenados no banco de dados, utilize as views user_source, all_source ou dba_source.
❙◗▲❃
❙◗▲❃
❙◗▲❃
✷
❝♦❧✉♠♥ t❡①t ❢♦r♠❛t ❛✶✵✵
s❡t ♣❛❣❡s ✶✵✵✵
s❡❧❡❝t ❧✐♥❡✱ t❡①t
❢r♦♠ ❛❧❧❴s♦✉r❝❡ ✇❤❡r❡ ♥❛♠❡ ❂ ✬❈❆▲❈✬❀
▲✐♥❊ ❚❊❳❚
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶ ♣r♦❝❡❞✉r❡ ❝❛❧❝ ✐s
✷
✲✲
✸
①✶ ♥✉♠❜❡r
✿❂ ✶✵❀
✹
①✷ ♥✉♠❜❡r
✿❂ ✺❀
239
16.6. Visualizando erros de compilação
Casa do Código
✺
♦♣ ✈❛r❝❤❛r✷✭✶✮ ✿❂ ✬✰✬❀
✻
r❡s ♥✉♠❜❡r❀
✼
✲✲
✽ ❜❡❣✐♥
✾
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
✶✶
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
✶✷
r❡s ✿❂ ①✶ ✯ ①✷❀
✶✸
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✶✹
✐❢ ①✷ ❂ ✵ t❤❡♥
✶✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
✶✻
❡❧s❡
✶✼
r❡s ✿❂ ①✶ ✴ ①✷❀
✶✽
❡♥❞ ✐❢❀
✶✾
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
✷✵
r❡s ✿❂ ①✶ ✲ ①✷❀
✷✶
✐❢ r❡s ❂ ✵ t❤❡♥
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
✷✸
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
✷✺
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
✷✼
❡♥❞ ✐❢❀
✷✽
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
✷✾
r❡s ✿❂ ①✶ ✰ ①✷❀
✸✵
❡❧s❡
✸✶
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
✸✷
❡♥❞ ✐❢❀
✸✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
✸✹ ❡♥❞❀
✸✹ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
16.6 Visualizando erros de compilação
Para visualizar erros de compilação, use o comando show error.
240
Casa do Código
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
Capítulo 16. Programas armazenados
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ❝❛❧❝ ✐s
✲✲
①✶ ♥✉♠❜❡r
✿❂ ✶✵❀
①✷ ♥✉♠❜❡r
✿❂ ✺❀
♦♣ ✈❛r❝❤❛r✷✭✶✮ ✿❂ ✬✰✬❀
r❡s ♥✉♠❜❡r❀
✲✲
❜❡❣✐♥
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦✿ ✵✬✮❀
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
r❡s ✿❂ ①✶ ✯ ①✷❀
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✐❢ ①✷ ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
❡❧s❡
r❡s ✿❂ ①✶ ✴ ①✷❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
r❡s ✿❂ ①✶ ✲ ①✷❀
✐❢ r❡s ❂ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✦✬✮❀
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✦✬✮❀
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r❧ ❛ ③❡r♦✦✬✮❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
r❡s ✿❂ ①✶ ✰ ①✷❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬✮❀
❡♥❞ ✐❢❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❞♦ ❝á❧❝✉❧♦✿ ✬⑤⑤r❡s✮❀
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡✳
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
241
Casa do Código
16.6. Visualizando erros de compilação
❙◗▲❃ s❤♦✇ ❡rr♦r
❊rr♦s ♣❛r❛ ♣r♦❝❡❞✉r❡ ❈❆▲❈✿
▲✐♥❊✴❈❖▲ ❊❘❘❖❘
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✸✹✴✸
P▲❙✲✵✵✶✵✸✿ ❊♥❝♦♥tr❛❞♦ ♦ sí♠❜♦❧♦ ✧❀✧ q✉❛♥❞♦ ✉♠ ❞♦s
s❡❣✉✐♥t❡s sí♠❜♦❧♦s ❡r❛ ❡s♣❡r❛❞♦✿
❜❡❣✐♥ ❝❛s❡ ❞❡❝❧❛r❡ ❡♥❞ ❡①❝❡♣t✐♦♥ ❡①✐t ❢♦r ❣♦t♦ ✐❢ ❧♦♦♣
♠♦❞ ♥✉❧❧ ♣r❛❣♠❛ r❛✐s❡ r❡t✉r♥ s❡❧❡❝t ✉♣❞❛t❡ ✇❤✐❧❡ ✇✐t❤
❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r❃
❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r ❞❡❧✐♠✐t❛❞♦ ♣♦r ❛s♣❛s ❞✉♣❧❛s❃
❁✉♠❛ ✈❛r✐á✈❡❧ ❞❡ ❧✐❣❛çã♦❃ ❁❁ ❝❧♦s❡ ❝✉rr❡♥t ❞❡❧❡t❡ ❢❡t❝❤
❧♦❝❦ ✐♥s❡rt ♦♣❡♥ r♦❧❧❜❛❝❦ s❛✈❡♣♦✐♥t s❡t sq❧ ❡①❡❝✉t❡
❝♦♠♠✐t ❢♦r❛❧❧ ♠❡r❣❡ ♣✐♣❡
❖ sí♠❜♦❧♦ ✧❡①✐t✧ ❢♦✐ s✉❜st✐t✉í❞♦ ♣♦r ✧❀✧ ♣❛r❛ ❝♦♥t✐♥✉❛r✳
❙◗▲❃
O comando basicamente mostra duas colunas. A primeira com a linha e a coluna onde ocorreu o erro, e a segunda, a coluna com a descrição.
Este erro também pode ser encontrado através das views user_errors,
all_errors e dba_errors.
❙◗▲❃ s❡❧❡❝t ❧✐♥❡
✷
✱♣♦s✐t✐♦♥
✸
✱t❡①t
✹ ❢r♦♠ ✉s❡r❴❡rr♦rs
✺ ✇❤❡r❡ ♥❛♠❡ ❂ ✬❈❆▲❈✬❀
▲✐♥❊ P❖❙■❚■❖◆ ❚❊❳❚
✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✸✹
✸ P▲❙✲✵✵✶✵✸✿ ❊♥❝♦♥tr❛❞♦ ♦ sí♠❜♦❧♦ ✧❀✧ q✉❛♥❞♦ ✉♠
❞♦s s❡❣✉✐♥t❡s sí♠❜♦❧♦s ❡r❛ ❡s♣❡r❛❞♦✿
❜❡❣✐♥ ❝❛s❡ ❞❡❝❧❛r❡ ❡♥❞ ❡①❝❡♣t✐♦♥ ❡①✐t
❢♦r ❣♦t♦ ✐❢ ❧♦♦♣ ♠♦❞ ♥✉❧❧ ♣r❛❣♠❛ r❛✐s❡
r❡t✉r♥ s❡❧❡❝t ✉♣❞❛t❡ ✇❤✐❧❡ ✇✐t❤
❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r❃ ❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r
❞❡❧✐♠✐t❛❞♦ ♣♦r ❛s♣❛s ❞✉♣❧❛s❃
242
Casa do Código
Capítulo 16. Programas armazenados
❁✉♠❛ ✈❛r✐á✈❡❧ ❞❡ ❧✐❣❛çã♦❃ ❁❁ ❝❧♦s❡
❝✉rr❡♥t ❞❡❧❡t❡ ❢❡t❝❤
❧♦❝❦ ✐♥s❡rt ♦♣❡♥ r♦❧❧❜❛❝❦ s❛✈❡♣♦✐♥t
s❡tsq❧ ❡①❡❝✉t❡ ❝♦♠♠✐t
❢♦r❛❧❧ ♠❡r❣❡ ♣✐♣❡
❖ sí♠❜♦❧♦ ✧❡①✐t✧ ❢♦✐ s✉❜st✐t✉í❞♦ ♣♦r ✧❀✧
♣❛r❛ ❝♦♥t✐♥✉❛r✳
❙◗▲❃
16.7
Passando parâmetros
Programas armazenados, como procedures e functions, permitem trabalhar com passagem de parâmetros. Quando criamos um procedimento ou
uma função, podemos especificar parâmetros de entrada e saída para que valores possam ser levados para dentro destes programas ou recuperados deles.
Os parâmetros podem ser do tipo in, out ou in out. in define que
se trata de um parâmetro de entrada. Já um parâmetro do tipo out indica
que ele é de saída. Logo, in out indica um parâmetro de entrada e saída.
Quando estamos falando de parâmetros de entrada ( in), isso quer dizer que os valores contidos neles podem ser atribuídos a outras variáveis ou
parâmetros existentes dentro da procedure ou function. Contudo, não
podemos atribuir valores a eles. Já quando estamos falando dos parâmetros
de saída ( out), estamos dizendo que os valores destes parâmetros podem
ser alterados, mas não atribuídos a outras variáveis ou parâmetros existentes
dentro destes objetos.
Logo, quando temos parâmetros do tipo in out sendo usados, isso indica que tanto podemos atribuir valores a ele como também atribuir seus valores a outras variáveis ou parâmetros existentes dentro dos objetos. Veja isso
na prática.
♣r♦❝❡❞✉r❡ ❡①❡♠♣❧♦✭ ♣❛r❛♠✶ ✐♥
♥✉♠❜❡r
✱♣❛r❛♠✷ ♦✉t
♥✉♠❜❡r
✱♣❛r❛♠✸ ✐♥ ♦✉t ♥✉♠❜❡r✮ ✐s
✲✲
243
16.7. Passando parâmetros
① ♥✉♠❜❡r❀
② ♥✉♠❜❡r❀
③ ♥✉♠❜❡r❀
✲✲
❜❡❣✐♥
✲✲
① ✿❂ ♣❛r❛♠✶❀
♣❛r❛♠✶ ✿❂ ①❀
✲✲
② ✿❂ ♣❛r❛♠✷❀
♣❛r❛♠✷ ✿❂ ②❀
✲✲
③ ✿❂ ♣❛r❛♠✸❀
♣❛r❛♠✸ ✿❂ ③❀
✲✲
❡♥❞❀
✴
Casa do Código
✲✲ ✉s♦ ❝♦rr❡t♦
✲✲ ✉s♦ ✐♥❝♦rr❡t♦
✲✲ ✉s♦ ✐♥❝♦rr❡t♦
✲✲ ✉s♦ ❝♦rr❡t♦
✲✲ ✉s♦ ❝♦rr❡t♦
✲✲ ✉s♦ ❝♦rr❡t♦
Nota: quando não informamos o tipo do parâmetro, por padrão, ele
será do tipo in.
O uso de parâmetros em programas armazenados pode tornar nossos
programas muito mais flexíveis, possibilitando o reaproveitamento de código.
A seguir, são mostrados os mesmos exemplos de procedures e functions
anteriores, mas agora recriados utilizando passagem de parâmetros.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ❝❛❧❝ ✭ ①✶ ✐♥ ♥✉♠❜❡r
✷
✱①✷ ✐♥ ♥✉♠❜❡r
✸
✱♦♣ ✐♥ ✈❛r❝❤❛r✷
✹
✱r❡s ♦✉t ✈❛r❝❤❛r✷✮ ✐s
✺
✲✲
✻ ❜❡❣✐♥
✼
✲✲
✽
✐❢ ✭①✶ ✰ ①✷✮ ❂ ✵ t❤❡♥
✾
r❡s ✿❂ ✵❀
✶✵
❡❧s✐❢ ♦♣ ❂ ✬✯✬ t❤❡♥
✶✶
r❡s ✿❂ ①✶ ✯ ①✷❀
244
Casa do Código
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
Capítulo 16. Programas armazenados
❡❧s✐❢ ♦♣ ❂ ✬✴✬ t❤❡♥
✐❢ ①✷ ❂ ✵ t❤❡♥
r❡s ✿❂ ✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬❀
❡❧s❡
r❡s ✿❂ ①✶ ✴ ①✷❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✲✬ t❤❡♥
r❡s ✿❂ ①✶ ✲ ①✷❀
✐❢ r❡s ❂ ✵ t❤❡♥
r❡s ✿❂ ✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✿ ✬⑤⑤r❡s❀
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
r❡s ✿❂ ✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✿ ✬⑤⑤r❡s❀
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
r❡s ✿❂ ✬❘❡s✉❧t❛❞♦ ♠❛✐♦r q✉❡ ③❡r♦✿ ✬⑤⑤r❡s❀
❡♥❞ ✐❢❀
❡❧s✐❢ ♦♣ ❂ ✬✰✬ t❤❡♥
r❡s ✿❂ ①✶ ✰ ①✷❀
❡❧s❡
r❡s ✿❂ ✬❖♣❡r❛❞♦r ✐♥✈á❧✐❞♦✦✬❀
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Executando calc:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇r❡s ✈❛r❝❤❛r✷✭✶✵✵✮❀
✸ ❜❡❣✐♥
✹
❝❛❧❝ ✭ ①✶ ❂❃ ✶✵
✺
✱①✷ ❂❃ ✺
✻
✱♦♣ ❂❃ ✬✯✬
✼
✱r❡s ❂❃ ✇r❡s✮❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❈❛❧❝ ✶✿ ✬⑤⑤✇r❡s✮❀
✶✵
✲✲
245
16.7. Passando parâmetros
Casa do Código
✶✶
❝❛❧❝ ✭ ✶✵
✱✺
✶✷
✱✬✴✬
✶✸
✶✹
✱✇r❡s✮❀
✶✺
✲✲
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❘❡s✉❧t❛❞♦ ❈❛❧❝ ✷✿ ✬⑤⑤✇r❡s✮❀
✶✼
✲✲
✶✽ ❡♥❞❀
✶✾ ✴
❘❡s✉❧t❛❞♦ ❈❛❧❝ ✶✿ ✺✵
❘❡s✉❧t❛❞♦ ❈❛❧❝ ✷✿ ✷
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Perceba que nesta execução chamamos duas vezes a procedure. A primeira usando a passagem de parâmetros nomeada, e a segunda sem nomeação. Quando informamos os parâmetros no cabeçalho do programa, o Oracle
toma como ordenação a ordem em que os dispomos. Todavia, quando executamos tal programa precisamos respeitar esta ordem. Portanto, quando nomeamos a passagem de parâmetros, no momento da execução do programa,
não precisamos necessariamente informá-los na ordem com a qual foram definidos, basta apenas informar seus nomes e os respectivos valores a serem
atribuídos.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ❢✉♥❝t✐♦♥ ✈❛❧✐❞❛❴❝♣❢ ✭❝♣❢ ✐♥ ❝❤❛r✮ r❡t✉r♥
✈❛r❝❤❛r✷ ✐s
✷
✲✲
✸
♠❴t♦t❛❧ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✹
♠❴❞✐❣✐t♦ ♥✉♠❜❡r
❞❡❢❛✉❧t ✵❀
✺
✲✲
✻ ❜❡❣✐♥
✼
❢♦r ✐ ✐♥ ✶✳✳✾ ❧♦♦♣
✽
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✶ ✲ ✐✮❀
✾
❡♥❞ ❧♦♦♣❀
✶✵
✲✲
✶✶
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
246
Casa do Código
Capítulo 16. Programas armazenados
✶✷
✲✲
✶✸
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✶✹
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✶✺
❡♥❞ ✐❢❀
✶✻
✲✲
✶✼
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✵✱ ✶✮ t❤❡♥
✶✽
r❡t✉r♥ ✬■✬❀
✶✾
❡♥❞ ✐❢❀
✷✵
✲✲
✷✶
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✷✷
♠❴t♦t❛❧ ✿❂ ✵❀
✷✸
✲✲
✷✹
❢♦r ✐ ✐♥ ✶✳✳✶✵ ❧♦♦♣
✷✺
♠❴t♦t❛❧ ✿❂ ♠❴t♦t❛❧ ✰ s✉❜str ✭❝♣❢✱ ✐✱ ✶✮ ✯ ✭✶✷ ✲ ✐✮❀
✷✻
❡♥❞ ❧♦♦♣❀
✷✼
✲✲
✷✽
♠❴❞✐❣✐t♦ ✿❂ ✶✶ ✲ ♠♦❞ ✭♠❴t♦t❛❧✱ ✶✶✮❀
✷✾
✲✲
✸✵
✐❢ ♠❴❞✐❣✐t♦ ❃ ✾ t❤❡♥
✸✶
♠❴❞✐❣✐t♦ ✿❂ ✵❀
✸✷
❡♥❞ ✐❢❀
✸✸
✲✲
✸✹
✐❢ ♠❴❞✐❣✐t♦ ✦❂ s✉❜str ✭❝♣❢✱ ✶✶✱ ✶✮ t❤❡♥
✸✺
r❡t✉r♥ ✬■✬❀
✸✻
❡♥❞ ✐❢❀
✸✼
✲✲
✸✽
r❡t✉r♥ ✬❱✬❀
✸✾
✲✲
✹✵ ❡♥❞ ✈❛❧✐❞❛❴❝♣❢❀
✹✶ ✴
❋✉♥çã♦ ❝r✐❛❞❛✳
❙◗▲❃
Executando valida_cpf:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
r❡s ✈❛r❝❤❛r✷✭✶✮ ❞❡❢❛✉❧t ♥✉❧❧❀
247
16.7. Passando parâmetros
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
❈P❋
❈P❋
Casa do Código
✲✲
❜❡❣✐♥
r❡s ✿❂ ✈❛❧✐❞❛❴❝♣❢✭❝♣❢ ❂❃ ✬✵✷✵✾✶✻✼✽✺✷✵✬✮❀
✲✲
✐❢ r❡s ❂ ✬❱✬ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✈á❧✐❞♦✿ ✵✷✵✾✶✻✼✽✺✷✵✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✐♥✈á❧✐❞♦✿ ✵✷✵✾✶✻✼✽✺✷✵✬✮❀
❡♥❞ ✐❢❀
✲✲
r❡s ✿❂ ✈❛❧✐❞❛❴❝♣❢✭✬✵✷✵✶✶✻✹✽✾✷✵✬✮❀
✲✲
✐❢ r❡s ❂ ✬❱✬ t❤❡♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✈á❧✐❞♦✿ ✵✷✵✶✶✻✹✽✾✷✵✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈P❋ ✐♥✈á❧✐❞♦✿ ✵✷✵✶✶✻✹✽✾✷✵✬✮❀
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
✐♥✈á❧✐❞♦✿ ✵✷✵✾✶✻✼✽✺✷✵
✈á❧✐❞♦✿ ✵✷✵✶✶✻✹✽✾✷✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Anteriormente, mencionamos que embora procedures não retornem valores, vimos que através de parâmetros do tipo out isto é possível.
Contudo, as procedures não retornam valores implicitamente como as
functions. Vale lembrar que, embora as functions retornem valor, nós
podemos utilizar parâmetros do tipo out em sua definição, mesmo porque
uma function só pode retornar um único valor por chamada, enquanto
através dos parâmetros do tipo out é possível ter vários retornos.
248
Casa do Código
16.8
Capítulo 16. Programas armazenados
Dependência de objetos
É de fundamental importância que o desenvolvedor conheça como o Oracle
trata a questão da dependência entre os objetos armazenados no banco de
dados. Existem casos em que o próprio desenvolvedor é quem vai liberar os
objetos na base de dados, sendo ela uma base teste ou até em uma base de
produção. Diante disto, é sempre bom saber o que pode acontecer quando
liberamos objetos que possuem dependências entre si.
O Oracle trabalha em cima de dois conceitos com relação a este tipo de
dependência. Os conceitos de dependência direta e dependência indireta.
Conforme está na documentação da Oracle, quando se trata de uma dependência direta o Oracle consegue restabelecer o programa que está inválido.
Já quando não se trata de uma dependência direta, o Oracle não garante que
este restabelecimento seja feito de forma automática. Vamos verificar as características referentes às dependências diretas e indiretas entre objetos.
Para evidenciar as diferenças entre os tipos de dependências, criaremos
exemplos práticos. Para começar, vamos partir do ponto onde temos quatro
procedures chamadas: proc1, proc2, proc3 e proc4.
❙◗▲❃
✷
✸
✹
✺
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✹ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✹✦✦✦✬✮❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✸ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✸✦✦✦✬✮❀
♣r♦❝✹❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ✐s
249
16.8. Dependência de objetos
Casa do Código
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✷✦✦✦✬✮❀
✹
♣r♦❝✸❀
✺ ❡♥❞❀
✻ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✶ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✶✦✦✦✬✮❀
♣r♦❝✷❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Observando os scripts anteriores, vemos que a procedure proc1
chama a proc2 e a proc2 chama a proc3 até chegarmos à procedure
proc4. Neste caso, podemos identificar os dois casos de dependência os quais
estamos abordando.
A dependência direta está representada nas seguintes situações: proc1
com proc2, proc2 com proc3 e proc3 com proc4. Ou seja, a procedure
proc2 mantém uma dependência com a procedure proc1, pois para a
proc2 ser executada é preciso que a proc1 seja executada também. Logo, a
proc2 precisa estar válida para que a proc1 esteja validada. Assim acontece
com a procedure proc2 que mantém uma dependência com a proc3 e a
procedure proc3 com a proc4.
A dependência indireta está representada nas situações seguintes: proc1
com proc3, proc2 com proc4, proc1 com proc4. Da mesma forma
que na dependência direta, a procedure proc1 precisa ser executada para
que a proc3 também seja (indiretamente). Logo, a validação da procedure
proc3 precisa existir para que a proc1 também esteja válida. Veja o desenho.
250
Casa do Código
Capítulo 16. Programas armazenados
Fig. 16.1: Esquema mostrando dependências diretas e indiretas
Para verificar as dependências entre os objetos, podemos fazer um
select na view all_dependencies, onde constam todas as dependências existentes entres os objetos criados na base de dados. Para limitarmos a
pesquisa, vamos selecionar as dependências referentes aos objetos que criamos, informando os nomes dos mesmos na cláusula where do select.
251
Casa do Código
16.8. Dependência de objetos
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t
❢r♦♠
✇❤❡r❡
❛♥❞
♥❛♠❡ ⑤⑤ ✬ ❂❃ ✬ ⑤⑤r❡❢❡r❡♥❝❡❞❴♥❛♠❡ ✧❘❡❢❡rê♥❝✐❛s✧
❛❧❧❴❞❡♣❡♥❞❡♥❝✐❡s
♦✇♥❡r
❂ ✬❚❙◗▲✬
♥❛♠❡
✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
r❡❢❡r❡♥❝❡❞❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
♦r❞❡r ❜② ♥❛♠❡
✴
❘❡❢❡rê♥❝✐❛s
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶ ❂❃ P❘❖❈✷
P❘❖❈✷ ❂❃ P❘❖❈✸
P❘❖❈✸ ❂❃ P❘❖❈✹
❙◗▲❃
Já para verificar os status dos objetos, devemos fazer um select na view
all_objects, selecionando o campo STATUS.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
252
❙❚❆❚❯❙
✲✲✲✲✲✲✲
❱❆▲■❉
❱❆▲■❉
Casa do Código
P❘❖❈✸
P❘❖❈✹
Capítulo 16. Programas armazenados
❱❆▲■❉
❱❆▲■❉
❙◗▲❃
Para tornar mais clara a explanação sobre as dependências entre objetos,
na sequência estão alguns exemplos relacionados aos conceitos expostos anteriormente:
Criando objetos fora da ordem de dependência. Como já havíamos criado
os objetos anteriormente, vamos primeiramente excluí-los.
❙◗▲❃ ❞r♦♣ ♣r♦❝❡❞✉r❡ ♣r♦❝✶❀
Pr♦❝❡❞✐♠❡♥t♦ ❡❧✐♠✐♥❛❞♦✳
❙◗▲❃ ❞r♦♣ ♣r♦❝❡❞✉r❡ ♣r♦❝✷❀
Pr♦❝❡❞✐♠❡♥t♦ ❡❧✐♠✐♥❛❞♦✳
❙◗▲❃ ❞r♦♣ ♣r♦❝❡❞✉r❡ ♣r♦❝✸❀
Pr♦❝❡❞✐♠❡♥t♦ ❡❧✐♠✐♥❛❞♦✳
❙◗▲❃ ❞r♦♣ ♣r♦❝❡❞✉r❡ ♣r♦❝✹❀
Pr♦❝❡❞✐♠❡♥t♦ ❡❧✐♠✐♥❛❞♦✳
❙◗▲❃
Após excluir cada procedure, vamos criá-las novamente.
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✶ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✶✦✦✦✬✮❀
♣r♦❝✷❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
253
16.8. Dependência de objetos
❙◗▲❃
❙◗▲❃
✷
✸
✹
✺
✻
Casa do Código
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✷✦✦✦✬✮❀
♣r♦❝✸❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✸ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✸✦✦✦✬✮❀
♣r♦❝✹❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃
❙◗▲❃
✷
✸
✹
✺
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✹ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✹✦✦✦✬✮❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Veja que proc1, proc2 e proc3 foram criadas com advertência. Contudo, a proc4 foi criada com sucesso. Agora vamos verificar os status dos
objetos.
❙◗▲❃ s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✷
✱st❛t✉s
254
Casa do Código
Capítulo 16. Programas armazenados
✸ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✹ ✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
✺ ❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✻
✱✬P❘❖❈✷✬
✼
✱✬P❘❖❈✸✬
✽
✱✬P❘❖❈✹✬
✾
✮
✶✵ ❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬❀
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
❱❆▲■❉
Como era previsto, as procedures PROC1, PROC2 e PROC3 estão
inválidas, enquanto a PROC4 está válida. Isto ocorreu pelo fato de que na
ordem em que os objetos foram criados sempre faltava a criação do objeto
dependente, com exceção, é claro, do objeto PROC4.
Criando os objetos na ordem de dependência:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✹ ✐s
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✹✦✦✦✬✮❀
✹ ❡♥❞❀
✺ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✸ ✐s
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✸✦✦✦✬✮❀
✹
♣r♦❝✹❀
✺ ❡♥❞❀
✻ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ✐s
255
Casa do Código
16.8. Dependência de objetos
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✷✦✦✦✬✮❀
✹
♣r♦❝✸❀
✺ ❡♥❞❀
✻ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✶ ✐s
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✶✦✦✦✬✮❀
✹
♣r♦❝✷❀
✺ ❡♥❞❀
✻ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Verificando Objetos.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
Invalidando o objeto PROC1:
256
❙❚❆❚❯❙
✲✲✲✲✲✲✲
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
Casa do Código
❙◗▲❃
✷
✸
✹
✺
✻
✼
Capítulo 16. Programas armazenados
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✶ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✶✦✦✦✬✮❀
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡
♣r♦❝✷❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✷
✱st❛t✉s
✸ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✹ ✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
✺ ❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✻
✱✬P❘❖❈✷✬
✼
✱✬P❘❖❈✸✬
✽
✱✬P❘❖❈✹✬
✾
✮
✶✵ ❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬❀
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
Invalidando o objeto PROC2:
❙◗▲❃
✷
✸
✹
✺
✻
✼
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✷✦✦✦✬✮❀
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡
♣r♦❝✸❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
257
Casa do Código
16.8. Dependência de objetos
✷
✸ ❢r♦♠
✹ ✇❤❡r❡
✺ ❛♥❞
✻
✼
✽
✾
✶✵ ❛♥❞
✶✶ ✴
✱st❛t✉s
❛❧❧❴♦❜❥❡❝ts
♦✇♥❡r
❂ ✬❚❙◗▲✬
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
Invalidando o objeto PROC3:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✸ ✐s
✷ ❜❡❣✐♥
✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✸✦✦✦✬✮❀
✹
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡
✺
♣r♦❝✹❀
✻ ❡♥❞❀
✼ ✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
258
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
Casa do Código
✶✶
Capítulo 16. Programas armazenados
✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
❱❆▲■❉
Invalidando o objeto PROC4:
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✹ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✹✦✦✦✬✮❀
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✷
✱st❛t✉s
✸ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✹ ✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
✺ ❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✻
✱✬P❘❖❈✷✬
✼
✱✬P❘❖❈✸✬
✽
✱✬P❘❖❈✹✬
✾
✮
✶✵ ❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✶✶ ✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙◗▲❃
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
259
16.8. Dependência de objetos
Casa do Código
Corrigindo e recriando o objeto PROC1:
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✶ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✶✦✦✦✬✮❀
♣r♦❝✷❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❤♦✇ ❡rr♦r
❊rr♦s ♣❛r❛ ♣r♦❝❡❞✉r❡ P❘❖❈✶✿
▲✐♥❊✴❈❖▲
✲✲✲✲✲✲✲✲
✹✴✸
✹✴✸
❙◗▲❃
❊❘❘❖❘
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
P▲❙✲✵✵✾✵✺✿ ♦ ♦❜❥❡t♦ ❚❙◗▲✳P❘❖❈✷ é ✐♥✈á❧✐❞♦
Corrigindo e recriando o objeto PROC2:
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✷✦✦✦✬✮❀
♣r♦❝✸❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❤♦✇ ❡rr♦r
❊rr♦s ♣❛r❛ ♣r♦❝❡❞✉r❡ P❘❖❈✷✿
▲✐♥❊✴❈❖▲
✲✲✲✲✲✲✲✲
✹✴✸
✹✴✸
❙◗▲❃
❊❘❘❖❘
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
P▲❙✲✵✵✾✵✺✿ ♦ ♦❜❥❡t♦ ❚❙◗▲✳P❘❖❈✸ é ✐♥✈á❧✐❞♦
Corrigindo e recriando o objeto PROC3:
260
Casa do Código
❙◗▲❃
✷
✸
✹
✺
✻
Capítulo 16. Programas armazenados
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✸ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✸✦✦✦✬✮❀
♣r♦❝✹❀
❡♥❞❀
✴
❆❞✈❡rtê♥❝✐❛✿ Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❤♦✇ ❡rr♦r
❊rr♦s ♣❛r❛ ♣r♦❝❡❞✉r❡ P❘❖❈✸✿
▲✐♥❊✴❈❖▲
✲✲✲✲✲✲✲✲
✹✴✸
✹✴✸
❙◗▲❃
❊❘❘❖❘
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
P▲❙✲✵✵✾✵✺✿ ♦ ♦❜❥❡t♦ ❚❙◗▲✳P❘❖❈✹ é ✐♥✈á❧✐❞♦
Verificando objetos:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
❙◗▲❃
261
Casa do Código
16.8. Dependência de objetos
Corrigindo e validando o objeto PROC4:
❙◗▲❃
✷
✸
✹
✺
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ♣r♦❝✹ ✐s
❜❡❣✐♥
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬♣r♦❝✳ ✹✦✦✦✬✮❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
■◆❱❆▲■❉
■◆❱❆▲■❉
❱❆▲■❉
❙◗▲❃
Recompilando PROC2:
❙◗▲❃ ❛❧t❡r ♣r♦❝❡❞✉r❡ ♣r♦❝✷ ❝♦♠♣✐❧❡❀
Pr♦❝❡❞✐♠❡♥t♦ ❛❧t❡r❛❞♦✳
❙◗▲❃ s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✷
✱st❛t✉s
✸ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
262
Casa do Código
Capítulo 16. Programas armazenados
✹ ✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
✺ ❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✻
✱✬P❘❖❈✷✬
✼
✱✬P❘❖❈✸✬
✽
✱✬P❘❖❈✹✬
✾
✮
✶✵ ❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✶✶ ✴
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙❚❆❚❯❙
✲✲✲✲✲✲✲
■◆❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❙◗▲❃
Executando a PROC1:
❙◗▲❃ ❡①❡❝✉t❡ ♣r♦❝✶❀
♣r♦❝✳ ✶✦✦✦
♣r♦❝✳ ✷✦✦✦
♣r♦❝✳ ✸✦✦✦
♣r♦❝✳ ✹✦✦✦
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
s❡❧❡❝t ♦❜❥❡❝t❴♥❛♠❡
✱st❛t✉s
❢r♦♠ ❛❧❧❴♦❜❥❡❝ts
✇❤❡r❡ ♦✇♥❡r
❂ ✬❚❙◗▲✬
❛♥❞
♦❜❥❡❝t❴♥❛♠❡ ✐♥ ✭ ✬P❘❖❈✶✬
✱✬P❘❖❈✷✬
✱✬P❘❖❈✸✬
✱✬P❘❖❈✹✬
✮
❛♥❞
♦❜❥❡❝t❴t②♣❡ ❂ ✬♣r♦❝❡❞✉r❡✬
✴
263
Casa do Código
16.8. Dependência de objetos
❖❇❏❊❈❚❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❘❖❈✶
P❘❖❈✷
P❘❖❈✸
P❘❖❈✹
❙❚❆❚❯❙
✲✲✲✲✲✲✲
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❱❆▲■❉
❙◗▲❃
Vimos que, embora existam dependências indiretas entre os objetos, o
Oracle conseguiu identificar as chamadas e validar os objetos subsequentes.
Embora isdo tenha ocorrido, a Oracle não garante que em alguns casos isto
venha a acontecer. Diante disto, podemos dizer que o Oracle está preparado
para restabelecer as validações em caso de dependência direta e indireta, contudo, não é garantido que ele conseguirá detectar certas ligações.
Todavia, é sempre adequado verificar os status dos objetos após a liberação de objetos novos ou novas versões no banco de dados. Dependendo da
quantidade de objetos com dependência, invalidá-los poderá nos custar algum tempo até deixar o sistema estável novamente. Vale lembrar que, mesmo
existindo objetos inválidos no banco de dados, podemos não ter problemas
no funcionamento, caso o Oracle, ao executar alguma operação com um destes objetos, detecte a existência de dependências diretas e as restabeleça.
264
Capítulo 17
packages
No capítulo anterior, falamos sobre procedures e functions e como
elas são armazenadas e executadas através de um banco de dados. Pois
bem, packages, também chamados de pacotes, são programas armazenados, tendo como diferencial a possibilidade de funcionar como repositório
para agrupar vários objetos do tipo procedure e function, bem como
conter código PL/SQL ou servir de área para definições de variáveis, cursores, exceções, procedimentos e funções.
Contudo, talvez sua maior utilização esteja no agrupamento de programas que possuem uma mesma finalidade, como aqueles que façam parte
de uma área específica como RH, Financeira ou Comercial. Através de
packages conseguimos organizar estes programas dentro de um único objeto e definir como o acesso a estes objetos será realizado.
17.1. Estrutura de um package
Casa do Código
17.1 Estrutura de um package
Um package pode ser constituído por até duas partes, uma chamada
especification e outra chamada body. Podemos ter um package
especification sem package body, contudo, não podemos ter o contrário. Obrigatoriamente, para criamos um package body é necessário
criar também um package especification. Já vamos entender por quê.
Dentro do especification, podemos declarar variáveis, types, cabeçalhos de procedures e functions, exceptions, cursores etc., que
podem fazer ou não referência a um package body. Quando estiver fazendo referência a um body, podemos dizer que o especification, como
nome sugere, funciona como uma especificação do body.
Por exemplo, se temos um body dentro do qual há um código de uma
procedure, podemos ter declarado no especification o cabeçalho
deste programa, mesmo porque, por definição deste tipo de objeto, só conseguiremos acessar um programa que está armazenado dentro de um body
caso sua especificação esteja declarada em um especification. Por isto,
um body não pode existir sem um especification.
Caso o especification não faça referência a um body, ele pode estar
sendo utilizado para declaração de variáveis ou outros tipos de objetos que
não necessitariam de um body. Vale salientar que, caso tenhamos cabeçalhos
de procedures e functions em um especification, se faz necessário
que exista um body relacionado.
Já dentro do body é onde colocamos toda a codificação dos nossos programas, como codificações de procedures e functions. Além destes
objetos, também podemos declarar variáveis, cursores, exceções, types etc.,
que podem ser utilizados pelo restante dos objetos criados no body. No
entanto, podemos ter objetos dentro do body que não estão declarados no
especification, os quais não poderão ser acessados diretamente, somente
através de outros objetos contidos no próprio body. Os objetos declarados no
especification, por exemplo, variáveis e cursores, podem ser acessados
de dentro do body. Além disso, dentro do body podemos ter codificação
PL/SQL correspondente ao próprio package, pois o body pode conter sua
própria área begin e end.
266
Casa do Código
Capítulo 17. packages
Podemos ter no especification
• Especificação de procedures e functions;
• Declaração de variáveis e constantes;
• Declaração de cursores;
• Declaração de exceptions;
• Declaração de types.
Podemos ter no body
• Códigos PL/SQL;
• Códigos de procedures e functions;
• Declaração de variáveis e constantes;
• Declaração de cursores;
• Declaração de exceptions;
• Declaração de types.
Exemplo de especification:
❙◗▲❃ ❝r❡❛t❡ ♣❛❝❦❛❣❡ ❧✐st❛❣❡♠ ✐s
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✺
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡
✻
✱❢✐rst❴♥❛♠❡
✼
✱❤✐r❡❴❞❛t❡
✽
✱s❛❧❛r②
✾
❢r♦♠ ❞❡♣❛rt♠❡♥ts ❞
✶✵
✱❡♠♣❧♦②❡❡s ❡
✶✶
✇❤❡r❡ ❞✳♠❛♥❛❣❡r❴✐❞ ❂ ❡✳❡♠♣❧♦②❡❡❴✐❞
✶✷
♦r❞❡r ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
267
17.1. Estrutura de um package
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
Casa do Código
✲✲
t②♣❡ t❛❜ ✐s t❛❜❧❡ ♦❢ ❝✶✪r♦✇t②♣❡ ✐♥❞❡① ❜② ❜✐♥❛r②❴✐♥t❡❣❡r❀
✲✲
t❜❣❡r❡♥t❡ t❛❜❀
♥ ♥✉♠❜❡r❀
✲✲
♣r♦❝❡❞✉r❡ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦❀
✲✲
❡♥❞ ❧✐st❛❣❡♠❀
✴
P❛❝♦t❡ ❝r✐❛❞♦✳
❙◗▲❃
Para criarmos um package especification, utilizamos o comando
create. Seguindo nosso exemplo, na primeira linha temos o comando
create e logo em seguida o tipo de objeto que estamos criando, no caso,
package. Quando não informamos o tipo body, automaticamente o Oracle
cria o package como sendo do tipo especification.
Logo depois do tipo de objeto, informamos o nome ( listagem) seguido
da expressão is (linha 01). is pode ser substituído por as. Sempre que for
criar um objeto package especification, você deve utilizar esta sintaxe.
Depois da expressão is, são declarados os objetos que poderão ou
não ser usados em um package body. Neste exemplo, temos um
especification com a declaração de alguns objetos como o cursor c1,
o type tab, as variáveis n e tbgerente, e a especificação da procedure lista_gerente_por_depto. Note que só informamos o cabeçalho
da procedure. Logo terá que existir um body onde seu código estará criado. Os cabeçalhos dos objetos informados devem ser idênticos aos descritos
no corpo do package.
Note que, nestes casos, todos os objetos, por estarem no
especification, têm seu escopo público, ou seja, qualquer usuário que tenha acesso a este objeto poderá referenciá-los em sua sessão,
utilizando-os. Toda a declaração é finalizada por ponto e vírgula. Por fim,
268
Casa do Código
Capítulo 17. packages
temos o comando end (linha 21), que finaliza o package. Colocar ou não
o nome do package logo após o comando end é opcional. Contudo, não
podemos ter nomes diferentes no cabeçalho e rodapé do objeto.
Exemplo de body:
❙◗▲❃ ❝r❡❛t❡ ♣❛❝❦❛❣❡ ❜♦❞② ❧✐st❛❣❡♠ ✐s
✷
✲✲
✸
♣r♦❝❡❞✉r❡ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦ ✐s
✹
✲✲
✺
❜❡❣✐♥
✻
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
✼
t❜❣❡r❡♥t❡✭r✶✳❞❡♣❛rt♠❡♥t❴✐❞✮ ✿❂ r✶❀
✽
❡♥❞ ❧♦♦♣❀
✾
✲✲
✶✵
♥ ✿❂ t❜❣❡r❡♥t❡✳❢✐rst❀
✶✶
✲✲
✶✷
✇❤✐❧❡ ♥ ❁❂ t❜❣❡r❡♥t❡✳❧❛st ❧♦♦♣
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣t♦✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❞❡♣❛rt♠❡♥t❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✬●❡r❡♥t❡✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❢✐rst❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✶✹
✶✺
✬❉t✳ ❆❞♠✐✳✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❤✐r❡❴❞❛t❡⑤⑤✬ ✬⑤⑤
✬❙❛❧✳✿ ✬⑤⑤t♦❴❝❤❛r✭t❜❣❡r❡♥t❡✭♥✮✳s❛❧❛r②✱
✶✻
✬❢♠✩✾✾✾❣✾✾✾❣✾✾✵❞✵✵✬✮✮❀
✶✼
♥ ✿❂ t❜❣❡r❡♥t❡✳♥❡①t✭♥✮❀
✶✽
❡♥❞ ❧♦♦♣❀
✶✾
✲✲
✷✵
❡♥❞ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦❀
✷✶
✲✲
✷✷ ❡♥❞ ❧✐st❛❣❡♠❀
✷✸ ✴
❈♦r♣♦ ❞❡ P❛❝♦t❡ ❝r✐❛❞♦✳
❙◗▲❃
Igualmente ao utilizado na criação do package especification,
para criarmos um package body, nós utilizamos também o comando
create. Na primeira linha deste exemplo, temos o comando create e,
em seguida, o tipo de objeto que estamos criando, no caso, package body.
269
17.2. Acesso a packages
Casa do Código
Logo depois do tipo de objeto, informamos um nome para ele ( listagem),
seguido da expressão is (linha 01), que pode ser substituído por as. Sempre
que for criar um objeto package body, você deve utilizar esta sintaxe.
Este objeto body faz referência ao especification criado no exemplo
anterior. Nele está o código da procedure lista_gerente_por_depto
(linhas 3 a 20), declarada no especification. Note que, neste exemplo,
não utilizamos a área begin end do body e também não declaramos qualquer objeto dentro do corpo do package. Contudo, dentro da procedure,
estamos utilizando os objetos que foram declarados no especification,
por exemplo, o cursor (linha 6 a 8), o type (linha 7, 13 a 17) e as variáveis (linhas
10, 12 e 17).
Assim como esta, outras procedures, caso existissem mais dentro do
body, poderiam também acessar estes objetos. Todavia, se eles estivessem declarados no body, em vez de no especification, o efeito seria o mesmo.
Entretanto, o escopo destes objetos seria interno ao body, não podendo ser
acessados externamente.
Por fim, temos o comando end (linha 22), que finaliza o package. Como
no especification, colocar ou não o nome do package logo após o
comando end é opcional. Contudo, não podemos ter nomes diferentes no
cabeçalho e rodapé do objeto. Vale ressaltar que toda a declaração deve ser
finalizada por ponto e vírgula.
17.2 Acesso a packages
Como mencionado anteriormente, só podemos acessar um objeto que se encontra em um body se ele estiver declarado no especification. Logo, o
especification tem a característica de ser uma área pública onde todos
os usuários que possuam concessão de acesso a este objeto podem referenciar ou executar os objetos do body por intermédio do que está especificado
nesta área.
Tudo o que estiver declarado no especification e no body tem seu
escopo no nível de usuário, ou melhor, na sessão do usuário que executou tal
package. Os objetos package só começam a ocupar recursos na memória
quando algum objeto é referenciado. A área de begin end do body é exe270
Casa do Código
Capítulo 17. packages
cutada uma única vez na sessão do usuário, na primeira vez que o package
é referenciado.
Por isso, quando utilizada, é comum vê-la servir como local para inicialização de variáveis ou para execução de procedimentos que inicializem algum
objeto que será utilizado por outros objetos ao longo da vida útil da sessão.
Quanto aos objetos definidos dentro das procedures e functions internas ao body, estes têm seu escopo em nível local e os recursos só são
ocupados mediante a execução de tais procedures e functions.
Às vezes, packages especifications são utilizadas como área para
declaração e inicialização de variáveis ou cursores dentro de uma sessão, não
existindo um body. Como o especification tem seu escopo em nível
de sessão, ele é muito útil para ser usado pelos programas para guardar informações que serão utilizadas em algum processamento ou para determinar
padrões em um sistema. Como estas informações ficam na sessão enquanto
ela estiver aberta, todos os programas que estiverem sendo executados poderão compartilhar desta área e, consequentemente, dos dados e objetos que
estão declarados nela.
Resumindo, quando trabalhamos com packages precisamos saber de
alguns detalhes:
• Packages podem ser constituídas de duas partes: especification
e body.
• Um especification pode existir sem um body, mas não o contrário.
• Quando existirem um especification e um body, os dois objetos
devem ter exatamente o mesmo nome.
• Para acessar objetos de dentro de um body, é preciso que eles estejam
declarados em um especification (acesso direto), ou que, pelo
menos, possam ser acessados através de algum objeto que esteja no
especification (acesso indireto).
• Os objetos pertencentes ao package têm seu escopo em nível de sessão do usuário o qual executou tal package.
271
17.2. Acesso a packages
Casa do Código
• Os objetos de um package ocuparão recursos somente quando forem
referenciados.
• Áreas como especification e begin end do body serão executadas uma única vez na sessão do usuário, na primeira vez em que são
referenciadas.
• Igualmente a procedures e functions, é necessário ter concessão
de acesso para executar packages.
• Com o uso de especification e body, é possível disponibilizar
informações em nível global e em nível de programa, mantendo a integridade e consistência através de encapsulamento.
Veja na sequência um exemplo de mais uma package e sua aplicação.
O package a seguir é responsável por efetuar cálculos como somatória, subtração, divisão e multiplicação. Para cada operação, existe uma function
onde são passados dois parâmetros referentes aos números que se quer calcular. Após o cálculo, a função retorna o resultado.
❙◗▲❃ ❝r❡❛t❡ ♣❛❝❦❛❣❡ ❝❛❧❝✉❧♦ ❛s
✷
✲✲
✸
❢✉♥❝t✐♦♥ s♦♠❛ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r❀
✹
❢✉♥❝t✐♦♥ s✉❜tr❛✐ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r❀
✺
❢✉♥❝t✐♦♥ ♠✉❧t✐♣❧✐❝❛ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r❀
✻
❢✉♥❝t✐♦♥ ❞✐✈✐❞❡ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r❀
✼
✲✲
✽ ❡♥❞ ❝❛❧❝✉❧♦❀
✾ ✴
P❛❝♦t❡ ❝r✐❛❞♦✳
❙◗▲❃
Na primeira linha deste exemplo, temos o comando create e em
seguida o tipo de objeto que estamos criando, no caso, package (
especification). Logo depois do tipo de objeto, informamos o seu
nome ( calculo) seguido da expressão as (linha 01). No corpo do
272
Casa do Código
Capítulo 17. packages
especification, declaramos as funções soma, subtrai, multiplica
e divide (linhas 3 a 6). Note que aqui só são informados os cabeçalhos das
funções. Por fim, temos o comando end (linha 8) que finaliza o package.
Detalhes sobre o package especification calculo:
• Foi criado o package especification chamado calculo;
• No package especification foram declaradas quatro funções,
cada uma responsável por uma operação matemática (soma, subtração,
multiplicação e divisão).
❙◗▲❃ ❝r❡❛t❡ ♣❛❝❦❛❣❡ ❜♦❞② ❝❛❧❝✉❧♦ ❛s
✷
✲✲
✸
r❡s ♥✉♠❜❡r❀
✹
✲✲
✺
♣r♦❝❡❞✉r❡ ✐♠♣r✐♠❡❴♠s❣✭♠s❣ ✈❛r❝❤❛r✷✮ ✐s
✻
❜❡❣✐♥
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭♠s❣✮❀
✽
❡♥❞❀
✾
✲✲
✶✵
❢✉♥❝t✐♦♥ s♦♠❛ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r ✐s
✶✶
❜❡❣✐♥
✶✷
r❡s ✿❂ ①✶ ✰ ①✷❀
✶✸
r❡t✉r♥ r❡s❀
✶✹
❡♥❞❀
✶✺
✲✲
✶✻
❢✉♥❝t✐♦♥ s✉❜tr❛✐ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r ✐s
✶✼
❜❡❣✐♥
✶✽
r❡s ✿❂ ①✶ ✲ ①✷❀
✶✾
✲✲
✷✵
✐❢ r❡s ❂ ✵ t❤❡♥
✷✶
✐♠♣r✐♠❡❴♠s❣✭✬❘❡s✉❧t❛❞♦ ✐❣✉❛❧ ❛ ③❡r♦✿ ✬⑤⑤r❡s✮❀
✷✷
❡❧s✐❢ r❡s ❁ ✵ t❤❡♥
✷✸
✐♠♣r✐♠❡❴♠s❣✭✬❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✿ ✬⑤⑤r❡s✮❀
✷✹
❡❧s✐❢ r❡s ❃ ✵ t❤❡♥
✷✺
✐♠♣r✐♠❡❴♠s❣✭✬❘❡s✉❧t❛❞♦ ♠❛✐♦r q✉❡ ③❡r♦✿ ✬⑤⑤r❡s✮❀
✷✻
❡♥❞ ✐❢❀
✷✼
✲✲
✷✽
r❡t✉r♥ r❡s❀
273
17.2. Acesso a packages
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
Casa do Código
✲✲
❡♥❞❀
✲✲
❢✉♥❝t✐♦♥ ♠✉❧t✐♣❧✐❝❛ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥
♥✉♠❜❡r ✐s
❜❡❣✐♥
r❡s ✿❂ ①✶ ✯ ①✷❀
r❡t✉r♥ r❡s❀
❡♥❞❀
✲✲
❢✉♥❝t✐♦♥ ❞✐✈✐❞❡ ✭①✶ ♥✉♠❜❡r✱ ①✷ ♥✉♠❜❡r✮ r❡t✉r♥ ♥✉♠❜❡r ✐s
❜❡❣✐♥
✐❢ ①✷ ❂ ✵ t❤❡♥
r❡s ✿❂ ♥✉❧❧❀
✐♠♣r✐♠❡❴♠s❣✭✬❊rr♦ ❞❡ ❞✐✈✐sã♦ ♣♦r ③❡r♦✦✬✮❀
❡❧s❡
r❡s ✿❂ ①✶ ✴ ①✷❀
❡♥❞ ✐❢❀
✲✲
r❡t✉r♥ r❡s❀
❡♥❞❀
✲✲
❡♥❞ ❝❛❧❝✉❧♦❀
✴
❈♦r♣♦ ❞❡ P❛❝♦t❡ ❝r✐❛❞♦✳
❙◗▲❃
Agora vamos criar o segundo objeto, que é a segunda parte do nosso programa. Na primeira linha temos o comando create e em seguida o tipo do
objeto, package body, com seu nome, calculo, e a expressão as (linha
1). Declaramos uma variável chamada res no corpo do package (linha 3).
Esta variável está sendo utilizada em todo o programa. Entre as linhas 10 a
46, estão os códigos das funções declaradas no objeto especification.
Além destes, também temos um objeto procedure (linhas 5 a 8) utilizado
para imprimir mensagens na tela. Se observarmos este objeto, veremos que
ele não foi declarado no especification, logo, não poderá ser acessado
274
Casa do Código
Capítulo 17. packages
de fora do body.
Em nosso programa, a procedure imprime_msg está sendo utilizada
nas linhas 21,23, 25 e 42, pelas funções subtrai e divide. Vale lembrar mais
uma vez que toda a declaração ou codificação de objeto deve ser finalizada por
ponto e vírgula. Como no especification, o body também é finalizado
com o comando end (linha 48), seguindo as mesmas regras. É importante
frisar que os nomes dos objetos especification e body devem ser iguais.
Detalhes sobre o package body calculo:
• Foi criado o package body chamado calculo;
• No package body foi declarada uma variável chamada res que será
usada internamente pelos programas existentes (escopo privado);
• Foram codificados os objetos referentes às functions soma, subtrai,
multiplica e divide, declaradas no especification; estas, de
escopo público;
• Também foi codificado um objeto
procedure chamado
imprime_msg, de escopo privado, e que imprime mensagens na
tela, vindas das functions.
Executando o package calculo:
❙◗▲❃ ❞❡❝❧❛r❡
✷
r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
r❡s ✿❂ ❝❛❧❝✉❧♦✳s♦♠❛✭✹✺✵✱ ✺✺✵✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✹✺✵ ✰ ✺✺✵ ❂ ✬⑤⑤r❡s✮❀
✼ ❡♥❞❀
✽ ✴
✹✺✵ ✰ ✺✺✵ ❂ ✶✵✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
r❡s ♥✉♠❜❡r❀
275
17.2. Acesso a packages
Casa do Código
✸ ❜❡❣✐♥
✹
r❡s ✿❂ ❝❛❧❝✉❧♦✳s✉❜tr❛✐✭✸✺✵✱ ✻✺✵✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✸✺✵ ✲ ✻✺✵ ❂ ✬⑤⑤r❡s✮❀
✼ ❡♥❞❀
✽ ✴
❘❡s✉❧t❛❞♦ ♠❡♥♦r q✉❡ ③❡r♦✿ ✲✸✵✵
✸✺✵ ✲ ✻✺✵ ❂ ✲✸✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✷✵ ✯
❞❡❝❧❛r❡
r❡s ♥✉♠❜❡r❀
❜❡❣✐♥
r❡s ✿❂ ❝❛❧❝✉❧♦✳♠✉❧t✐♣❧✐❝❛✭✷✵✱ ✶✵✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✷✵ ✯ ✶✵ ❂ ✬⑤⑤r❡s✮❀
❡♥❞❀
✴
✶✵ ❂ ✷✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
r❡s ✿❂ ❝❛❧❝✉❧♦✳❞✐✈✐❞❡✭✺✵✱ ✺✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✺✵ ✴ ✺ ❂ ✬⑤⑤r❡s✮❀
✼ ❡♥❞❀
✽ ✴
✺✵ ✴ ✺ ❂ ✶✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Observe o que acontece quando tentamos acessar algum objeto que não
tem escopo no nível público, ou seja, que não se encontra declarado no
especification:
❙◗▲❃ ❞❡❝❧❛r❡
276
Casa do Código
Capítulo 17. packages
✷
r❡s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
r❡s ✿❂ ❝❛❧❝✉❧♦✳❞✐✈✐❞❡✭✺✵✱ ✺✮❀
✺
✲✲
✻
❝❛❧❝✉❧♦✳✐♠♣r✐♠❡❴♠s❣✭✬✺✵ ✴ ✺ ❂ ✬⑤⑤r❡s✮❀
✼ ❡♥❞❀
✽ ✴
❝❛❧❝✉❧♦✳✐♠♣r✐♠❡❴♠s❣✭✬✺✵ ✴ ✺ ❂ ✬⑤⑤r❡s✮❀
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✻✿
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✻✱ ❝♦❧✉♥❛ ✶✶✿
P▲❙✲✵✵✸✵✷✿ ♦ ❝♦♠♣♦♥❡♥t❡ ✬✐♠♣r✐♠❡❴♠s❣✬ ❞❡✈❡ s❡r ❞❡❝❧❛r❛❞♦
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✻✱ ❝♦❧✉♥❛ ✸✿
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
❙◗▲❃ ❜❡❣✐♥
✷
❝❛❧❝✉❧♦✳r❡s ✿❂ ❝❛❧❝✉❧♦✳❞✐✈✐❞❡✭✺✵✱ ✺✮❀
✸
✲✲
✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬✺✵ ✴ ✺ ❂ ✬⑤⑤❝❛❧❝✉❧♦✳r❡s✮❀
✺ ❡♥❞❀
✻ ✴
❝❛❧❝✉❧♦✳r❡s ✿❂ ❝❛❧❝✉❧♦✳❞✐✈✐❞❡✭✺✵✱ ✺✮❀
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✷✿
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✷✱ ❝♦❧✉♥❛ ✶✶✿
P▲❙✲✵✵✸✵✷✿ ♦ ❝♦♠♣♦♥❡♥t❡ ✬❘❊❙✬ ❞❡✈❡ s❡r ❞❡❝❧❛r❛❞♦
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✷✱ ❝♦❧✉♥❛ ✸✿
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✹✱ ❝♦❧✉♥❛ ✹✺✿
P▲❙✲✵✵✸✵✷✿ ♦ ❝♦♠♣♦♥❡♥t❡ ✬❘❊❙✬ ❞❡✈❡ s❡r ❞❡❝❧❛r❛❞♦
❖❘❆✲✵✻✺✺✵✿ ❧✐♥❤❛ ✹✱ ❝♦❧✉♥❛ ✸✿
P▲✴❙◗▲✿ ❙t❛t❡♠❡♥t ✐❣♥♦r❡❞
❙◗▲❃
Nos casos em que tentarmos acessar objetos não públicos, o Oracle informa que ele deve ser declarado.
277
Casa do Código
17.3. Recompilando packages
17.3 Recompilando packages
Quando alteramos um package no banco de dados, pode acontecer de termos que compilá-la, novamente. Para isso, utilizamos o comando alter.
Veja os exemplos na sequência:
❙◗▲❃ ❛❧t❡r ♣❛❝❦❛❣❡ ❧✐st❛❣❡♠ ❝♦♠♣✐❧❡❀
P❛❝♦t❡ ❛❧t❡r❛❞♦✳
❙◗▲❃
17.4
Recuperando informações
Para visualizar informações referentes às packages, utilize as views
user_objects, all_objects ou dba_objects. Nesta view constam
informações como STATUS e data de criação do objeto.
❙◗▲❃ s❡❧❡❝t ♦✇♥❡r✱ ♦❜❥❡❝t❴t②♣❡✱ st❛t✉s✱ ❝r❡❛t❡❞✱ ❧❛st❴❞❞❧❴t✐♠❡
✷ ❢r♦♠ ❛❧❧❴♦❜❥❡❝ts ✇❤❡r❡ ♦❜❥❡❝t❴♥❛♠❡ ❂ ✬❧✐st❛❣❡♠✬❀
❖❲◆❊❘
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❚❙◗▲
❚❙◗▲
❝r❡❛t❡❉
✲✲✲✲✲✲✲✲
✵✷✴✶✷✴✶✶
✵✷✴✶✷✴✶✶
❖❇❏❊❈❚❴❚❨P❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
♣❛❝❦❛❣❡
♣❛❝❦❛❣❡ ❜♦❞②
❙❚❆❚❯❙
✲✲✲✲✲✲✲
❱❆▲■❉
❱❆▲■❉
▲❆❙❚❴❉❉▲
✲✲✲✲✲✲✲✲
✵✷✴✶✷✴✶✶
✵✷✴✶✷✴✶✶
❙◗▲❃
Outra forma de recuperar dados referentes a packages é utilizando o
comando describe. Ele mostra a definição de todas as procedures e
functions contidas no package.
❙◗▲❃ ❞❡s❝ ❧✐st❛❣❡♠
♣r♦❝❡❞✉r❡ ▲■❙❚❆❴●❊❘❊◆❚❊❴P❖❘❴❉❊P❚❖
278
Casa do Código
Capítulo 17. packages
❙◗▲❃
17.5
Recuperando códigos
Já para visualizar o código dos objetos package no banco de dados utilize
as views user_source, all_source ou dba_source.
❙◗▲❃
❙◗▲❃
❙◗▲❃
❙◗▲❃
✷
❝♦❧✉♠♥ t❡①t ❢♦r♠❛t ❛✸✵✵
s❡t ❧✐♥❡s ✶✵✵✵
s❡t ♣❛❣❡s ✶✵✵✵
s❡❧❡❝t ❧✐♥❡✱ t❡①t
❢r♦♠ ❛❧❧❴s♦✉r❝❡ ✇❤❡r❡ ♥❛♠❡ ❂ ✬❧✐st❛❣❡♠✬❀
▲■◆❊ ❚❊❳❚
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶ ♣❛❝❦❛❣❡ ❧✐st❛❣❡♠ ✐s
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✺
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡
✻
✱❢✐rst❴♥❛♠❡
✼
✱❤✐r❡❴❞❛t❡
✽
✱s❛❧❛r②
✾
❢r♦♠ ❞❡♣❛rt♠❡♥ts ❞
✶✵
✱❡♠♣❧♦②❡❡s ❡
✶✶
✇❤❡r❡ ❞✳♠❛♥❛❣❡r❴✐❞ ❂ ❡✳❡♠♣❧♦②❡❡❴✐❞
✶✷
♦r❞❡r ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
✶✸
✲✲
✶✹
t②♣❡ t❛❜ ✐s t❛❜❧❡ ♦❢ ❝✶✪r♦✇t②♣❡ ✐♥❞❡① ❜②
❜✐♥❛r②❴✐♥t❡❣❡r❀
✶✺
✲✲
✶✻
t❜❣❡r❡♥t❡ t❛❜❀
✶✼
♥ ♥✉♠❜❡r❀
✶✽
✲✲
✶✾
♣r♦❝❡❞✉r❡ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦❀
✷✵
✲✲
✷✶ ❡♥❞ ❧✐st❛❣❡♠❀
✶ ♣❛❝❦❛❣❡ ❜♦❞② ❧✐st❛❣❡♠ ✐s
279
17.6. Visualizando erros de compilação
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
Casa do Código
✲✲
♣r♦❝❡❞✉r❡ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦ ✐s
✲✲
❜❡❣✐♥
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
t❜❣❡r❡♥t❡✭r✶✳❞❡♣❛rt♠❡♥t❴✐❞✮ ✿❂ r✶❀
❡♥❞ ❧♦♦♣❀
✲✲
♥ ✿❂ t❜❣❡r❡♥t❡✳❢✐rst❀
✲✲
✇❤✐❧❡ ♥ ❁❂ t❜❣❡r❡♥t❡✳❧❛st ❧♦♦♣
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣t♦✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❞❡♣❛rt♠❡♥t❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✬●❡r❡♥t❡✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❢✐rst❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✬❉t✳ ❆❞♠✐✳✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❤✐r❡❴❞❛t❡⑤⑤✬ ✬⑤⑤
✬❙❛❧✳✿ ✬⑤⑤t♦❴❝❤❛r✭t❜❣❡r❡♥t❡✭♥✮✳s❛❧❛r②✱
✬❢♠✩✾✾✾❣✾✾✾❣✾✾✵❞✵✵✬✮✮❀
♥ ✿❂ t❜❣❡r❡♥t❡✳♥❡①t✭♥✮❀
❡♥❞ ❧♦♦♣❀
✲✲
❡♥❞ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦❀
✲✲
❡♥❞ ❧✐st❛❣❡♠❀
✹✸ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
17.6
Visualizando erros de compilação
Para visualizar erros de compilação, use o comando show error.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣❛❝❦❛❣❡ ❧✐st❛❣❡♠ ✐s
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✺
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡
✻
✱❢✐rst❴♥❛♠❡
✼
✱❤✐r❡❴❞❛t❡
280
Casa do Código
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
Capítulo 17. packages
✱s❛❧❛r②
❢r♦♠ ❞❡♣❛rt♠❡♥ts ❞
✱❡♠♣❧♦②❡❡s ❡
✇❤❡r❡ ❞✳♠❛♥❛❣❡r❴✐❞ ❂ ❡✳❡♠♣❧♦②❡❡❴✐❞
♦r❞❡r ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
✲✲
t②♣❡ t❛❜ ✐s t❛❜❧❡ ♦❢ ❝✶✪r♦✇t②♣❡ ✐♥❞❡① ❜② ❜✐♥❛r②❴✐♥t❡❣❡r❀
✲✲
t❜❣❡r❡♥t❡ t❛❜❀
♥ ♥✉♠❜❡r❀
✲✲
♣r♦❝❡❞✉r❡ ❧✐st❛❴❣❡r❡♥t❡❴♣♦r❴❞❡♣t♦❀
❀ ✲✲ ♣r♦✈♦❝❛♥❞♦ ✉♠ ❡rr♦ ❞❡ s✐♥t❛①❡✳
✲✲
❡♥❞ ❧✐st❛❣❡♠❀
✴
❆❞✈❡rtê♥❝✐❛✿ P❛❝♦t❡ ❝r✐❛❞♦ ❝♦♠ ❡rr♦s ❞❡ ❝♦♠♣✐❧❛çã♦✳
❙◗▲❃ s❤♦✇ ❡rr♦r
❊rr♦s ♣❛r❛ ♣❛❝❦❛❣❡ ❧✐st❛❣❡♠✿
▲■◆❊✴❈❖▲ ❊❘❘❖❘
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✷✵✴✹
P▲❙✲✵✵✶✵✸✿ ❊♥❝♦♥tr❛❞♦ ♦ sí♠❜♦❧♦ ✧❀✧ q✉❛♥❞♦ ✉♠ ❞♦s
s❡❣✉✐♥t❡s
sí♠❜♦❧♦s ❡r❛ ❡s♣❡r❛❞♦✿
❡♥❞ ❢✉♥❝t✐♦♥ ♣❛❝❦❛❣❡ ♣r❛❣♠❛ ♣r✐✈❛t❡ ♣r♦❝❡❞✉r❡ s✉❜t②♣❡
t②♣❡
✉s❡ ❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r❃
❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r ❞❡❧✐♠✐t❛❞♦ ♣♦r ❛s♣❛s ❞✉♣❧❛s❃ ❢♦r♠
❝✉rr❡♥t
❝✉rs♦r
❙◗▲❃
O comando basicamente mostra duas colunas. A primeira com a linha
e a coluna onde ocorreu o erro, e a segunda coluna com a descrição. Estes erros também podem ser visualizados através das views user_errors,
281
Casa do Código
17.6. Visualizando erros de compilação
all_errors e dba_errors.
❙◗▲❃ s❡❧❡❝t ❧✐♥❡
✷
✱♣♦s✐t✐♦♥
✸
✱t❡①t
✹ ❢r♦♠ ✉s❡r❴❡rr♦rs
✺ ✇❤❡r❡ ♥❛♠❡ ❂ ✬❧✐st❛❣❡♠✬❀
▲■◆❊ P❖❙■❚■❖◆ ❚❊❳❚
✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✷✵
✹ P▲❙✲✵✵✶✵✸✿ ❊♥❝♦♥tr❛❞♦ ♦ sí♠❜♦❧♦ ✧❀✧ q✉❛♥❞♦ ✉♠ ❞♦s
s❡❣✉✐♥t❡s sí♠❜♦❧♦s ❡r❛ ❡s♣❡r❛❞♦✿
❡♥❞ ❢✉♥❝t✐♦♥ ♣❛❝❦❛❣❡ ♣r❛❣♠❛ ♣r✐✈❛t❡
♣r♦❝❡❞✉r❡ s✉❜t②♣❡ t②♣❡ ✉s❡
❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r❃ ❁✉♠ ✐❞❡♥t✐❢✐❝❛❞♦r
❞❡❧✐♠✐t❛❞♦ ♣♦r ❛s♣❛s ❞✉♣❧❛s❃ ❢♦r♠
❝✉rr❡♥t ❝✉rs♦r
❙◗▲❃
282
Capítulo 18
Transações autônomas
Quando buscamos informações em um banco de dados, esperamos que elas
estejam íntegras. Para garantir a integridade e consistências dos dados, o Oracle mantém controles de transações. Quando uma operação DML é disparada, isso indica que os dados de uma tabela, por exemplo, podem estar sendo
alterados. Nesse momento, podemos concluir que enquanto as alterações não
forem confirmadas os dados que estão sendo manipulados na transação em
questão não estão consistentes. Apenas quando forem confirmados, através
de um rollback ou de um commit, os dados estarão íntegros.
Há situações em que podemos ter várias chamadas a outros objetos que
estejam executando comandos DML e efetivando-os logo em seguida. Entretanto, ao fazer isso, corremos o risco de efetivar ações de outros comandos
DML, executados anteriormente, que não deveriam ser efetivados, ou pelo
menos não naquele momento. Isso acontece pois sabemos que, ao executar
um comando de efetivação, como um commit ou um rollback, o Oracle
Casa do Código
efetiva tudo o que estiver pendente na sessão.
Para esses casos, podemos utilizar transações autônomas para isolar ações
de determinados programas. Utilizamos este recurso informando-o na declaração dos objetos, como em procedures e functions (dentro ou fora de
packages), blocos anônimos (menos em sub-blocos) ou triggers. Sua
função é fazer com que o Oracle abra uma nova sessão somente para executar
tal objeto, ou seja, neste momento existirão pelo menos duas transações em
aberto: a transação original e outra transação autônoma. Veja o exemplo a
seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
♣r♦❝❡❞✉r❡ ❧✐st❛❴❞❡♣t ✐s
✹
✲✲
✺
♣r❛❣♠❛ ❛✉t♦♥♦♠♦✉s❴tr❛♥s❛❝t✐♦♥❀
✻
❜❡❣✐♥
✼
✲✲
✽
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ ❉❡♣❛rt❛♠❡♥t♦s ✲✲✲✲✲✲✲✲✲✲✲✬✮❀
✶✵
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✶✶
✲✲
✶✷
❢♦r ✐ ✐♥ ✭s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t ♦r❞❡r ❜② ❞❡♣t♥♦✮ ❧♦♦♣
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✐✳❞❡♣t♥♦⑤⑤✬ ✲ ✬⑤⑤✐✳❞♥❛♠❡✮❀
✶✹
❡♥❞ ❧♦♦♣❀
✶✺
✲✲
✶✻
❝♦♠♠✐t❀
✶✼
✲✲
✶✽
❡♥❞❀
✶✾
✲✲
✷✵ ❜❡❣✐♥
✷✶
✐♥s❡rt ✐♥t♦ ❞❡♣t ✭❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❧♦❝✮
✈❛❧✉❡s ✭✹✸✱ ✬❖❘❉❊❘ ▼❆◆❆●❊❘✬✱✬❇❘❆❙■▲✬✮❀
✷✷
✲✲
✷✸
❧✐st❛❴❞❡♣t❀
✷✹
✲✲
✷✺
❝♦♠♠✐t❀
✷✻
✲✲
284
Casa do Código
Capítulo 18. Transações autônomas
✷✼
❧✐st❛❴❞❡♣t❀
✷✽
✲✲
✷✾ ❡♥❞❀
✸✵ ✴
Nesse exemplo, criamos um bloco PL/SQL anônimo e dentro dele
declaramos uma procedure chamada lista_dept. Esta procedure
lista todos os departamentos existentes.
Ela foi declarada como
autonomous_transaction, ou seja, quando ela for executada será
aberta uma transação autônoma.
No corpo do bloco PL/SQL, temos um insert que inclui um departamento novo. Logo depois deste comando, chamamos a procedure
lista_dept para listar todos os departamentos que já se encontram cadastrados. Depois disso, efetivamos a alteração realizada pelo insert e mandamos listar os departamentos, novamente. Agora vamos analisar o resultado.
✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ ❉❡♣❛rt❛♠❡♥t♦s ✲✲✲✲✲✲✲✲✲✲✲
✶✵ ✲ ❆❈❈❖❯◆❚■◆●
✸✵ ✲ ❙❆▲❊❙
✹✵ ✲ ❖P❊❘❆❚■❖◆❙
✹✶ ✲ ●❊◆❊❘❆▲ ▲❊❉●❊❘
✹✷ ✲ P❯❘❈❍❆❙■◆●
✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ ❉❡♣❛rt❛♠❡♥t♦s ✲✲✲✲✲✲✲✲✲✲✲
✶✵ ✲ ❆❈❈❖❯◆❚■◆●
✸✵ ✲ ❙❆▲❊❙
✹✵ ✲ ❖P❊❘❆❚■❖◆❙
✹✶ ✲ ●❊◆❊❘❆▲ ▲❊❉●❊❘
✹✷ ✲ P❯❘❈❍❆❙■◆●
✹✸ ✲ ❖❘❉❊❘ ▼❆◆❆●❊❘
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
No resultado, temos duas listagens. Uma impressa após o comando
insert, e outra após a efetivação do insert através do comando commit.
Note que a impressão realizada antes do commit não mostra o departamento
285
Casa do Código
43, embora, ele já tenha sido inserido neste ponto. Já a impressão após o comando commit mostra o novo departamento.
Desta forma, temos que nos atentar para o seguinte cenário. Sabemos que,
quando é aberta uma transação no Oracle, ela monta uma imagem, digamos
assim, dos objetos e dados disponíveis para o usuário nesta sessão. Com relação aos dados, a visão permite enxergar somente aquilo que está efetivado
no banco de dados, ou seja, dados consistentes e íntegros. Isso quer dizer que
dados pendentes de efetivação não poderão ser visualizados, isso é, dados excluídos, inseridos ou atualizados que ainda não tenham sido commitados.
Logo, quando isto acontece, não conseguimos visualizar as alterações que
estão sendo realizadas. Quando temos um objeto utilizando transação autônoma, conseguimos manipular somente os dados efetivados. Dessa forma, se
nós realizarmos um comando select a fim de obter os dados alterados na
sessão original, mas não efetivados, não conseguiremos enxergá-los. Apenas
para ressaltar, isso se dá ao fato de que dentro deste objeto estamos em outro
escopo, em uma nova transação.
Outro ponto muito importante é que, quando utilizamos objetos com
transação autônoma, precisamos efetivar a transação através de um commit
ou de um rollback. Como este tipo de ação faz com que uma nova transação seja aberta, temos que finalizá-la. Caso contrário, ela ficaria pendente
e isso poderia gerar um erro.
Conforme visto no exemplo anterior, utilizamos a seguinte linha de comando pragma autonomous_transaction, na área de declaração, para
abrir uma nova transação. Veja outro exemplo a seguir.
Para este exemplo, criamos vários objetos. Primeiramente, criamos uma
procedure chamada lista_pais, que listará na tela todos os países já
cadastrados na tabela countries. Cada lista impressa terá um número indicando o número da impressão.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ❧✐st❛❴♣❛✐s✭♥✉♠❴❧✐st❛ ♥✉♠❜❡r✮ ✐s
✷
✲✲
✸ ❜❡❣✐♥
✹
✲✲
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ▲■❙❚❆❴P❆■❙✬✮❀
✻
✲✲
286
Casa do Código
✼
✽
Capítulo 18. Transações autônomas
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ P❛ís ✲ ✬⑤⑤♥✉♠❴❧✐st❛⑤⑤✬✲✲✲✲✲✲✲✲✲✲✲✬✮❀
❞❜♠s❴♦✉t♣✉t✳♥❡✇❴❧✐♥❡❀
✲✲
❢♦r ✐ ✐♥ ✭s❡❧❡❝t ✯ ❢r♦♠ ❝♦✉♥tr✐❡s ✇❤❡r❡ r❡❣✐♦♥❴✐❞ ❂ ✶
♦r❞❡r ❜② ❝♦✉♥tr②❴♥❛♠❡✮ ❧♦♦♣
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✐✳❝♦✉♥tr②❴✐❞⑤⑤✬ ✲
✬⑤⑤✐✳❝♦✉♥tr②❴♥❛♠❡✮❀
❡♥❞ ❧♦♦♣❀
✲✲
❡♥❞❀
✴
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
A procedure a seguir tem o objetivo de inserir um registro na tabela
countries referente ao país Portugal. Note que nesta procedure temos declarada uma transação autônoma. No corpo, além do comando insert,
temos a chamada à procedure lista_pais, que vai listar os países cadas-
trados. Esta listagem será a segunda lista a ser impressa. Logo após, temos
um commit que efetivará a ação do comando insert e encerrará a transação autônoma.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ✐♥s❡r❡❴♣❛✐s❴♣♦rt✉❣❛❧ ✐s
✷
✲✲
✸
♣r❛❣♠❛ ❛✉t♦♥♦♠♦✉s❴tr❛♥s❛❝t✐♦♥❀
✹
✲✲
✺ ❜❡❣✐♥
✻
✲✲
✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿
■◆❙❊❘❊❴P❆■❙❴P❖❘❚❯●❆▲✬✮❀
✽
✲✲
✾
✐♥s❡rt ✐♥t♦ ❝♦✉♥tr✐❡s ✭❝♦✉♥tr②❴✐❞✱ ❝♦✉♥tr②❴♥❛♠❡✱
r❡❣✐♦♥❴✐❞✮ ✶✵ ✈❛❧✉❡s ✭✬P❚✬✱
✬P♦rt✉❣❛❧✬✱✶✮❀
✶✶
✲✲
287
Casa do Código
✶✷
❧✐st❛❴♣❛✐s✭✷✮❀
✶✸
✲✲
✶✹
❝♦♠♠✐t❀
✶✺
✲✲
✶✻ ❡♥❞❀
✶✼ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
A próxima procedure tem a finalidade de apenas chamar a procedure
insere_pais_portugal. Ela serve apenas para, digamos assim, estabelecer uma ligação indireta entre as procedures insere_pais_espanha e
insere_pais_portugal.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ❝❤❛♠❛❴✐♥s❡r❡❴♣❛✐s❴♣♦rt✉❣❛❧ ✐s
✷
✲✲
✸ ❜❡❣✐♥
✹
✲✲
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿
❈❍❆▼❆❴■◆❙❊❘❊❴P❆■❙❴P❖❘❚❯●❆▲✬✮❀
✻
✲✲
✼
✐♥s❡r❡❴♣❛✐s❴♣♦rt✉❣❛❧❀
✽
✲✲
✾ ❡♥❞❀
✶✵ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Já a procedure insere_pais_espanha tem o objetivo de inserir um
registro na tabela countries referente ao país Espanha. No corpo da
procedure, além do comando insert, temos a chamada à procedure
lista_pais, que irá listar os países cadastrados. Esta listagem será a primeira lista a ser impressa. Logo após, temos um rollback que desfará a
ação do comando insert. Depois do rollback, temos uma nova cha288
Casa do Código
Capítulo 18. Transações autônomas
mada à procedure lista_pais, a segunda neste objeto, que imprime a terceira listagem.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ✐♥s❡r❡❴♣❛✐s❴❡s♣❛♥❤❛ ✐s
✷
✲✲
✸ ❜❡❣✐♥
✹
✲✲
✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿
■◆❙❊❘❊❴P❆■❙❴❊❙P❆◆❍❆✬✮❀
✻
✲✲
✼
✐♥s❡rt ✐♥t♦ ❝♦✉♥tr✐❡s ✭❝♦✉♥tr②❴✐❞✱ ❝♦✉♥tr②❴♥❛♠❡✱
r❡❣✐♦♥❴✐❞✮
✽
✈❛❧✉❡s ✭✬❊❙✬✱✬❊s♣❛♥❤❛✬✱✶✮❀
✾
✲✲
✶✵
❧✐st❛❴♣❛✐s✭✶✮❀
✶✶
✲✲
✶✷
❝❤❛♠❛❴✐♥s❡r❡❴♣❛✐s❴♣♦rt✉❣❛❧❀
✶✸
✲✲
✶✹
r♦❧❧❜❛❝❦❀
✶✺
✲✲
✶✻
❧✐st❛❴♣❛✐s✭✸✮❀
✶✼
✲✲
✶✽ ❡♥❞❀
✶✾ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Note que em todos os objetos temos chamadas à procedure
dbms_output, indicando a execução do objeto corrente. Usaremos
esta identificação para saber a ordem cronológica da execução dos programas. Agora vamos executar a procedure insere_pais_espanha, que é a
que desencadeará a execução dos demais objetos criados.
❙◗▲❃ ❜❡❣✐♥
✷
✐♥s❡r❡❴♣❛✐s❴❡s♣❛♥❤❛❀
✸ ❡♥❞❀
✹ ✴
289
Casa do Código
Esse código PL/SQL executa a procedure insere_pais_espanha, que
chama as demais procedures onde obtivemos os resultados a seguir.
Neste nosso exemplo, ao executarmos essa procedure, primeiramente, o
país Espanha foi inserido na tabela countries. Logo após a inserção, mandamos listar os países. O resultado da listagem 1 é mostrado a seguir.
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ■◆❙❊❘❊❴P❆■❙❴❊❙P❆◆❍❆
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ▲■❙❚❆❴P❆■❙
✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ P❛ís ✲ ✶✲✲✲✲✲✲✲✲✲✲✲
❇❊ ✲ ❇❡❧❣✐✉♠
❉❑ ✲ ❉❡♥♠❛r❦
❊❙ ✲ ❊s♣❛♥❤❛
❋❘ ✲ ❋r❛♥❝❡
❉❊ ✲ ●❡r♠❛♥②
■❚ ✲ ■t❛❧②
◆▲ ✲ ◆❡t❤❡r❧❛♥❞s
❈❍ ✲ ❙✇✐t③❡r❧❛♥❞
❯❑ ✲ ❯♥✐t❡❞ ❑✐♥❣❞♦♠
Note que, na terceira linha da listagem, temos o país Espanha inserido. Logo após a execução do procedimento de listagem, continuando a
execução da procedure insere_pais_espanha, foi chamada a procedure chama_insere_pais_portugal, que por sua vez, chama a procedure insere_pais_portugal. A procedure insere_pais_portugal
será executada em outra transação, pois nela declaramos um pragma
autonomous_transaction. Ela executa o insert referente ao país Portugal e logo em seguida executa a impressão da listagem 2. Para encerrar, um
commit é executado, efetivando as operações. Veja o resultado.
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ❈❍❆▼❆❴■◆❙❊❘❊❴P❆■❙❴P❖❘❚❯●❆▲
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ■◆❙❊❘❊❴P❆■❙❴P❖❘❚❯●❆▲
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ▲■❙❚❆❴P❆■❙
✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ P❛ís ✲ ✷✲✲✲✲✲✲✲✲✲✲✲
❇❊ ✲ ❇❡❧❣✐✉♠
❉❑ ✲ ❉❡♥♠❛r❦
❋❘ ✲ ❋r❛♥❝❡
❉❊ ✲ ●❡r♠❛♥②
■❚ ✲ ■t❛❧②
290
Casa do Código
◆▲
P❚
❈❍
❯❑
✲
✲
✲
✲
Capítulo 18. Transações autônomas
◆❡t❤❡r❧❛♥❞s
P♦rt✉❣❛❧
❙✇✐t③❡r❧❛♥❞
❯♥✐t❡❞ ❑✐♥❣❞♦♠
Veja que aqui não apareceu o país Espanha. Isso porque a procedure
insere_pais_portugal foi executada dentro de uma transação autônoma, logo, quando ela chama a listagem, apenas os dados efetivados e os
da sessão corrente são visualizados.
Após o término da execução da procedure insere_pais_portugal,
voltamos para a procedure insere_pais_espanha, onde, na sequência
do programa, temos um rollback, desfazendo tudo que ficou pendente na
sessão. Após desfazer as ações, executamos a listagem de número 3. A seguir,
o resultado.
❊①❡❝✉t❛♥❞♦ ♣r♦❝❡❞✉r❡✿ ▲■❙❚❆❴P❆■❙
✲✲✲✲✲✲✲✲✲✲✲ ▲✐st❛ P❛ís ✲ ✸✲✲✲✲✲✲✲✲✲✲✲
❇❊ ✲ ❇❡❧❣✐✉♠
❉❑ ✲ ❉❡♥♠❛r❦
❋❘ ✲ ❋r❛♥❝❡
❉❊ ✲ ●❡r♠❛♥②
■❚ ✲ ■t❛❧②
◆▲ ✲ ◆❡t❤❡r❧❛♥❞s
P❚ ✲ P♦rt✉❣❛❧
❈❍ ✲ ❙✇✐t③❡r❧❛♥❞
❯❑ ✲ ❯♥✐t❡❞ ❑✐♥❣❞♦♠
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note que na saída da listagem final (listagem 3) temos cadastrado o país
Portugal, mas não o país Espanha. O rollback acabou desfazendo a inserção referente ao país Espanha, mas não a inserção referente ao país Portugal,
pois esta inserção foi realizada e efetivada via outra transação, a transação
autônoma.
Não é comum ver transações autônomas sendo utilizadas em programas
PL/SQL, contudo, em alguns casos elas se tornam imprescindíveis. Quando
291
Casa do Código
estivermos trabalhando com triggers (capítulo mais a seguir), será visto
que, para o disparo de determinados tipos de triggers em situações específicas, somos obrigados a usar transações autônomas para poder atender o
objetivo.
292
Capítulo 19
Triggers
O objeto trigger nada mais é do que um bloco de código PL/SQL armazenado no banco de dados e que é disparado automaticamente mediante uma
ação. Este disparo pode ocorrer de duas formas, por intermédio de alterações
feitas em registros de uma determinada tabela, neste caso se tratando do disparo de um trigger de banco de dados ou por ações em nível de sistema
por um trigger de sistema.
Vamos aprender sobre estes dois tipos, mostrando as características dos
triggers de banco de dados que são muito utilizados no desenvolvimento
de programas e dos triggers de sistema que são mais utilizados pelos administradores de banco de dados.
19.1. Trigger de banco de dados
Casa do Código
19.1 Trigger de banco de dados
Um trigger de banco de dados sempre está associado a uma tabela. Não
existindo tabela, não existe trigger de bando de dados. Quando queremos
que uma ação aconteça automaticamente mediante uma alteração em alguma
tabela, ou melhor, nos registros que ela possui, podemos utilizá-los para isto.
Um trigger pode disparar quando alguma ação ocorre em uma tabela
e também em um determinado momento. Por exemplo, podemos criar um
trigger que dispare quando fizermos um update em determinada tabela,
e que ocorra após o update dos registros. Além disso, podemos definir que
este trigger disparará para cada linha afetada pelo comando dml, chamado de trigger de linha, ou se executará uma única vez independente de
quantas linhas sofrerem alterações. Este último, nós chamamos de trigger de
tabela ou de comando. Também podemos definir cláusulas where para o
trigger para que o disparo só aconteça se alguns critérios forem obedecidos.
19.2 Trigger de tabela
Vamos analisar a definição do trigger.
❝r❡❛t❡ tr✐❣❣❡r t✐♣♦❴t❛❜❡❧❛
❜❡❢♦r❡ ❞❡❧❡t❡ ♦r ✐♥s❡rt ♦r ✉♣❞❛t❡ ♦❢ s❛❧ ♦♥ ❡♠♣
❜❡❣✐♥
❡♥❞❀
Para criar um trigger, primeiramente damos um nome. Utilizamos o
comando create trigger para criar o objeto. Temos obrigatoriamente
que definir quando será o disparo. Neste exemplo, informamos que seu disparo ocorrerá antes da ação, neste caso before. Caso tenhamos necessidade
que o disparo ocorra depois, informamos after.
Vamos abrir um parênteses aqui para explicar melhor esta questão de
after e before na especificação do trigger. A expressão before definida no trigger pode ser um pouco confusa, pois dá a impressão que o
trigger vai detectar que vamos executar um insert, por exemplo, e antes
de acontecer tal ação ele dispara o trigger.
294
Casa do Código
Capítulo 19. Triggers
Mas não é bem assim. Na verdade, o before quer dizer antes que as
alterações sejam feitas nos registros da tabela em questão, ou seja, podemos
dizer que o Oracle faz as alterações primeiramente em memória, para depois
efetivá-las no banco de dados. Com isso, dependendo do momento tratado,
before ou after, podemos ou não alterar estes dados.
Quando o trigger é disparado no momento before, os dados ainda
não foram efetivados, neste caso podemos alterar os valores antes que eles
sejam gravados no banco de dados. Quando é disparado no after não há
mais como alterá-los, pois já foram efetivados no banco de dados.
Depois de definir quando ocorrerá, precisamos informar em quais situações, ou melhor, ações, o trigger deve disparar. Note que para esta definição foi determinado que o disparo sempre ocorrerá quando a tabela emp
sofrer um delete, insert ou update específico na coluna sal. Nos
casos de update, podemos ou não informar colunas específicas para determinar o disparo. Neste exemplo, qualquer atualização que não seja na coluna
sal da tabela emp o trigger não vai disparar. Caso não queira definir
colunas específicas apenas não use a expressão of.
Este trigger pode ser caracterizado como um trigger de tabela, pois
não informamos que ele vai disparar para cada linha afetada. Portanto, não
importa quantas linhas serão excluídas, inseridas ou atualizadas, ele sempre
disparará uma única vez.
Na sequência, segue um exemplo de trigger de tabela e sua aplicação. Vamos criar um trigger que fará a auditoria da tabela emp. Cada vez que
um ou mais registros forem inseridos ou atualizados, este programa vai calcular a quantidade de registros contidos na tabela emp, a soma de todos os
salários e comissões. Esses dados serão inseridos em uma tabela chamada
tab_audit_emp. Vamos criar a tabela:
❙◗▲❃
✷
✸
✹
✺
✻
✼
❝r❡❛t❡ t❛❜❧❡ t❛❜❴❛✉❞✐t❴❡♠♣
✭
♥r❴r❡❣✐str♦s
♥✉♠❜❡r
✱✈❧❴t♦t❛❧❴s❛❧❛r✐♦ ♥✉♠❜❡r
✱✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦ ♥✉♠❜❡r
✮
✴
295
19.2. Trigger de tabela
Casa do Código
❚❛❜❡❧❛ ❝r✐❛❞❛✳
❙◗▲❃
Segue o código da trigger:
❙◗▲❃ ❝r❡❛t❡ tr✐❣❣❡r t✐❣❴❛✉❞✐t❴❡♠♣
✷
❛❢t❡r ✐♥s❡rt ♦r ❞❡❧❡t❡ ♦r ✉♣❞❛t❡ ♦❢ s❛❧✱ ❝♦♠♠ ♦♥ ❡♠♣
✸ ❞❡❝❧❛r❡
✹
✇♥r❴r❡❣✐str♦s
♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✺
✇✈❧❴t♦t❛❧❴s❛❧❛r✐♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✻
✇✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✼
✇♥r❴r❡❣✐str♦s❴❛✉❞✐t ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✽ ❜❡❣✐♥
✾
s❡❧❡❝t ❝♦✉♥t✭✯✮
✶✵
✐♥t♦ ✇♥r❴r❡❣✐str♦s
✶✶
❢r♦♠ ❡♠♣❀
✶✷
✲✲
✶✸
s❡❧❡❝t s✉♠✭s❛❧✮
✶✹
✐♥t♦ ✇✈❧❴t♦t❛❧❴s❛❧❛r✐♦
✶✺
❢r♦♠ ❡♠♣❀
✶✻
✲✲
✶✼
s❡❧❡❝t s✉♠✭❝♦♠♠✮
✶✽
✐♥t♦ ✇✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦
✶✾
❢r♦♠ ❡♠♣❀
✷✵
✲✲
✷✶
s❡❧❡❝t ❝♦✉♥t✭✯✮
✷✷
✐♥t♦ ✇♥r❴r❡❣✐str♦s❴❛✉❞✐t
✷✸
❢r♦♠ t❛❜❴❛✉❞✐t❴❡♠♣❀
✷✹
✲✲
✷✺
✐❢ ✇♥r❴r❡❣✐str♦s❴❛✉❞✐t ❂ ✵ t❤❡♥
✷✻
✲✲
✷✼
✐♥s❡rt ✐♥t♦ t❛❜❴❛✉❞✐t❴❡♠♣ ✭
♥r❴r❡❣✐str♦s✱ ✈❧❴t♦t❛❧❴s❛❧❛r✐♦✱ ✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦✮
✷✽
✈❛❧✉❡s ✭✇♥r❴r❡❣✐str♦s✱ ✇✈❧❴t♦t❛❧❴s❛❧❛r✐♦✱
✇✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦✮❀
✷✾
✲✲
✸✵
❡❧s❡
✸✶
✲✲
✸✷
✉♣❞❛t❡ t❛❜❴❛✉❞✐t❴❡♠♣
296
Casa do Código
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
s❡t
✲✲
❡♥❞ ✐❢❀
❡♥❞❀
✴
Capítulo 19. Triggers
♥r❴r❡❣✐str♦s
❂ ✇♥r❴r❡❣✐str♦s
✱✈❧❴t♦t❛❧❴s❛❧❛r✐♦ ❂ ✇✈❧❴t♦t❛❧❴s❛❧❛r✐♦
✱✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦ ❂ ✇✈❧❴t♦t❛❧❴❝♦♠✐ss❛♦❀
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Vamos entender o que este trigger faz. Primeiramente, chamamos este
de tig_audit_emp. Ele vai disparar após a tabela emp sofrer um comando
insert, delete ou update, sendo que para este último, somente quando
as colunas sal ou comm forem alteradas. Note que a linha for each row
não aparece. Isso indica que nosso trigger é um de tabela. Portanto, não
importa a quantidade de linhas afetadas pelo comando, ele só vai disparar
uma única vez. O trigger também só vai ser disparado após ( after) os
comandos insert, delete ou update forem efetivados.
Dentro destas condições o trigger dispara e executa comandos SQL
para buscar as informações que serão utilizadas para gerar nossa auditoria,
como a quantidade de registros na tabela, a soma de todos os salários e comissões. Isso justifica o fato de o trigger ser disparado uma única vez, pois
neste disparo ele varre todos os registros da tabela, não necessitando trabalhar
registro por registro afetado.
Depois de buscar as informações, o programa faz um select para verificar se já existe um registro na tabela de auditoria. Caso exista, ele somente
atualiza as informações existentes. Caso contrário, insere um registro. Vamos
testá-lo. Primeiramente, verificamos a tabela tab_audit_emp.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❛✉❞✐t❴❡♠♣❀
♥ã♦ ❤á ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s
❙◗▲❃
297
Casa do Código
19.2. Trigger de tabela
Agora vamos pegar uma massa de teste para realizar uma atualização nos
dados da tabela emp.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵
✷ ✴
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✺✻✻
✼✼✽✽
✼✽✼✻
✼✾✵✷
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✼✾✵✷ ✶✼✴✶✷✴✽✵
✽✽✵
▼❆◆❆●❊❘
✼✽✸✾ ✵✷✴✵✹✴✽✶
✸✷✼✷✱✺
❆◆❆▲❨❙❚
✼✺✻✻ ✵✾✴✶✷✴✽✷
✸✸✵✵
❈▲❊❘❑
✼✼✽✽ ✶✷✴✵✶✴✽✸
✶✷✶✵
❆◆❆▲❨❙❚
✼✺✻✻ ✵✸✴✶✷✴✽✶
✸✸✵✵
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✷✵
✷✵
✷✵
✷✵
✷✵
❙◗▲❃
Vamos atualizar os salários de todos os empregados que estão alocados
no departamento 20.
❙◗▲❃
✷
✸
✹
✉♣❞❛t❡ ❡♠♣
s❡t
s❛❧ ❂ s❛❧ ✰ ✭s❛❧ ✯ ✶✵ ✴ ✶✵✵✮
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵
✴
✺ ❧✐♥❤❛s ❛t✉❛❧✐③❛❞❛s✳
❙◗▲❃ ❝♦♠♠✐t❀
❱❛❧✐❞❛çã♦ ❝♦♠♣❧❡t❛✳
298
Casa do Código
Capítulo 19. Triggers
❙◗▲❃
Vamos verificar as atualizações na tabela emp.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✺✻✻
✼✼✽✽
✼✽✼✻
✼✾✵✷
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✼✾✵✷ ✶✼✴✶✷✴✽✵
✾✻✽
▼❆◆❆●❊❘
✼✽✸✾ ✵✷✴✵✹✴✽✶
✸✺✾✾✱✼✺
❆◆❆▲❨❙❚
✼✺✻✻ ✵✾✴✶✷✴✽✷
✸✻✸✵
❈▲❊❘❑
✼✼✽✽ ✶✷✴✵✶✴✽✸
✶✸✸✶
❆◆❆▲❨❙❚
✼✺✻✻ ✵✸✴✶✷✴✽✶
✸✻✸✵
❈❖▼▼
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✷✵
✷✵
✷✵
✷✵
✷✵
❙◗▲❃
Ok. Os dados foram atualizados. Agora vamos verificar nossa tabela de
auditoria.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❛✉❞✐t❴❡♠♣❀
◆❘❴❘❊●■❙❚❘❖❙ ❱▲❴❚❖❚❆▲❴❙❆▲❆❘■❖ ❱▲❴❚❖❚❆▲❴❈❖▼■❙❙❆❖
✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶✹
✸✶✸✵✽✱✼✺
✷✷✹✹
❙◗▲❃
Note que o trigger realizou o cálculo considerando não só as linhas
afetadas, mas sim todas as linhas da tabela, como era o esperado, ou seja, foi
criado um registro nesta tabela contendo informações referentes a todos os
299
19.2. Trigger de tabela
Casa do Código
registros de funcionários cadastrados. Agora vamos excluir alguns registros
da tabela emp.
❙◗▲❃ ❞❡❧❡t❡ ❢r♦♠ ❡♠♣
✷ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵
✸ ✴
✸ ❧✐♥❤❛s ❞❡❧❡t❛❞❛s✳
❙◗▲❃ ❝♦♠♠✐t❀
❱❛❧✐❞❛çã♦ ❝♦♠♣❧❡t❛✳
❙◗▲❃
Ok. Excluímos os dados com sucesso. Agora vamos verificar nossa tabela
de auditoria.
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❛✉❞✐t❴❡♠♣❀
◆❘❴❘❊●■❙❚❘❖❙ ❱▲❴❚❖❚❆▲❴❙❆▲❆❘■❖ ❱▲❴❚❖❚❆▲❴❈❖▼■❙❙❆❖
✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶✶
✷✷✺✺✽✱✼✺
✷✷✹✹
❙◗▲❃
Por último, vamos testar a inserção de dados.
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷
✈❛❧✉❡s ✭✼✾✸✺✱ ✬P❆❯▲❖✬✱ ✬❈▲❊❘❑✬✱ ✼✾✵✷✱
t♦❴❞❛t❡✭✬✶✼✴✵✾✴✷✵✶✶✬✱✬❞❞✴♠♠✴②②②②✬✮✱
✶✵✵✵✱ ♥✉❧❧✱ ✷✵✮❀
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
Novo resultado.
300
Casa do Código
Capítulo 19. Triggers
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❛✉❞✐t❴❡♠♣❀
◆❘❴❘❊●■❙❚❘❖❙ ❱▲❴❚❖❚❆▲❴❙❆▲❆❘■❖ ❱▲❴❚❖❚❆▲❴❈❖▼■❙❙❆❖
✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶✷
✷✸✺✺✽✱✼✺
✷✷✹✹
❙◗▲❃
Apresentamos aqui apenas uma forma de como utilizar os triggers de
tabela. Contudo, as possibilidades de utilização são muitas. Tudo vai depender da necessidade.
19.3 Trigger de linha
Muito parecido com o trigger de tabela, o de linha tem praticamente as mesmas características, sendo por um detalhe: o trigger de linha dispara para cada
linha afetada pelo comando dml. Veja o exemplo na sequência.
❝r❡❛t❡ ♦r r❡♣❧❛❝❡
❛❢t❡r ✉♣❞❛t❡ ♦♥
r❡❢❡r❡♥❝✐♥❣ ♦❧❞
♥❡✇
❢♦r ❡❛❝❤ r♦✇
❜❡❣✐♥
tr✐❣❣❡r t✐♣♦❴❧✐♥❤❛
❢✉♥❝
❛s ❱
❛s ◆
❡♥❞❀
Neste exemplo temos algo mais do que a definição de quando e como
o trigger será disparado. Estamos definindo que ele será do tipo linha,
ou seja, ele vai disparar para cada linha afetada pelo update. Para isso foi
colocado em sua definição a seguinte linha de comando: for each row.
Quando trabalhamos com trigger de linha, podemos manipular os valores das linhas afetadas. Em alguns casos, podemos até alterar os valores de
certas colunas antes de as mesmas serem salvas. Quando definimos que um
trigger é de linha, o Oracle cria duas referências chamadas old e new. Estas referências apontam sempre para os dados anteriores às alterações e para
os dados posteriores às alterações, respectivamente.
301
19.3. Trigger de linha
Casa do Código
Por exemplo, se alteramos o valor da coluna sal de 100 para 500,
old.sal conterá o valor 100 e new.sal conterá o valor 500. E assim será
para todos os valores das colunas da tabela que estão sendo afetadas ou não
pelo comando.
Quando temos um trigger sendo disparado no before, ou seja, antes
do comando dml, nós podemos alterar o valor de new. O valor de old
nunca pode ser alterado. Caso a alteração seja no after, nem old nem
new podem ser alterados. Nem sempre teremos os valores de old e new.
Quando estamos atualizando os registros em uma tabela teremos o new e o
old, pois neste caso estamos atualizando um registro que já existe.
Quando estamos inserindo um registro, não temos os valores de old,
pois se trata de um registro novo, não havendo assim valores antigos. Quando
estamos excluindo um registro temos o old e não temos o new, pois estamos
excluindo um registro, não informando dados novos.
As referências old e new podem receber apelidos. Neste caso utilizamos
a diretriz referencing para definir esta informação. Neste exemplo, estamos criando os seguintes alias: V para old e N para new. Logo, quando
formos trabalhar com as colunas devemos usar, por exemplo, v.sal para
pegar o valor antigo e n.sal para o novo.
Veremos a seguir uma aplicação de trigger de linha onde criaremos um
histórico para a troca de cargos dos empregados. Cada vez que um empregado trocar de cargo, um histórico contendo algumas informações será guardado. Neste histórico teremos o código do empregado, o cargo anterior, o
novo cargo, a data da alteração e uma descrição. Para isso, vamos criar uma
tabela que será o repositório destas informações históricas.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
302
❝r❡❛t❡ t❛❜❧❡ t❛❜❴❤✐st❴❝❛r❣♦❴❡♠♣
✭
❡♠♣♥♦
♥✉♠❜❡r
✱❥♦❜❴❛♥t❡r✐♦r
✈❛r❝❤❛r✷✭✾✮
✱❥♦❜❴❛t✉❛❧
✈❛r❝❤❛r✷✭✾✮
✱❞t❴❛❧t❡r❛❝❛♦❴❝❛r❣♦ ❞❛t❡
✱❞s❴❤✐st♦r✐❝♦
✈❛r❝❤❛r✷✭✷✵✵✵✮
✮
✴
Casa do Código
Capítulo 19. Triggers
❚❛❜❡❧❛ ❝r✐❛❞❛✳
❙◗▲❃
Criamos a tab_hist_cargo_emp que abrigará as informações que
compõem o nosso histórico. Agora vamos para o trigger que fará este
controle.
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
❝r❡❛t❡ tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣
❛❢t❡r ✉♣❞❛t❡ ♦❢ ❥♦❜ ♦♥ ❡♠♣
r❡❢❡r❡♥❝✐♥❣ ♦❧❞ ❛s ✈
♥❡✇ ❛s ♥
❢♦r ❡❛❝❤ r♦✇
❜❡❣✐♥
✐♥s❡rt ✐♥t♦ t❛❜❴❤✐st❴❝❛r❣♦❴❡♠♣ ✭ ❡♠♣♥♦
✱❥♦❜❴❛♥t❡r✐♦r
✱❥♦❜❴❛t✉❛❧
✱❞t❴❛❧t❡r❛❝❛♦❴❝❛r❣♦
✱❞s❴❤✐st♦r✐❝♦✮
✈❛❧✉❡s ✭ ✿♥✳❡♠♣♥♦
✱✿✈✳❥♦❜
✱✿♥✳❥♦❜
✱s②s❞❛t❡
✱✬❖ ❡♠♣r❡❣❛❞♦ ✬⑤⑤✿♥✳❡♥❛♠❡⑤⑤
✬ ♣❛ss♦✉ ♣❛r❛ ♦ ❝❛r❣♦ ✬⑤⑤✿♥✳❥♦❜⑤⑤
✬ ❡♠ ❝❛r❛t❡r ❞❡ ♣r♦♠♦çã♦✳✬✮❀
❡♥❞❀
✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Cada vez que o trigger tig_hist_cargo_emp disparar, depois da
atualização de um cargo, será gravado um histórico, ou seja, uma linha, na
tabela tab_hist_cargo_emp contendo as informações pertinentes à alteração do cargo. O trigger vai disparar para cada linha alterada. Vamos
testá-lo.
303
19.3. Trigger de linha
❙◗▲❃
✷
✸
✹
Casa do Código
✉♣❞❛t❡ ❡♠♣
s❡t
❥♦❜ ❂ ✬▼❆◆❆●❊❘✬
✇❤❡r❡ ❡♠♣♥♦ ❂ ✼✹✾✾
✴
✶ ❧✐♥❤❛ ❛t✉❛❧✐③❛❞❛✳
❙◗▲❃
Verificando o histórico:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❤✐st❴❝❛r❣♦❴❡♠♣
✷ ✴
❊▼P◆❖ ❏❖❇❴❆◆❚❊❘ ❏❖❇❴❆❚❯❆▲ ❉❚❴❆▲❚❊❘
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲
✼✹✾✾ ❙❆▲❊❙▼❆◆ ▼❆◆❆●❊❘ ✵✺✴✵✾✴✶✶
❉❙❴❍■❙❚❖❘■❈❖
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❖ ❡♠♣r❡❣❛❞♦ ❆▲▲❊◆ ♣❛ss♦✉ ♣❛r❛ ♦ ❝❛r❣♦ ▼❆◆❆●❊❘ ❡♠ ❝❛r❛t❡r ❞❡
♣r♦♠♦çã♦✳
❙◗▲❃
Muito bem. O histórico foi criado informando que o empregado allen
mudou de cargo. Agora vamos a outro exemplo. Criaremos um trigger
que irá calcular e guardar na tabela emp o percentual referente à comissão
em relação ao salário do empregado. Para isso, vamos incluir uma coluna
na tabela emp chamada pc_com_sal. Neste trigger, faremos uso na
cláusula when para determinar quais os registros poderão sofre este cálculo.
Vale salientar que a cláusula when pode ser usada tanto para os triggers de
linhas como para os de tabela.
Alterando a tabela emp:
❙◗▲❃ ❛❧t❡r t❛❜❧❡ ❡♠♣ ❛❞❞ ♣❝❴❝♦♠❴s❛❧ ♥✉♠❜❡r❀
❚❛❜❡❧❛ ❛❧t❡r❛❞❛✳
304
Casa do Código
Capítulo 19. Triggers
❙◗▲❃
Criando o trigger:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
❝r❡❛t❡ tr✐❣❣❡r t✐❣❴♣❝❴❝♦♠❴s❛❧❴❡♠♣
❜❡❢♦r❡ ✐♥s❡rt ♦r ✉♣❞❛t❡ ♦❢ s❛❧✱ ❝♦♠♠ ♦♥ ❡♠♣
r❡❢❡r❡♥❝✐♥❣ ♦❧❞ ❛s ✈
♥❡✇ ❛s ♥
❢♦r ❡❛❝❤ r♦✇
✇❤❡♥ ✭♥✳❥♦❜ ❂ ✬❙❆▲❊❙▼❆◆✬✮
❜❡❣✐♥
✿♥✳♣❝❴❝♦♠❴s❛❧ ✿❂ ♥✈❧✭✿♥✳❝♦♠♠✱✵✮ ✯ ✶✵✵ ✴ ✿♥✳s❛❧❀
❡♥❞❀
✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Note que agora criamos um trigger que vai disparar no before, ou
seja, antes das informações serem efetivadas no banco de dados. Usamos o
before, pois o programa estará alterando um dado, ou melhor, o valor de
uma coluna, referente à mesma linha que vai disparar o trigger. Portanto,
isso deve acontecer antes que as informações sejam efetivadas. Se usássemos
after, não conseguiríamos fazer tal alteração. Utilizamos a cláusula when
para determinar que o trigger só vá disparar quando a linha em questão
for de algum empregado que tenha como cargo ( job) igual a salesman.
Vamos testá-lo.
❙◗▲❃ s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ❝♦♠♠✱ ♣❝❴❝♦♠❴s❛❧ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❏❖❇
❙❆▲
❈❖▼▼ P❈❴❈❖▼❴❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
❙❆▲❊❙▼❆◆
✶✻✵✵
✸✵✻
❙❆▲❊❙▼❆◆
✶✷✺✵
✺✶✵
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
❙❆▲❊❙▼❆◆
✶✷✺✵
✶✹✷✽
305
Casa do Código
19.3. Trigger de linha
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
▼❆◆❆●❊❘
▼❆◆❆●❊❘
❆◆❆▲❨❙❚
P❘❊❙■❉❊◆❚
❙❆▲❊❙▼❆◆
❈▲❊❘❑
❈▲❊❘❑
❆◆❆▲❨❙❚
❈▲❊❘❑
✷✽✺✵
✷✹✺✵
✸✻✸✵
✺✵✵✵
✶✺✵✵
✶✸✸✶
✾✺✵
✸✻✸✵
✶✸✵✵
✵
✶✹ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣ s❡t s❛❧ ❂ s❛❧❀
✶✹ ❧✐♥❤❛s ❛t✉❛❧✐③❛❞❛s✳
❙◗▲❃
Primeiramente, verificamos os dados da tabela emp. Logo após, executamos um update apenas para que nosso trigger dispare. Note que o
update atualiza todos os salários dos empregados com o mesmo salário. Fizemos isso apenas para que todas as linhas sejam varridas e que o cálculo do
percentual seja realizado para os registros já cadastrados. Vamos ver o resultado.
❙◗▲❃ s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ❝♦♠♠✱ ♣❝❴❝♦♠❴s❛❧ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
306
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❏❖❇
❙❆▲
❈❖▼▼ P❈❴❈❖▼❴❙❆▲
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
❙❆▲❊❙▼❆◆
✶✻✵✵
✸✵✻
✶✾✱✶✷✺
❙❆▲❊❙▼❆◆
✶✷✺✵
✺✶✵
✹✵✱✽
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
❙❆▲❊❙▼❆◆
✶✷✺✵
✶✹✷✽
✶✶✹✱✷✹
▼❆◆❆●❊❘
✷✽✺✵
▼❆◆❆●❊❘
✷✹✺✵
❆◆❆▲❨❙❚
✸✻✸✵
P❘❊❙■❉❊◆❚
✺✵✵✵
❙❆▲❊❙▼❆◆
✶✺✵✵
✵
✵
Casa do Código
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
Capítulo 19. Triggers
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
❈▲❊❘❑
❈▲❊❘❑
❆◆❆▲❨❙❚
❈▲❊❘❑
✶✸✸✶
✾✺✵
✸✻✸✵
✶✸✵✵
✶✹ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Veja que a coluna pc_com_sal recebeu o cálculo do percentual, conforme a ação disparada via trigger. Também podemos observar que somente os registros cujos empregados tenham como cargo salesman sofreram esta ação. Agora vamos inserir um novo empregado, com o cargo igual
a salesman e outro com o cargo clerk, e vamos ver o que acontece.
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷
✈❛❧✉❡s ✭✼✾✹✵✱✬P❊❉❘❖✬✱✬❈▲❊❘❑✬✱✼✼✽✽✱
t♦❴❞❛t❡✭✬✵✺✴✵✾✴✷✵✶✶✬✱✬❞❞✴♠♠✴rrrr✬✮✱✼✺✵✱✶✵✵✱✸✵✮❀
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱
❝♦♠♠✱ ❞❡♣t♥♦✮
✷
✈❛❧✉❡s ✭✼✾✹✶✱✬❏❖❆❖✬✱✬❙❆▲❊❙▼❆◆✬✱✼✻✾✽✱
t♦❴❞❛t❡✭✬✵✺✴✵✾✴✷✵✶✶✬✱✬❞❞✴♠♠✴rrrr✬✮✱✶✷✵✵✱✸✺✵✱✸✵✮
✸ ✴
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
Verificando a tabela emp.
❙◗▲❃ s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ❝♦♠♠✱ ♣❝❴❝♦♠❴s❛❧ ❢r♦♠ ❡♠♣❀
❊▼P◆❖ ❊◆❆▼❊
❏❖❇
❙❆▲
❈❖▼▼ P❈❴❈❖▼❴❙❆▲
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✼✸✻✾ ❙▼■❚❍
❈▲❊❘❑
✾✻✽
307
Casa do Código
19.3. Trigger de linha
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✼✾✹✵
✼✾✹✶
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
P❊❉❘❖
❏❖❆❖
❙❆▲❊❙▼❆◆
❙❆▲❊❙▼❆◆
▼❆◆❆●❊❘
❙❆▲❊❙▼❆◆
▼❆◆❆●❊❘
▼❆◆❆●❊❘
❆◆❆▲❨❙❚
P❘❊❙■❉❊◆❚
❙❆▲❊❙▼❆◆
❈▲❊❘❑
❈▲❊❘❑
❆◆❆▲❨❙❚
❈▲❊❘❑
❈▲❊❘❑
❙❆▲❊❙▼❆◆
✶✻✵✵
✶✷✺✵
✸✺✾✾✱✼✺
✶✷✺✵
✷✽✺✵
✷✹✺✵
✸✻✸✵
✺✵✵✵
✶✺✵✵
✶✸✸✶
✾✺✵
✸✻✸✵
✶✸✵✵
✼✺✵
✶✷✵✵
✸✵✻
✺✶✵
✶✾✱✶✷✺
✹✵✱✽
✶✹✷✽
✶✶✹✱✷✹
✵
✵
✶✵✵
✸✺✵ ✷✾✱✶✻✻✻✻✻✼
✶✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Analisando as informações podemos constatar que o empregado pedro,
embora tenha recebido valores de salário e comissão, não sofreu o cálculo
do percentual. Isso ocorreu pelo fato de ele não ter como cargo, salesman.
Neste caso, o trigger não disparou. Já para o empregado joao, o trigger
disparou e calculou o percentual.
Aqui apresentamos alguns exemplos simples, apenas para mostrar o funcionamento dos triggers. Contudo, dependendo da necessidade podemos
escrever códigos complexos para atender às mais variadas situações que podem surgir. Mesmo porque, como pode ser visto, um trigger nada mais é
que um bloco PL/SQL, ou seja, um programa, que é programado para disparar de forma automática.
Predicados condicionais para triggers de banco de dados
Vimos que um mesmo trigger pode disparar por um ou mais tipos de
ações, como no insert, delete e update. Contudo, dependendo da ação
ocorrida na tabela, podem surgir necessidades diferentes para cada uma. Para
isso, usamos os predicados condicionais que nos dizem qual ação resultou
308
Casa do Código
Capítulo 19. Triggers
no disparo do trigger. Estes predicados são: inserting, updating
e deleting. Seus possíveis valores são true e false. Veja o exemplo a
seguir, onde criaremos um histórico para gravar as ações de manipulação dos
departamentos cadastrados na tabela dept. Criando a tabela:
❙◗▲❃ ❝r❡❛t❡ t❛❜❧❡ t❛❜❴❤✐st❴❞❡♣t
✷ ✭ ❞❡♣t♥♦ ♥✉♠❜❡r
✸
✱❞t❴❤✐st♦r✐❝♦ ❞❛t❡
✹
✱❞s❴❤✐st♦r✐❝♦ ✈❛r❝❤❛r✷✭✷✵✵✵✮
✺ ✮
✻ ✴
❚❛❜❡❧❛ ❝r✐❛❞❛✳
❙◗▲❃
Nesta tabela será gravado o código do departamento, a data da ação e também um descritivo do histórico. Vamos criar o trigger que fará o controle
de histórico.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❤✐st❴❞❡♣t
✷
❛❢t❡r ✐♥s❡rt ♦r ❞❡❧❡t❡ ♦r ✉♣❞❛t❡ ♦♥ ❞❡♣t
✸
❢♦r ❡❛❝❤ r♦✇
✹ ❞❡❝❧❛r❡
✺
✇❛❝❛♦ ✈❛r❝❤❛r✷✭✷✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✻ ❜❡❣✐♥
✼
✲✲
✽
✐❢ ✐♥s❡rt✐♥❣ t❤❡♥
✾
✇❛❝❛♦ ✿❂ ✬✐♥s❡r✐❞♦✬❀
✶✵
❡❧s✐❢ ✉♣❞❛t✐♥❣ t❤❡♥
✶✶
✇❛❝❛♦ ✿❂ ✬❛t✉❛❧✐③❛❞♦✬❀
✶✷
❡❧s✐❢ ❞❡❧❡t✐♥❣ t❤❡♥
✶✸
✇❛❝❛♦ ✿❂ ✬❡①❝❧✉í❞♦✬❀
✶✹
❡♥❞ ✐❢❀
✶✺
✲✲
✶✻
✐♥s❡rt ✐♥t♦ t❛❜❴❤✐st❴❞❡♣t ✭❞❡♣t♥♦✱ ❞t❴❤✐st♦r✐❝♦✱
❞s❴❤✐st♦r✐❝♦✮
✶✼
✈❛❧✉❡s ✭ ♥✈❧✭✿♥❡✇✳❞❡♣t♥♦✱✿♦❧❞✳❞❡♣t♥♦✮
✶✽
✱s②s❞❛t❡
✶✾
✱✬❖ ❞❡♣❛rt❛♠❡♥t♦ ✬⑤⑤
♥✈❧✭✿♥❡✇✳❞♥❛♠❡✱✿♦❧❞✳❞♥❛♠❡✮⑤⑤✬
309
Casa do Código
19.3. Trigger de linha
✷✵
✲✲
✷✶ ❡♥❞❀
✷✷ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
❢♦✐ ✬⑤⑤✇❛❝❛♦⑤⑤✬✳✬✮❀
O trigger em questão tem o objetivo de verificar qual a ação foi executada na tabela e a partir desta informação montar o histórico. Testando a
geração do histórico:
❙◗▲❃ ✉♣❞❛t❡ ❞❡♣t
✷ s❡t ❞♥❛♠❡ ❂ ❞♥❛♠❡❀
✹ ❧✐♥❤❛s ❛t✉❛❧✐③❛❞❛s✳
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✺✵✱✬❚■✬✱✬❇❘❆❙■▲✬✮❀
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃ ❞❡❧❡t❡ ❞❡♣t ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✺✵❀
✶ ❧✐♥❤❛ ❞❡❧❡t❛❞❛✳
❙◗▲❃
Agora executamos uma série de ações em cima da tabela dept, para termos diferentes tipos de histórico. Vamos verificar:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ t❛❜❴❤✐st❴❞❡♣t❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✷✵
✸✵
✹✵
✺✵
✺✵
310
❉❚❴❍■❙❚❖
✲✲✲✲✲✲✲✲
✵✾✴✵✾✴✶✶
✵✾✴✵✾✴✶✶
✵✾✴✵✾✴✶✶
✵✾✴✵✾✴✶✶
✵✾✴✵✾✴✶✶
✵✾✴✵✾✴✶✶
❉❙❴❍■❙❚❖❘■❈❖
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❖ ❞❡♣❛rt❛♠❡♥t♦ ❆❈❈❖❯◆❚■◆● ❢♦✐ ❛t✉❛❧✐③❛❞♦✳
❖ ❞❡♣❛rt❛♠❡♥t♦ ❘❊❙❊❆❘❈❍ ❢♦✐ ❛t✉❛❧✐③❛❞♦✳
❖ ❞❡♣❛rt❛♠❡♥t♦ ❙❆▲❊❙ ❢♦✐ ❛t✉❛❧✐③❛❞♦✳
❖ ❞❡♣❛rt❛♠❡♥t♦ ❖P❊❘❆❚■❖◆❙ ❢♦✐ ❛t✉❛❧✐③❛❞♦✳
❖ ❞❡♣❛rt❛♠❡♥t♦ ❚■ ❢♦✐ ✐♥s❡r✐❞♦✳
❖ ❞❡♣❛rt❛♠❡♥t♦ ❚■ ❢♦✐ ❡①❝❧✉í❞♦✳
Casa do Código
Capítulo 19. Triggers
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Através dos predicados é possível determinar qual ação disparou o
trigger e, com isso, fazer com que o programa tome decisões e caminhos diferentes. Devemos observar algumas restrições e características com relação
à criação e manipulação dos triggers que diferem de um bloco PL/SQL,
sendo este anônimo ou não. Dentro de um trigger não podemos utilizar
commit ou rollback, a menos que estejamos utilizando pragma. Seu uso
será discutido mais adiante. Fora esta exceção, não é permitida a utilização
destes comandos dentro do código dos triggers. Dessa forma, para validar
as alterações realizadas pelo trigger é necessária uma efetivação externa,
geralmente vindo do programa causador do disparo do seu disparo. Temos
as seguintes premissas:
• Não são permitidos comandos de ddl dentro de triggers;
• Não são permitidos comandos de controle da transação, como
rollback, commit, savepoint etc. (exceto com o uso de pragma).
Outro ponto que deve ser observado é com relação à criação de um
trigger. Quando o criamos, o Oracle faz validações igualmente a quando
criamos procedures, functions ou packages. Se este trigger apresentar algum erro de sintaxe, objetos não existentes, erros de referência ou
qualquer outro problema que impossibilite seu uso, o Oracle permite a criação, mas o deixa inválido no banco de dados.
Desta forma, o trigger não fica apto para o uso e não será disparado
mesmo que as ações satisfaçam suas definições. Neste caso, ele deve ser analisado, corrigido e recriado, novamente. Quando isso acontecer, não é necessário excluí-lo, basta recriá-lo. Basta usar o comando replace no momento
em que estiver recriando. Na sequência, mostro um exemplo:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣
✷
❛❢t❡r ✉♣❞❛t❡ ♦❢ ❥♦❜ ♦♥ ❡♠♣
✸
r❡❢❡r❡♥❝✐♥❣ ♦❧❞ ❛s ✈
311
19.3. Trigger de linha
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
Casa do Código
♥❡✇ ❛s ♥
❢♦r ❡❛❝❤ r♦✇
❜❡❣✐♥
✐♥s❡rt ✐♥t♦ t❛❜❴❤✐st❴❝❛r❣♦❴❡♠♣ ✭ ❡♠♣♥♦
✱❥♦❜❴❛♥t❡r✐♦r
✱❥♦❜❴❛t✉❛❧
✱❞t❴❛❧t❡r❛❝❛♦❴❝❛r❣♦
✱❞s❴❤✐st♦r✐❝♦✮
✈❛❧✉❡s ✭ ✿♥✳❡♠♣♥♦
✱✿✈✳❥♦❜
✱✿♥✳❥♦❜
✱s②s❞❛t❡
✱✬❖ ❡♠♣r❡❣❛❞♦ ✬⑤⑤✿♥✳❡♥❛♠❡⑤⑤
✬ ♣❛ss♦✉ ♣❛r❛ ♦ ❝❛r❣♦ ✬⑤⑤✿♥✳❥♦❜⑤⑤
✬ ❡♠ ❝❛r❛t❡r ❞❡ ♣r♦♠♦çã♦✳✬✮❀
❡♥❞❀
✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Caso seja necessário compilar um trigger pelo fato de ele estar inválido,
use o comando alter trigger. Todavia, não é comum, pois ao criá-lo ou
recriá-lo o Oracle já faz esta validação, a menos que ele tenha sido invalidado
via dependência de algum outro objeto.
❙◗▲❃ ❛❧t❡r tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣ ❝♦♠♣✐❧❡❀
●❛t✐❧❤♦ ❛❧t❡r❛❞♦✳
❙◗▲❃
Também podemos ativar ou desativar um trigger. Quando o desativamos, ele permanece criado no banco de dados, mas fica inativo. Desta forma,
ele não dispara caso a tabela de referência seja manipulada. Para ativar ou
desativar um trigger, também utilizamos o comando alter table.
312
Casa do Código
Capítulo 19. Triggers
❙◗▲❃ ❛❧t❡r tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣ ❞✐s❛❜❧❡ ✲✲ ❞❡s❛❜✐❧✐t❛ ♦
tr✐❣❣❡r
✷ ✴
●❛t✐❧❤♦ ❛❧t❡r❛❞♦✳
❙◗▲❃ ❛❧t❡r tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣ ❡♥❛❜❧❡ ✲✲ ❤❛❜✐❧✐t❛ ♦
tr✐❣❣❡r
✷ ✴
●❛t✐❧❤♦ ❛❧t❡r❛❞♦✳
❙◗▲❃
Também é possível habilitar ou desabilitar todos os triggers associados a uma tabela com um comando apenas.
❙◗▲❃ ❛❧t❡r t❛❜❧❡ ❡♠♣ ❞✐s❛❜❧❡ ❛❧❧ tr✐❣❣❡rs❀
❚❛❜❡❧❛ ❛❧t❡r❛❞❛✳
❙◗▲❃ ❛❧t❡r t❛❜❧❡ ❡♠♣ ❡♥❛❜❧❡ ❛❧❧ tr✐❣❣❡rs❀
❚❛❜❡❧❛ ❛❧t❡r❛❞❛✳
❙◗▲❃
Para eliminar um trigger, utilizamos o comando frop trigger.
Esse comando faz com que ele seja eliminado definitivamente.
❙◗▲❃ ❞r♦♣ tr✐❣❣❡r t✐❣❴❤✐st❴❝❛r❣♦❴❡♠♣❀
●❛t✐❧❤♦ ❡❧✐♠✐♥❛❞♦✳
❙◗▲❃
Para se criar um trigger, o usuário deve possuir os privilégios de criação: create trigger (ou create any trigger) e alter table.
Este último está relacionado à tabela base para o trigger. Quando o usuário tem privilégios para criação de tabelas, implicitamente, já terá o poder
313
19.3. Trigger de linha
Casa do Código
para alterá-las ou excluí-las. Veja um exemplo de concessão de privilégios
para triggers.
create any trigger permite que o usuário crie
triggers em qualquer esquema, exceto sys. Isso não é recomendado
Nota:
para a criação deles em tabelas de dicionário de dados.
❙◗▲❃ ❣r❛♥t ❝r❡❛t❡ tr✐❣❣❡r t♦ tsq❧❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃ ❣r❛♥t ❝r❡❛t❡ ❛♥② tr✐❣❣❡r t♦ tsq❧❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃
Para recuperar a definição e o código de um trigger, use as views
user_triggers, all_trigger ou dba_triggers.
❙◗▲❃ s❡❧❡❝t tr✐❣❣❡r❴❜♦❞②
✷ ❢r♦♠ ✉s❡r❴tr✐❣❣❡rs ✇❤❡r❡ tr✐❣❣❡r❴♥❛♠❡ ❂ ✬❚■●❴P❈❴❈❖▼❴❙❆▲❴❊▼P✬❀
❚❘■●●❊❘❴❇❖❉❨
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❜❡❣✐♥
✿♥✳♣❝❴❝♦♠❴s❛❧ ✿❂ ♥✈❧✭✿♥✳❝♦♠♠✱✵✮ ✯ ✶✵✵ ✴ ✿♥✳s❛❧❀
❡♥❞❀
❙◗▲❃
No geral, os triggers de banco de dados podem servir, por exemplo,
para controle, segurança e auditoria de informações de tabelas em um banco
de dados, para a realização de backups ou replicação de dados, objetivando
sempre a automação de algum processo.
314
Casa do Código
Capítulo 19. Triggers
Sequência de disparo de um trigger
Uma tabela não está limitada a apenas um trigger. Podemos ter vários associados a uma única tabela. Quando isso acontece, temos que nos
preocupar com alguns aspectos, por exemplo, se a ordem de execução de um
determinado trigger influencia em uma execução de um outro. Para isso,
é preciso entender a ordem de execução dos triggers, que depende do tipo
e do momento em que será disparado. Olhando o desenho a seguir, fica mais
clara a ordem de execução, dependendo do tipo e do momento em que são
disparados.
Imagine o seguinte cenário: temos dois triggers, um de tabela (chamado de tgrtab) e outro de linha (chamado de tgrlin). O trigger
de tabela dispara tanto no momento before quanto no momento after.
O trigger de linha segue a mesma lógica. Ambos são disparados na ação
update. Vamos ver como fica a ordem de disparo quando executamos um
update nos registros.
Fig. 19.1: Esquema mostrando a sequência de disparo das triggers de linha de
tabela
Note que o trigger tgrtab executa uma única vez antes na atualização de todos os registros e uma única vez no final quando todos os registros já
foram atualizados. Já o trigger tgrlin executa após a primeira execução
do trigger tgrtab e antes e depois da atualização de cada registro.
315
19.4. Mutante table
Casa do Código
Outro ponto a ser observado é que não há impedimento algum em termos
dois triggers exatamente iguais, que sejam do mesmo tipo e que disparem
no mesmo momento. Entretanto, para estes casos, não é possível determinar
qual a ordem em que cada um será executado. A Oracle não garante a ordem da execução quando há triggers contendo características de disparo
iguais. Caso sejam dependentes um do outro, o aconselhável é juntá-los, e
que tais dependências sejam tratadas no código.
19.4
Mutante table
Existe uma limitação no uso dos triggers de linha, quando selecionamos dados de uma tabela, no evento after, que seja a base do trigger, ou seja,
estamos tentando selecionar os dados de uma tabela que está sendo alterada
e ao mesmo tempo é a causadora do disparo. Contudo, quando temps este
cenário, mas o evento é o before, este problema não acontece.
Quando um trigger é disparado, isso indica que os dados de uma tabela estão sendo alterados. Neste momento podemos concluir que, enquanto
as alterações não forem confirmadas, os dados que estão sendo manipulados
na transação em questão não estão consistentes. Apenas quando forem confirmados, através de um rollback ou de um commit, os dados estarão
íntegros.
Seguindo esta lógica, no momento antes da efetivação dos dados alterados, não é possível executar a manipulação deles,por exemplo, através de um
comando select, mesmo se nossa intenção seja buscar apenas os registros
que não estão sofrendo tais alterações. Isso confirma a limitação no nível de
tabela e não no nível de dados. Quando tentamos realizar esta operação, um
erro chamado mutante table é gerado. Veja o resumo das regras a seguir:
• O erro de mutante table não acontece quando a trigger é de
linha e o momento de disparo for before, isso tanto para os comandos
delete, update, insert ou select. Já no evento after, o erro de
mutante table acontece para todos estes comandos (com exceção
do uso de transações autônomas);
• Para as triggers de tabela, não precisamos nos preocupar com o
erro de mutante table, pois independente de o evento ser before
316
Casa do Código
Capítulo 19. Triggers
ou after, e de qual seja o comando, select, delete, update ou
insert, esse tipo de problema não ocorre.
Agora veremos o exemplo na sequência:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❡♠♣❴♣r❛❣♠❛
✷
❛❢t❡r ✉♣❞❛t❡ ♦♥ ❡♠♣
✸
❢♦r ❡❛❝❤ r♦✇
✹ ❞❡❝❧❛r❡
✺
✇❝♦♥t❴r❡❣✐str♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✻ ❜❡❣✐♥
✼
✲✲
✽
s❡❧❡❝t ❝♦✉♥t✭✯✮ ✐♥t♦ ✇❝♦♥t❴r❡❣✐str♦ ❢r♦♠ ❡♠♣❀
✾
✲✲
✶✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛
❊▼P✿ ✬⑤⑤✇❝♦♥t❴r❡❣✐str♦✮❀
✶✶
✲✲
✶✷ ❡♥❞❀
✶✸ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Criamos um trigger do tipo linha, com o qual a cada atualização realizada nos registros da tabela emp é executado um select count para
verificar e mostrar a quantidade de registros desta mesma tabela. Agora vamos executar o comando a seguir:
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣
✷ s❡t s❛❧ ❂ s❛❧
✸ ✴
✉♣❞❛t❡ ❡♠♣
✯
❊❘❘❖ ♥❛ ❧✐♥❤❛ ✶✿
❖❘❆✲✵✹✵✾✶✿ ❛ t❛❜❡❧❛ ❚❙◗▲✳❊▼P é ♠✉t❛♥t❡❀ t❛❧✈❡③ ♦ ❣❛t✐❧❤♦✴❢✉♥çã♦
♥ã♦ ♣♦ss❛ ❧♦❝❛❧✐③á✲❧❛
❖❘❆✲✵✻✺✶✷✿ ❡♠ ✧❚❙◗▲✳❚■●❴❊▼P❴P❘❆●▼❆✧✱ ❧✐♥❡ ✺
❖❘❆✲✵✹✵✽✽✿ ❡rr♦ ❞✉r❛♥t❡ ❛ ❡①❡❝✉çã♦ ❞♦ ❣❛t✐❧❤♦
317
19.4. Mutante table
Casa do Código
✬❚❙◗▲✳❚■●❴❊▼P❴P❘❆●▼❆✬
❙◗▲❃
Como era previsto, o erro ocorreu após tentarmos realizar a alteração.
Agora vamos recriar o trigger como sendo um de tabela e executar a atualização novamente.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❡♠♣❴♣r❛❣♠❛
✷
❛❢t❡r ✉♣❞❛t❡ ♦♥ ❡♠♣
✸ ❞❡❝❧❛r❡
✹
✇❝♦♥t❴r❡❣✐str♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✺ ❜❡❣✐♥
✻
✲✲
✼
s❡❧❡❝t ❝♦✉♥t✭✯✮ ✐♥t♦ ✇❝♦♥t❴r❡❣✐str♦ ❢r♦♠ ❡♠♣❀
✽
✲✲
✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛
❊▼P✿ ✬⑤⑤✇❝♦♥t❴r❡❣✐str♦✮❀
✶✵
✲✲
✶✶ ❡♥❞❀
✶✷ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣
✷ s❡t s❛❧ ❂ s❛❧❀
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛ ❊▼P✿ ✶✹
Note que quando utilizamos um trigger do tipo tabela não temos este
problema. Mas aí vem a pergunta: e se tivermos esta necessidade e nos depararmos com este problema? O que fazer? Nestes casos, podemos utilizar o
recurso de transações autônomas, informando-o na declaração do trigger.
Sua função é fazer com que o Oracle abra uma nova sessão somente para atender o trigger, ou seja, neste momento existirão pelo menos duas transações
em aberto. Uma é referente à transação que está realizando as alterações na
318
Casa do Código
Capítulo 19. Triggers
tabela em questão, e outra referente ao disparo do trigger. Veja o desenho
a seguir onde tentamos ilustramos como o Oracle trata esta situação.
Fig. 19.2: Abrindo transações através de pragma autonomous_transaction
Contudo, conforme já explicado no capítulo anterior sobre transações
autônomas, temos que nos atentar para a seguinte situação. Sabemos que,
quando é aberta uma transação no Oracle, ela monta uma imagem dos objetos e dados disponíveis para o usuário em questão. Com relação aos dados,
isso permite visualizar somente aquilo que está efetivado no banco de dados,
ou seja, dados consistentes e íntegros. Isso quer dizer que dados pendentes
de efetivação não poderão ser visualizados, isso é, dados excluídos, inseridos
ou atualizados que ainda não tenham sido commitados.
Logo, quando isso acontece, no caso de um trigger, não conseguimos
visualizar as alterações que estão sendo realizadas, pelo menos não as que
fogem do escopo old e new. Portanto, quando temos um trigger com
transação autônoma, conseguimos manipular os dados de old e new, mas
319
19.4. Mutante table
Casa do Código
se realizarmos um comando select a fim de obter estes dados, não conseguiremos enxergá-los. Apenas para ressaltar, isto se dá ao fato de que dentro
do trigger estamos em outro escopo, em uma nova transação.
Outro ponto muito importante é que quando utilizamos trigger com
transação autônoma precisamos finalizá-la através de um commit ou de um
rollback. Como a autonomous_transaction faz com que uma nova
transação seja aberta, temos que finalizá-la. Caso contrário, ela ficaria pendente e isso poderia gerar um erro. Vamos verificar na prática:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❡♠♣❴♣r❛❣♠❛
✷
❜❡❢♦r❡ ✉♣❞❛t❡ ♦♥ ❡♠♣
✸
❢♦r ❡❛❝❤ r♦✇
✹ ❞❡❝❧❛r❡
✺
✲✲
✻
♣r❛❣♠❛ ❛✉t♦♥♦♠♦✉s❴tr❛♥s❛❝t✐♦♥❀
✼
✲✲
✽
✇❝♦♥t❴r❡❣✐str♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✾ ❜❡❣✐♥
✶✵
✲✲
✶✶
s❡❧❡❝t ❝♦✉♥t✭✯✮ ✐♥t♦ ✇❝♦♥t❴r❡❣✐str♦ ❢r♦♠ ❡♠♣❀
✶✷
✲✲
✶✸
✐❢ ♥✈❧✭✿♦❧❞✳❝♦♠♠✱✵✮ ❁ ✸✵✵ t❤❡♥
✶✹
✿♥❡✇✳❝♦♠♠ ✿❂ ✿♥❡✇✳s❛❧ ✯ ✶✵ ✴ ✶✵✵❀
✶✺
❡♥❞ ✐❢❀
✶✻
✲✲
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛
❊▼P✿ ✬⑤⑤✇❝♦♥t❴r❡❣✐str♦✮❀
✶✽
✲✲
✶✾
❝♦♠♠✐t❀
✷✵
✲✲
✷✶ ❡♥❞❀
✷✷ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Uma observação: para este exemplo alteramos o trigger de
after para before para que pudéssemos alterar o valor de new.
320
Casa do Código
Capítulo 19. Triggers
Note que na área de declaração colocamos a seguinte linha: pragma
autonomous_transaction;. Isso faz com que uma nova transação seja
aberta para a execução do trigger. Agora vamos executar uma alteração
na tabela emp e veremos como ele se comporta.
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣
✷ s❡t s❛❧ ❂ s❛❧
✸ ✴
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
♥❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
t❛❜❡❧❛
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
❊▼P✿
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹
✶✹ ❧✐♥❤❛s ❛t✉❛❧✐③❛❞❛s✳
❙◗▲❃
A execução não nos gerou erro. Vamos verificar a tabela emp. Antes da
execução da atualização e disparo do trigger os dados estavam assim:
❙◗▲❃ s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ s❛❧✱ ❝♦♠♠ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
❊◆❆▼❊
❙❆▲
❈❖▼▼
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
✾✻✽
❆▲▲❊◆
✶✻✵✵
✸✵✻
❲❆❘❉
✶✷✺✵
✺✶✵
❏❖◆❊❙
✸✺✾✾✱✼✺
▼❆❘❚■◆
✶✷✺✵
✶✹✷✽
321
Casa do Código
19.4. Mutante table
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
✷✽✺✵
✷✹✺✵
✸✻✸✵
✺✵✵✵
✶✺✵✵
✶✸✸✶
✾✺✵
✸✻✸✵
✶✸✵✵
✵
✶✹ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Após a execução da atualização e disparo do trigger os dados ficaram
assim:
❙◗▲❃ s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡✱ s❛❧✱ ❝♦♠♠ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
❊◆❆▼❊
❙❆▲
❈❖▼▼
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
✾✻✽
✾✻✱✽
❆▲▲❊◆
✶✻✵✵
✸✵✻
❲❆❘❉
✶✷✺✵
✺✶✵
❏❖◆❊❙
✸✺✾✾✱✼✺
✸✺✾✱✾✽
▼❆❘❚■◆
✶✷✺✵
✶✹✷✽
❇▲❆❑❊
✷✽✺✵
✷✽✺
❈▲❆❘❑
✷✹✺✵
✷✹✺
❙❈❖❚❚
✸✻✸✵
✸✻✸
❑■◆●
✺✵✵✵
✺✵✵
❚❯❘◆❊❘
✶✺✵✵
✶✺✵
❆❉❆▼❙
✶✸✸✶
✶✸✸✱✶
❏❆▼❊❙
✾✺✵
✾✺
❋❖❘❉
✸✻✸✵
✸✻✸
▼■▲▲❊❘
✶✸✵✵
✶✸✵
✶✹ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
322
Casa do Código
Capítulo 19. Triggers
Agora vamos cadastrar um novo empregado através de um insert para
vermos bem o controle de transação sendo consistido. Para isso, alteramos
novamente nosso trigger, incluindo nas condições de disparo o comando
insert.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t✐❣❴❡♠♣❴♣r❛❣♠❛
✷
❜❡❢♦r❡ ✉♣❞❛t❡ ♦r ✐♥s❡rt ♦♥ ❡♠♣
✸
❢♦r ❡❛❝❤ r♦✇
✹ ❞❡❝❧❛r❡
✺
✲✲
✻
♣r❛❣♠❛ ❛✉t♦♥♦♠♦✉s❴tr❛♥s❛❝t✐♦♥❀
✼
✲✲
✽
✇❝♦♥t❴r❡❣✐str♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
✾ ❜❡❣✐♥
✶✵
✲✲
✶✶
s❡❧❡❝t ❝♦✉♥t✭✯✮ ✐♥t♦ ✇❝♦♥t❴r❡❣✐str♦ ❢r♦♠ ❡♠♣❀
✶✷
✲✲
✶✸
✐❢ ♥✈❧✭✿♦❧❞✳❝♦♠♠✱✵✮ ❁ ✸✵✵ t❤❡♥
✶✹
✿♥❡✇✳❝♦♠♠ ✿❂ ✿♥❡✇✳s❛❧ ✯ ✶✵ ✴ ✶✵✵❀
✶✺
❡♥❞ ✐❢❀
✶✻
✲✲
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛
❊▼P✿ ✬⑤⑤✇❝♦♥t❴r❡❣✐str♦✮❀
✶✽
✲✲
✶✾
❝♦♠♠✐t❀
✷✵
✲✲
✷✶ ❡♥❞❀
✷✷ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Executando o insert.
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣
✷
✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ ♠❣r✱ ❤✐r❡❞❛t❡✱ s❛❧✱ ❝♦♠♠✱ ❞❡♣t♥♦✱
♣❝❴❝♦♠❴s❛❧✮
✸
✈❛❧✉❡s
323
19.5. Trigger de sistema
Casa do Código
✹
✭✼✾✸✺✱ ✬P❆❯▲✬✱ ✬❙❆▲❊❙▼❆◆✬✱ ✼✻✾✽✱ t♦❴❞❛t❡✭✬✶✺✲▼❆❘✲✶✾✽✵✬✱
✬❞❞✲♠♦♥✲rrrr✬✮✱
✶✵✵✵✱ ✶✵✵✱ ✸✵✱ ♥✉❧❧✮❀
◗✉❛♥t✐❞❛❞❡ ❞❡ r❡❣✐str♦s ♥❛ t❛❜❡❧❛ ❊▼P✿ ✶✹
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
Note que a mensagem vinda do trigger nos informou que temos 14
registros, ou seja, ele não está contando com este que acabamos de inserir,
que seria o registro 15. Mesmo que alteremos o triiger para que dispare
no momento after, ele não vai enxergar o novo registro, pois o insert está
acontecendo numa transação e a contagem do registro, feita pelo trigger,
acontece em outra.
Se mesmo com o uso de transações autônomas não for possível resolver
problemas de mutante table, talvez mesclar o uso de triggers de linha
com os de tabela possa ser uma saída.
Considerações sobre triggers
• Um trigger tanto de linha quanto de tabela pode agir de forma recursiva. O Oracle garante até 50 níveis de recursividade para estes dois
tipos de objeto;
• Um trigger não pode contemplar eventos diferentes de execução (
before ou after) em um mesmo objeto. Devem ser criados dois
triggers distintos;
• Ao excluir uma tabela, triggers associadas a ela também são excluídos automaticamente.
19.5
Trigger de sistema
Trigger de sistema são objetos criados em nível de sistema e não de tabelas.
Quando falamos em sistemas nos referimos ao banco de dados, mais preci324
Casa do Código
Capítulo 19. Triggers
samente a ações que ocorrem nele. Seu uso é mais comum pelos DBAs (administradores de banco de dados) e é uma ferramenta poderosa quando utilizada com criatividade.
Os triggers de sistema disparam conforme um evento que acontece no
banco de dados. Veja a seguir a lista de alguns eventos:
• startup: quando o banco de dados é aberto;
• shutdown:
antes de o banco de dados iniciar o
shutdown(fechamento). Se for shutdown abort este evento
não é disparado;
• servererror: quando um erro ocorre. Com exceção dos erros: ORA1034, ORA-1403, ORA-1422, ORA-1423 e ORA-4030;
• after logon: depois de uma conexão ser completada no banco de
dados;
• before logoff: quando o usuário desconecta do banco de dados;
• before create / after create: quando um objeto é criado no
banco de dados (comando create), exceto o comando create
database;
• before alter / after alter: quando um objeto é alterado no
banco de dados (comando alter), com exceção do comando alter
database;
• before drop / after drop: quando um objeto é eliminado do
banco de dados (comando drop);
• before analyze / after analyze: quando o comando analyze
é executado. Este comando é utilizado para gerar estatísticas relacionadas ao desempenho de comandos SQL e processos do banco de dados;
• before commit / after commit: quando um commit é executado;
325
19.5. Trigger de sistema
Casa do Código
• before ddl / after ddl: quando um comando ddl é executado, com exceção dos comandos alter database, create
controlfile, create database e ddl executados a partir de interface PL/SQL;
• before grant / after grant: quando o comando grant é executado;
• before rename / after rename: quando o rename é executado;
• before revoke / after revoke: quando o comando revoke é
executado;
• before truncate / after truncate: quando o truncate é
executado.
Além de contar com os eventos para determinar quando o trigger de sistema deve disparar, também temos a disposição os atributos de evento que
nos dão informações sobre o banco de dados, transações e sobre as operações
que disparam o trigger. Veja a lista a seguir.
• ora_client_ip_address (tipo: varchar2): retorna o IP da máquina cliente no evento de LOGON, se o protocolo for TCP/IP;
• ora_database_name (tipo: varchar2(50)): nome do banco de
dados;
• ora_dict_obj_name (tipo: varchar(30)): nome do objeto que
sofreu o evento ddl;
• ora_dict_obj_name_list(name_list out
ora_name_list_t) (tipo:
binary_integer): retorna lista
de objetos afetados no evento;
• ora_dict_obj_ownerR (tipo: varchar(30)): proprietário (usuário/schema) do objeto que sofreu o evento ddl;
• ora_dict_obj_owner_list(OWNER_LIST OUT
ora_name_list_t) (tipo:
binary_integer): retorna lista
de proprietários (usuário/schemas) dos objetos afetados no evento;
326
Casa do Código
Capítulo 19. Triggers
• ora_dict_obj_type (tipo: varchar(20)): tipo de objeto que sofreu o evento ddl;
• ora_grantee(user_list out ora_name_list_t)
(tipo:
binary_integer): retorna lista de usuários ou roles que receberam
grant;
• ora_is_alter_column(column_name in varchar2)
(tipo:
boolean): retorna true se a coluna especificada foi alterada;
• ora_is_drop_column(column_name in varchar2)
(tipo:
boolean): retorna true se a coluna especificada foi eliminada;
• ora_login_user (tipo: varchar2(30)): nome do usuário que acabou de conectar em uma sessão do banco de dados;
• ora_privileges(privilege_list out ora_name_list_t)
(tipo: binary_integer): retorna lista de privilégios dados ou
revogados;
• ora_revokee(user_list out ora_name_list_t)
(tipo:
binary_integer): retorna lista dos que perderam privilégios;
• ora_sysevent (tipo: varchar2(20)): retorna o nome do evento
que foi disparado. O nome é o mesmo usado na definição do trigger;
• ora_with_grant_option (tipo: boolean): retorna true se o
grant tem with grant option.
Na sequência, alguns exemplos:
❙◗▲❃
✷
✸
✹
✺
✻
✼
❝r❡❛t❡ t❛❜❧❡ ❤✐st❴✉s✉❛r✐♦
✭
♥♠❴✉s✉❛r✐♦
✈❛r❝❤❛r✷✭✺✵✮
✱❞t❴❤✐st♦r✐❝♦ ❞❛t❡
✱❞s❴❤✐st♦r✐❝♦ ✈❛r❝❤❛r✷✭✹✵✵✵✮
✮
✴
327
19.5. Trigger de sistema
Casa do Código
❚❛❜❡❧❛ ❝r✐❛❞❛✳
❙◗▲❃
Criamos uma tabela para guardar os históricos gerados pelos triggers.
No exemplo a seguir, temos um que registra quando o usuário conecta no
banco de dados.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t❣r❴❤✐st❴❝♦♥❡①❛♦❴✉s✉❛r✐♦
✷
❛❢t❡r ❧♦❣♦♥ ♦♥ ❞❛t❛❜❛s❡
✸ ❜❡❣✐♥
✹
✐♥s❡rt ✐♥t♦ ❤✐st❴✉s✉❛r✐♦ ✈❛❧✉❡s
✺
✭❖❘❆❴▲❖●■◆❴❯❙❊❘✱s②s❞❛t❡✱✬❈♦♥❡①ã♦ ❝♦♠ ♦ ❜❛♥❝♦ ❞❡ ❞❛❞♦s
✬⑤⑤❖❘❆❴❉❆❚❆❇❆❙❊❴◆❆▼❊✮❀
✻ ❡♥❞❀
✼ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Conectando ao banco de dados:
❙◗▲❃ ❞✐s❝♦♥♥❡❝t
❉❡s❝♦♥❡❝t❛❞♦ ❞❡ ❖r❛❝❧❡ ❉❛t❛❜❛s❡ ✶✵❣ ❊①♣r❡ss ❊❞✐t✐♦♥ ❘❡❧❡❛s❡
✶✵✳✷✳✵✳✶✳✵ ✲ Pr♦❞✉❝t✐♦♥
❙◗▲❃
❙◗▲❃ ❝♦♥♥ tsq❧✴tsq❧❅①❡❀
❈♦♥❡❝t❛❞♦✳
❙◗▲❃
❙◗▲❃
Nota: Como já estávamos conectados ao banco de dados, primeiramente, desconectamos e refizemos a conexão logo após.
Verificando histórico:
328
Casa do Código
Capítulo 19. Triggers
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❤✐st❴✉s✉❛r✐♦❀
◆▼❴❯❙❯❆❘■❖
❉❚❴❍■❙❚❖ ❉❙❴❍■❙❚❖❘■❈❖
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❚❙◗▲
✵✹✴✶✵✴✶✶ ❈♦♥❡①ã♦ ❝♦♠ ♦ ❜❛♥❝♦ ❞❡ ❞❛❞♦s ❳❊
❙◗▲❃
Como pode ser visto, o trigger gravou o histórico com as informações
pertinentes ao usuário que conectou no banco de dados.
O próximo registra alterações de dml realizados pelo usuário, mais precisamente a criação de objetos no sistema.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r t❣r❴❤✐st❴❝r✐❛t❛❜❴✉s✉❛r✐♦
✷
❛❢t❡r ❝r❡❛t❡ ♦♥ ❞❛t❛❜❛s❡
✸ ❜❡❣✐♥
✹
✐♥s❡rt ✐♥t♦ ❤✐st❴✉s✉❛r✐♦ ✈❛❧✉❡s
✺
✭❖❘❆❴▲❖●■◆❴❯❙❊❘✱s②s❞❛t❡✱
✬❖ ❖❜❥❡t♦ ✬⑤⑤❖❘❆❴❉■❈❚❴❖❇❏❴◆❆▼❊⑤⑤✬ ❢♦✐ ❝r✐❛❞♦
♥♦ ❜❛♥❝♦ ❞❡ ❞❛❞♦s✳✬✮❀
✻ ❡♥❞❀
✼ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Criando o objeto tabela teste_trigger:
❙◗▲❃
✷
✸
✹
✺
✻
✼
❝r❡❛t❡ t❛❜❧❡ t❡st❡❴tr✐❣❣❡r
✭
✐❞❴❝❛♠♣♦ ✈❛r❝❤❛r✷✭✺✵✮
✱♥♠❴❝❛♠♣♦ ❞❛t❡
✱❞s❴❝❛♠♣♦
✈❛r❝❤❛r✷✭✹✵✵✵✮
✮
✴
❚❛❜❡❧❛ ❝r✐❛❞❛✳
❙◗▲❃
329
19.6. Trigger de view
Casa do Código
Verificando tabela de histórico:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❤✐st❴✉s✉❛r✐♦❀
◆▼❴❯❙❯❆❘■❖
❉❚❴❍■❙❚❖ ❉❙❴❍■❙❚❖❘■❈❖
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❚❙◗▲
✵✹✴✶✵✴✶✶ ❖ ♦❜❥❡t♦ ❚❊❙❚❊❴❚❘■●●❊❘ ❢♦✐ ❝r✐❛❞♦ ♥♦
❜❛♥❝♦ ❞❡ ❞❛❞♦s✳
❙◗▲❃
19.6 Trigger de view
Aprendemos anteriormente que um trigger pode estar associado a uma
tabela ou ao avento de sistema. Contudo, quando estamos falando de views,
que são bem semelhantes a tabelas, pelo menos na forma de apresentação
dos dados, existe a possibilidade de criarmos um trigger e o associarmos
também a este tipo de objeto.
Em regras gerais, só conseguimos criar um trigger para uma determinada view que seja composta de apenas uma tabela. No entanto, se criarmos um trigger usando a cláusula instead of, podemos trabalhar
com triggers associadas a views compostas de uma ou mais tabelas. O
trigger usado com instead of tem sua definição um pouco diferente,
pois esta cláusula substitui os eventos before e after. Outro ponto que
deve ser observado é que o uso desta cláusula só pode ser empregado com
triggers de linha.
A questão de poder ou não criar um trigger para uma view está relacionada às operações que podemos efetuar em cima desta view. Esquecendo um
pouco os triggers, sabemos que operações de DML ( insert, delete
ou update) só podem ocorrer quando a view for de apenas uma tabela. Portanto, a utilização de triggers em views segue os mesmos princípios. A
única diferença é que quando utilizamos triggers para realizar comando
DML em views podemos utilizá-los com a opção instead of, o que torna
possível tratar de forma diferente as views que possuam mais de uma tabela
na sua composição.
330
Casa do Código
Capítulo 19. Triggers
A seguir, um exemplo de uma view composta pelas tabelas emp e dept
onde nós vamos inserir dados. Criando view de empregados por departamento:
❙◗▲❃
✷
✸
✹
✺
✻
❝r❡❛t❡ ✈✐❡✇ ❡♠♣❴❞❡♣t❴✈ ❛s
s❡❧❡❝t ❡✳❡♠♣♥♦✱ ❡✳❡♥❛♠❡✱ ❡✳❥♦❜✱ ❡✳s❛❧✱ ❞✳❞♥❛♠❡
❢r♦♠ ❡♠♣ ❡
✱❞❡♣t ❞
✇❤❡r❡ ❡✳❞❡♣t♥♦ ❂ ❞✳❞❡♣t♥♦
❀
❱✐❡✇ ❝r✐❛❞❛✳
❙◗▲❃
Selecionando dados:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✼✾✸✺
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
P❆❯▲
❏❖❇
❙❆▲ ❉◆❆▼❊
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽ ❘❊❙❊❆❘❈❍
❙❆▲❊❙▼❆◆
✶✻✵✵ ❙❆▲❊❙
❙❆▲❊❙▼❆◆
✶✷✺✵ ❙❆▲❊❙
▼❆◆❆●❊❘
✸✺✾✾✱✼✺ ❘❊❙❊❆❘❈❍
❙❆▲❊❙▼❆◆
✶✷✺✵ ❙❆▲❊❙
▼❆◆❆●❊❘
✷✽✺✵ ❙❆▲❊❙
▼❆◆❆●❊❘
✷✹✺✵ ❆❈❈❖❯◆❚■◆●
❆◆❆▲❨❙❚
✸✻✸✵ ❘❊❙❊❆❘❈❍
P❘❊❙■❉❊◆❚
✺✵✵✵ ❆❈❈❖❯◆❚■◆●
❙❆▲❊❙▼❆◆
✶✺✵✵ ❙❆▲❊❙
❈▲❊❘❑
✶✸✸✶ ❘❊❙❊❆❘❈❍
❈▲❊❘❑
✾✺✵ ❙❆▲❊❙
❆◆❆▲❨❙❚
✸✻✸✵ ❘❊❙❊❆❘❈❍
❈▲❊❘❑
✶✸✵✵ ❆❈❈❖❯◆❚■◆●
❙❆▲❊❙▼❆◆
✶✵✵✵ ❙❆▲❊❙
✶✺ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
331
19.6. Trigger de view
Casa do Código
Criando trigger com instead of para manipulação dos dados:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
332
❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r tr❣❴❡♠♣❴❞❡♣t❴✈
✐♥st❡❛❞ ♦❢
✐♥s❡rt ♦r ❞❡❧❡t❡ ♦r ✉♣❞❛t❡
♦♥ ❡♠♣❴❞❡♣t❴✈
r❡❢❡r❡♥❝✐♥❣ ♥❡✇ ❛s ♥❡✇ ♦❧❞ ❛s ♦❧❞
❞❡❝❧❛r❡
❝✉rs♦r ❝✶✭♣❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡✮ ✐s
s❡❧❡❝t ❞❡♣t♥♦✱ ❞♥❛♠❡
❢r♦♠ ❞❡♣t
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦❀
✲✲
❝✉rs♦r ❝✷✭♣❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡✮ ✐s
s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡
❢r♦♠ ❡♠♣
✇❤❡r❡ ❡♠♣♥♦ ❂ ♣❡♠♣♥♦❀
✲✲
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡❀
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✇❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
❜❡❣✐♥
✲✲
✐❢ ✐♥s❡rt✐♥❣ t❤❡♥
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✶ ✭✿♥❡✇✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✲✲
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❞❡♣t ✭❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❧♦❝✮
✈❛❧✉❡s ✭✿♥❡✇✳❞❡♣t♥♦✱ ✿♥❡✇✳❞♥❛♠❡✱ ♥✉❧❧✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿ ✬⑤⑤✇❞❡♣t♥♦⑤⑤✬ ✲
Casa do Código
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
✺✷
✺✸
Capítulo 19. Triggers
✬⑤⑤✇❞♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
♦♣❡♥ ❝✷ ✭✿♥❡✇✳❡♠♣♥♦✮❀
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✮
✈❛❧✉❡s ✭✿♥❡✇✳❡♠♣♥♦✱ ✿♥❡✇✳❡♥❛♠❡✱ ✿♥❡✇✳❥♦❜✱ ✿♥❡✇✳s❛❧✱
✿♥❡✇✳♠❣r✱ ✿♥❡✇✳❞❡♣t♥♦✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❋✉♥❝✐♦♥ár✐♦ ❡①✐st❡♥t❡✿ ✬⑤⑤✇❡♠♣♥♦⑤⑤✬ ✲
✬⑤⑤✇❡♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
❙◗▲❃
Na primeira parte da criação do trigger vamos tratar a ação de insert
na view emp_dept_v. A seguir temos várias execuções onde testamos, primeiramente, o comando insert.
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣❴❞❡♣t❴✈ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱
❞❡♣t♥♦✱ ❞♥❛♠❡✮
✷
✈❛❧✉❡s ✭✽✵✵✵✱ ✬❇❘❯❈❊✬✱ ✬▼❆◆❆●❊❘✬✱ ✶✵✵✵✱
✼✽✸✾✱ ✷✵✱ ✬❘❊❙❊❆❘❈❍✬✮❀
❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿ ✷✵ ✲ ❘❊❙❊❆❘❈❍✳
❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳
333
19.6. Trigger de view
Casa do Código
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣❴❞❡♣t❴✈ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✱
❞♥❛♠❡✮
✷
✈❛❧✉❡s ✭✽✵✵✵✱ ✬❇❘❯❈❊✬✱ ✬▼❆◆❆●❊❘✬✱ ✶✵✵✵✱
✼✽✸✾✱ ✷✵✱ ✬❘❊❙❊❆❘❈❍✬✮❀
❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿ ✷✵ ✲ ❘❊❙❊❆❘❈❍✳
❋✉♥❝✐♦♥ár✐♦ ❡①✐st❡♥t❡✿ ✽✵✵✵ ✲ ❇❘❯❈❊✳
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣❴❞❡♣t❴✈ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✱
❞♥❛♠❡✮
✷
✈❛❧✉❡s ✭✽✵✵✶✱ ✬❙■▲❱❊❙❚❊❘✬✱ ✬▼❆◆❆●❊❘✬✱ ✶✵✵✵✱
✼✽✸✾✱ ✽✵✱ ✬❙✫❊✬✮❀
❉❡♣❛rt❛♠❡♥t♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳
❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣❴❞❡♣t❴✈ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✱
❞♥❛♠❡✮
✷
✈❛❧✉❡s ✭✽✵✵✶✱ ✬❙■▲❱❊❙❚❊❘✬✱ ✬▼❆◆❆●❊❘✬✱ ✶✵✵✵✱
✼✽✸✾✱ ✾✵✱ ✬❋■◆❆◆❈■❆▲✬✮❀
❉❡♣❛rt❛♠❡♥t♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳
❋✉♥❝✐♦♥ár✐♦ ❡①✐st❡♥t❡✿ ✽✵✵✶ ✲ ❙■▲❱❊❙❚❊❘✳
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
❙◗▲❃ ✐♥s❡rt ✐♥t♦ ❡♠♣❴❞❡♣t❴✈ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✱
❞♥❛♠❡✮
✷
✈❛❧✉❡s ✭✽✵✵✷✱ ✬❲■▲▲✬✱ ✬▼❆◆❆●❊❘✬✱ ✶✵✵✵✱ ✼✽✸✾✱
✾✵✱ ✬❋■◆❆◆❈■❆▲✬✮❀
334
Casa do Código
Capítulo 19. Triggers
❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿ ✾✵ ✲ ❋■◆❆◆❈■❆▲✳
❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳
✶ ❧✐♥❤❛ ❝r✐❛❞❛✳
❙◗▲❃
Agora vamos para a segunda parte do trigger, onde vamos tratar a
ação update. Criação do trigger:
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r tr❣❴❡♠♣❴❞❡♣t❴✈
✷
✐♥st❡❛❞ ♦❢
✸
✐♥s❡rt ♦r ❞❡❧❡t❡ ♦r ✉♣❞❛t❡
✹
♦♥ ❡♠♣❴❞❡♣t❴✈
✺
r❡❢❡r❡♥❝✐♥❣ ♥❡✇ ❛s ♥❡✇ ♦❧❞ ❛s ♦❧❞
✻ ❞❡❝❧❛r❡
✼
❝✉rs♦r ❝✶✭♣❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡✮ ✐s
✽
s❡❧❡❝t ❞❡♣t♥♦✱ ❞♥❛♠❡
✾
❢r♦♠ ❞❡♣t
✶✵
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦❀
✶✶
✲✲
✶✷
❝✉rs♦r ❝✷✭♣❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡✮ ✐s
✶✸
s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡
✶✹
❢r♦♠ ❡♠♣
✶✺
✇❤❡r❡ ❡♠♣♥♦ ❂ ♣❡♠♣♥♦❀
✶✻
✲✲
✶✼
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡❀
✶✽
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✶✾
✇❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✷✵
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✷✶ ❜❡❣✐♥
✷✷
✲✲
✷✸
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✷✹
✐❢ ✐♥s❡rt✐♥❣ t❤❡♥
✷✺
✲✲
✷✻
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
✷✼
♦♣❡♥ ❝✶ ✭✿♥❡✇✳❞❡♣t♥♦✮❀
✷✽
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✷✾
✲✲
335
19.6. Trigger de view
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
✺✷
✺✸
✺✹
✺✺
✺✻
✺✼
✺✽
✺✾
✻✵
✻✶
✻✷
336
Casa do Código
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❞❡♣t ✭❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❧♦❝✮
✈❛❧✉❡s ✭✿♥❡✇✳❞❡♣t♥♦✱ ✿♥❡✇✳❞♥❛♠❡✱ ♥✉❧❧✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ❝❛❞❛str❛❞♦ ❝♦♠
s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿
✬⑤⑤✇❞❡♣t♥♦⑤⑤✬ ✲ ✬⑤⑤✇❞♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
♦♣❡♥ ❝✷ ✭✿♥❡✇✳❡♠♣♥♦✮❀
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✮
✈❛❧✉❡s ✭✿♥❡✇✳❡♠♣♥♦✱ ✿♥❡✇✳❡♥❛♠❡✱ ✿♥❡✇✳❥♦❜✱
✿♥❡✇✳s❛❧✱✿♥❡✇✳♠❣r✱ ✿♥❡✇✳❞❡♣t♥♦✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠
s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ❡①✐st❡♥t❡✿
✬⑤⑤✇❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤✇❡♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❡❧s✐❢ ✉♣❞❛t✐♥❣ t❤❡♥
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✶ ✭✿♥❡✇✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✲✲
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ♥ã♦ ❡①✐st❡✳✬✮❀
✲✲
❡❧s❡
Casa do Código
✻✸
✻✹
✻✺
✻✻
✻✼
✻✽
✻✾
✼✵
✼✶
✼✷
✼✸
✼✹
✼✺
✼✻
✼✼
✼✽
✼✾
✽✵
✽✶
✽✷
✽✸
✽✹
✽✺
✽✻
✽✼
✽✽
✽✾
✾✵
✾✶
✾✷
✾✸
✾✹
✾✺
✾✻
Capítulo 19. Triggers
✲✲
✉♣❞❛t❡ ❞❡♣t
s❡t
❞♥❛♠❡ ❂ ✿♥❡✇✳❞♥❛♠❡
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿♥❡✇✳❞❡♣t♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♥❡✇✳❞♥❛♠❡⑤⑤✬✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
♦♣❡♥ ❝✷ ✭✿♥❡✇✳❡♠♣♥♦✮❀
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ♥ã♦ ❝❛❞❛str❛❞♦✳✬✮❀
✲✲
❡❧s❡
✉♣❞❛t❡ ❡♠♣
s❡t
❡♥❛♠❡ ❂ ✿♥❡✇✳❡♥❛♠❡
✱❥♦❜
❂ ✿♥❡✇✳❥♦❜
✱s❛❧
❂ ✿♥❡✇✳s❛❧
✱♠❣r
❂ ✿♥❡✇✳♠❣r
✱❞❡♣t♥♦ ❂ ✿♥❡✇✳❞❡♣t♥♦
✇❤❡r❡ ❡♠♣♥♦ ❂ ✿♥❡✇✳❡♠♣♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♥❡✇✳❡♥❛♠❡⑤⑤✬✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞ ✐❢❀
✲✲
❡♥❞❀
✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
337
19.6. Trigger de view
Casa do Código
❙◗▲❃
Testando o trigger:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✽✵✵✵❀
❊▼P◆❖ ❊◆❆▼❊
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✽✵✵✵ ❇❘❯❈❊
▼❆◆❆●❊❘
✶✵✵✵
✼✽✸✾
❉❊P❚◆❖ ❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✷✵ ❘❊❙❊❆❘❈❍
❙◗▲❃
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣❴❞❡♣t❴✈
✷
s❡t
❡♥❛♠❡ ❂ ✬❇❘❯❈❊❲✬
✸
✱❥♦❜
❂ ✬❆◆❆▲❨❙❚✬
✹
✱s❛❧
❂ ✶✺✵✵
✱❞❡♣t♥♦ ❂ ✷✵
✺
✻
✱❞♥❛♠❡ ❂ ✬❘❊❙❊❆❘❈❍✬
✼
✇❤❡r❡ ❡♠♣♥♦ ❂ ✽✵✵✵❀
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❘❊❙❊❆❘❈❍✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❇❘❯❈❊❲✳
✶ ❧✐♥❤❛ ❛t✉❛❧✐③❛❞❛✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✽✵✵✵❀
❊▼P◆❖ ❊◆❆▼❊
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✽✵✵✵ ❇❘❯❈❊❲
❆◆❆▲❨❙❚
✶✺✵✵
✼✽✸✾
❉❊P❚◆❖ ❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✷✵ ❘❊❙❊❆❘❈❍
❙◗▲❃
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
338
Casa do Código
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✺✻✻
✼✼✽✽
✼✽✼✻
✼✾✵✷
✽✵✵✵
Capítulo 19. Triggers
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❇❘❯❈❊❲
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
✼✾✵✷
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
✼✽✸✾
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❈▲❊❘❑
✶✸✸✶
✼✼✽✽
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❆◆❆▲❨❙❚
✶✺✵✵
✼✽✸✾
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✷✵
✷✵
✷✵
✷✵
✷✵
✷✵
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲
❘❊❙❊❆❘❈❍
❘❊❙❊❆❘❈❍
❘❊❙❊❆❘❈❍
❘❊❙❊❆❘❈❍
❘❊❙❊❆❘❈❍
❘❊❙❊❆❘❈❍
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
❙◗▲❃ ✉♣❞❛t❡ ❡♠♣❴❞❡♣t❴✈
✷ s❡t
❞♥❛♠❡ ❂ ✬P❊❙◗❯■❙❆✬
✸ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❙▼■❚❍✳
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❏❖◆❊❙✳
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❙❈❖❚❚✳
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❆❉❆▼❙✳
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❋❖❘❉✳
❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠ s✉❝❡ss♦✿ ❇❘❯❈❊❲✳
339
Casa do Código
19.6. Trigger de view
✻ ❧✐♥❤❛s ❛t✉❛❧✐③❛❞❛s✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✺✻✻
✼✼✽✽
✼✽✼✻
✼✾✵✷
✽✵✵✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❏❖◆❊❙
❙❈❖❚❚
❆❉❆▼❙
❋❖❘❉
❇❘❯❈❊❲
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
✼✾✵✷
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
✼✽✸✾
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❈▲❊❘❑
✶✸✸✶
✼✼✽✽
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❆◆❆▲❨❙❚
✶✺✵✵
✼✽✸✾
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✷✵
✷✵
✷✵
✷✵
✷✵
✷✵
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲
P❊❙◗❯■❙❆
P❊❙◗❯■❙❆
P❊❙◗❯■❙❆
P❊❙◗❯■❙❆
P❊❙◗❯■❙❆
P❊❙◗❯■❙❆
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
A exclusão finaliza a última parte do nosso trigger de view.
❙◗▲❃ ❡❞
●r❛✈♦✉ ❛rq✉✐✈♦ ❛❢✐❡❞t✳❜✉❢
✶ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ tr✐❣❣❡r tr❣❴❡♠♣❴❞❡♣t❴✈
✷
✐♥st❡❛❞ ♦❢
✸
✐♥s❡rt ♦r ❞❡❧❡t❡ ♦r ✉♣❞❛t❡
✹
♦♥ ❡♠♣❴❞❡♣t❴✈
✺
r❡❢❡r❡♥❝✐♥❣ ♥❡✇ ❛s ♥❡✇ ♦❧❞ ❛s ♦❧❞
✻ ❞❡❝❧❛r❡
✼
❝✉rs♦r ❝✶✭♣❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡✮ ✐s
✽
s❡❧❡❝t ❞❡♣t♥♦✱ ❞♥❛♠❡
✾
❢r♦♠ ❞❡♣t
340
Casa do Código
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✷✽
✷✾
✸✵
✸✶
✸✷
✸✸
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
Capítulo 19. Triggers
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦❀
✲✲
❝✉rs♦r ❝✷✭♣❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡✮ ✐s
s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡
❢r♦♠ ❡♠♣
✇❤❡r❡ ❡♠♣♥♦ ❂ ♣❡♠♣♥♦❀
✲✲
❝✉rs♦r ❝✸✭♣❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡✮ ✐s
s❡❧❡❝t ❝♦✉♥t✭✯✮
❢r♦♠ ❡♠♣
✇❤❡r❡ ❞❡♣t♥♦ ❂ ♣❞❡♣t♥♦❀
✲✲
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡❀
✇❞♥❛♠❡
❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✇❡♠♣♥♦
❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✇❡♥❛♠❡
❡♠♣✳❡♥❛♠❡✪t②♣❡❀
qt❴❡♠♣♥♦ ♥✉♠❜❡r ❞❡❢❛✉❧t ✵❀
❜❡❣✐♥
✲✲
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✐❢ ✐♥s❡rt✐♥❣ t❤❡♥
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✶ ✭✿♥❡✇✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✲✲
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❞❡♣t ✭❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❧♦❝✮
✈❛❧✉❡s ✭✿♥❡✇✳❞❡♣t♥♦✱ ✿♥❡✇✳❞♥❛♠❡✱ ♥✉❧❧✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦ ❡①✐st❡♥t❡✿ ✬⑤⑤✇❞❡♣t♥♦⑤⑤✬ ✲
✬⑤⑤✇❞♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
341
19.6. Trigger de view
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
✺✷
✺✸
✺✹
✺✺
✺✻
✺✼
✺✽
✺✾
✻✵
✻✶
✻✷
✻✸
✻✹
✻✺
✻✻
✻✼
✻✽
✻✾
✼✵
✼✶
✼✷
✼✸
✼✹
✼✺
✼✻
✼✼
✼✽
✼✾
342
Casa do Código
♦♣❡♥ ❝✷ ✭✿♥❡✇✳❡♠♣♥♦✮❀
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✐♥s❡rt ✐♥t♦ ❡♠♣ ✭❡♠♣♥♦✱ ❡♥❛♠❡✱ ❥♦❜✱ s❛❧✱ ♠❣r✱ ❞❡♣t♥♦✮
✈❛❧✉❡s ✭✿♥❡✇✳❡♠♣♥♦✱ ✿♥❡✇✳❡♥❛♠❡✱ ✿♥❡✇✳❥♦❜✱ ✿♥❡✇✳s❛❧✱
✿♥❡✇✳♠❣r✱ ✿♥❡✇✳❞❡♣t♥♦✮❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❋✉♥❝✐♦♥ár✐♦ ❝❛❞❛str❛❞♦ ❝♦♠ s✉❝❡ss♦✳✬✮❀
❡❧s❡
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❋✉♥❝✐♦♥ár✐♦ ❡①✐st❡♥t❡✿ ✬⑤⑤✇❡♠♣♥♦⑤⑤✬ ✲ ✬⑤⑤✇❡♥❛♠❡⑤⑤✬✳✬✮❀
❡♥❞ ✐❢❀
✲✲
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❡❧s✐❢ ✉♣❞❛t✐♥❣ t❤❡♥
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✶ ✭✿♥❡✇✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✲✲
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ♥ã♦ ❡①✐st❡✳✬✮❀
✲✲
❡❧s❡
✲✲
✉♣❞❛t❡ ❞❡♣t
s❡t
❞♥❛♠❡ ❂ ✿♥❡✇✳❞♥❛♠❡
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿♥❡✇✳❞❡♣t♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♥❡✇✳❞♥❛♠❡⑤⑤✬✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
♦♣❡♥ ❝✷ ✭✿♥❡✇✳❡♠♣♥♦✮❀
Casa do Código
✽✵
✽✶
✽✷
✽✸
✽✹
✽✺
✽✻
✽✼
✽✽
✽✾
✾✵
✾✶
✾✷
✾✸
✾✹
✾✺
✾✻
✾✼
✾✽
✾✾
✶✵✵
✶✵✶
✶✵✷
✶✵✸
✶✵✹
✶✵✺
✶✵✻
✶✵✼
✶✵✽
✶✵✾
✶✶✵
✶✶✶
✶✶✷
✶✶✸
✶✶✹
✶✶✺
✶✶✻
Capítulo 19. Triggers
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ♥ã♦ ❝❛❞❛str❛❞♦✳✬✮❀
✲✲
❡❧s❡
✉♣❞❛t❡ ❡♠♣
s❡t
❡♥❛♠❡ ❂ ✿♥❡✇✳❡♥❛♠❡
✱❥♦❜
❂ ✿♥❡✇✳❥♦❜
✱s❛❧
❂ ✿♥❡✇✳s❛❧
✱♠❣r
❂ ✿♥❡✇✳♠❣r
✱❞❡♣t♥♦ ❂ ✿♥❡✇✳❞❡♣t♥♦
✇❤❡r❡ ❡♠♣♥♦ ❂ ✿♥❡✇✳❡♠♣♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ❛t✉❛❧✐③❛❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♥❡✇✳❡♥❛♠❡⑤⑤✬✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❡❧s✐❢ ❞❡❧❡t✐♥❣ t❤❡♥
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❡♠♣r❡❣❛❞♦✳
♦♣❡♥ ❝✷ ✭✿♦❧❞✳❡♠♣♥♦✮❀
❢❡t❝❤ ❝✷ ✐♥t♦ ✇❡♠♣♥♦✱ ✇❡♥❛♠❡❀
✲✲
✐❢ ❝✷✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ♥ã♦ ❝❛❞❛str❛❞♦✳✬✮❀
✲✲
❡❧s❡
❞❡❧❡t❡ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✿♦❧❞✳❡♠♣♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♦❧❞✳❡♥❛♠❡⑤⑤✬✳✬✮❀
✲✲
❡♥❞ ✐❢❀
✲✲
343
19.6. Trigger de view
✶✶✼
✶✶✽
✶✶✾
✶✷✵
✶✷✶
✶✷✷
✶✷✸
✶✷✹
✶✷✺
✶✷✻
✶✷✼
✶✷✽
✶✷✾
✶✸✵
✶✸✶
✶✸✷
✶✸✸
✶✸✹
✶✸✺
Casa do Código
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✶ ✭✿♦❧❞✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✶ ✐♥t♦ ✇❞❡♣t♥♦✱ ✇❞♥❛♠❡❀
✲✲
✐❢ ❝✶✪♥♦t❢♦✉♥❞ t❤❡♥
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ♥ã♦ ❡①✐st❡✳✬✮❀
✲✲
❡❧s❡
✲✲
✲✲ ✈❡r✐❢✐❝❛ s❡ ❡①✐st❡ ❞❡♣❛rt❛♠❡♥t♦✳
♦♣❡♥ ❝✸ ✭✿♦❧❞✳❞❡♣t♥♦✮❀
❢❡t❝❤ ❝✸ ✐♥t♦ qt❴❡♠♣♥♦❀
✲✲
✐❢ qt❴❡♠♣♥♦ ❂ ✵ t❤❡♥
✲✲
❞❡❧❡t❡ ❢r♦♠ ❞❡♣t ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿♦❧❞✳❞❡♣t♥♦❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ❡①❝❧✉í❞♦ ❝♦♠
s✉❝❡ss♦✿ ✬⑤⑤✿♦❧❞✳❞♥❛♠❡⑤⑤✬✳✬✮❀
✶✸✻
✲✲
✶✸✼
❡❧s❡
✶✸✽
✲✲
✶✸✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❖ ❞❡♣❛rt❛♠❡♥t♦
✬⑤⑤✿♦❧❞✳❞♥❛♠❡⑤⑤✬
♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳
❆✐♥❞❛ ❡①✐st❡♠
✶✹✵
✲✲
✶✹✶
❡♥❞ ✐❢❀
✶✹✷
✲✲
✶✹✸
❡♥❞ ✐❢❀
✶✹✹
✲✲
✶✹✺
❡♥❞ ✐❢❀
✶✹✻
✲✲
✶✹✼✯ ❡♥❞❀
❙◗▲❃ ✴
●❛t✐❧❤♦ ❝r✐❛❞♦✳
344
Casa do Código
Capítulo 19. Triggers
❙◗▲❃
Vamos testar a ação de exclusão:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✼✾✸✺
✽✵✵✶
✽✵✵✵
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
P❆❯▲
❙■▲❱❊❙❚❊❘
❇❘❯❈❊❲
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
✼✾✵✷
❙❆▲❊❙▼❆◆
✶✻✵✵
✼✻✾✽
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
✼✽✸✾
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
▼❆◆❆●❊❘
✷✽✺✵
✼✽✸✾
▼❆◆❆●❊❘
✷✹✺✵
✼✽✸✾
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
P❘❊❙■❉❊◆❚
✺✵✵✵
❙❆▲❊❙▼❆◆
✶✺✵✵
✼✻✾✽
❈▲❊❘❑
✶✸✸✶
✼✼✽✽
❈▲❊❘❑
✾✺✵
✼✻✾✽
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❈▲❊❘❑
✶✸✵✵
✼✼✽✷
❙❆▲❊❙▼❆◆
✶✵✵✵
✼✻✾✽
▼❆◆❆●❊❘
✶✵✵✵
✼✽✸✾
❆◆❆▲❨❙❚
✶✺✵✵
✼✽✸✾
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✷✵
✸✵
✸✵
✷✵
✸✵
✸✵
✶✵
✷✵
✶✵
✸✵
✷✵
✸✵
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❊❙◗❯■❙❆
❙❆▲❊❙
❙❆▲❊❙
P❊❙◗❯■❙❆
❙❆▲❊❙
❙❆▲❊❙
❆❈❈❖❯◆❚■◆●
P❊❙◗❯■❙❆
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
P❊❙◗❯■❙❆
❙❆▲❊❙
345
Casa do Código
19.6. Trigger de view
✷✵
✶✵
✸✵
✽✵
✷✵
P❊❙◗❯■❙❆
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❙✫❊
P❊❙◗❯■❙❆
✶✼ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
❙◗▲❃ ❞❡❧❡t❡ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❡♠♣♥♦ ❂ ✽✵✵✵❀
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❇❘❯❈❊❲✳
❖ ❞❡♣❛rt❛♠❡♥t♦ P❊❙◗❯■❙❆ ♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳ ❆✐♥❞❛ ❡①✐st❡♠
❢✉♥❝✐♦♥ár✐♦s ❛❣r❡❣❛❞♦s ❛ ❡❧❡✳
✶ ❧✐♥❤❛ ❞❡❧❡t❛❞❛✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✸✻✾
✼✹✾✾
✼✺✷✶
✼✺✻✻
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✼✽✽
✼✽✸✾
✼✽✹✹
✼✽✼✻
✼✾✵✵
✼✾✵✷
✼✾✸✹
✼✾✸✺
✽✵✵✶
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❙▼■❚❍
❆▲▲❊◆
❲❆❘❉
❏❖◆❊❙
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❙❈❖❚❚
❑■◆●
❚❯❘◆❊❘
❆❉❆▼❙
❏❆▼❊❙
❋❖❘❉
▼■▲▲❊❘
P❆❯▲
❙■▲❱❊❙❚❊❘
❉❊P❚◆❖ ❉◆❆▼❊
346
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❈▲❊❘❑
✾✻✽
✼✾✵✷
❙❆▲❊❙▼❆◆
✶✻✵✵
✼✻✾✽
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
▼❆◆❆●❊❘
✸✺✾✾✱✼✺
✼✽✸✾
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
▼❆◆❆●❊❘
✷✽✺✵
✼✽✸✾
▼❆◆❆●❊❘
✷✹✺✵
✼✽✸✾
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
P❘❊❙■❉❊◆❚
✺✵✵✵
❙❆▲❊❙▼❆◆
✶✺✵✵
✼✻✾✽
❈▲❊❘❑
✶✸✸✶
✼✼✽✽
❈▲❊❘❑
✾✺✵
✼✻✾✽
❆◆❆▲❨❙❚
✸✻✸✵
✼✺✻✻
❈▲❊❘❑
✶✸✵✵
✼✼✽✷
❙❆▲❊❙▼❆◆
✶✵✵✵
✼✻✾✽
▼❆◆❆●❊❘
✶✵✵✵
✼✽✸✾
Casa do Código
✲✲✲✲✲✲✲✲✲✲
✷✵
✸✵
✸✵
✷✵
✸✵
✸✵
✶✵
✷✵
✶✵
✸✵
✷✵
✸✵
✷✵
✶✵
✸✵
✽✵
Capítulo 19. Triggers
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
P❊❙◗❯■❙❆
❙❆▲❊❙
❙❆▲❊❙
P❊❙◗❯■❙❆
❙❆▲❊❙
❙❆▲❊❙
❆❈❈❖❯◆❚■◆●
P❊❙◗❯■❙❆
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
P❊❙◗❯■❙❆
❙❆▲❊❙
P❊❙◗❯■❙❆
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❙✫❊
✶✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
❙◗▲❃ ❞❡❧❡t❡ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈ ✇❤❡r❡ ❞❡♣t♥♦ ❂ ✷✵❀
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❙▼■❚❍✳
❖ ❞❡♣❛rt❛♠❡♥t♦ P❊❙◗❯■❙❆ ♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳
❢✉♥❝✐♦♥ár✐♦s ❛❣r❡❣❛❞♦s ❛ ❡❧❡✳
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❏❖◆❊❙✳
❖ ❞❡♣❛rt❛♠❡♥t♦ P❊❙◗❯■❙❆ ♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳
❢✉♥❝✐♦♥ár✐♦s ❛❣r❡❣❛❞♦s ❛ ❡❧❡✳
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❙❈❖❚❚✳
❖ ❞❡♣❛rt❛♠❡♥t♦ P❊❙◗❯■❙❆ ♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳
❢✉♥❝✐♦♥ár✐♦s ❛❣r❡❣❛❞♦s ❛ ❡❧❡✳
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❆❉❆▼❙✳
❖ ❞❡♣❛rt❛♠❡♥t♦ P❊❙◗❯■❙❆ ♥ã♦ ♣♦❞❡ s❡r ❡①❝❧✉í❞♦✳
✉♥❝✐♦♥ár✐♦s ❛❣r❡❣❛❞♦s ❛ ❡❧❡✳
❋✉♥❝✐♦♥ár✐♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ ❋❖❘❉✳
❉❡♣❛rt❛♠❡♥t♦ ❡①❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✿ P❊❙◗❯■❙❆✳
❆✐♥❞❛ ❡①✐st❡♠
❆✐♥❞❛ ❡①✐st❡♠
❆✐♥❞❛ ❡①✐st❡♠
❆✐♥❞❛ ❡①✐st❡♠
✺ ❧✐♥❤❛s ❞❡❧❡t❛❞❛s✳
347
Casa do Código
19.6. Trigger de view
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❴❞❡♣t❴✈❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✹✾✾
✼✺✷✶
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✽✸✾
✼✽✹✹
✼✾✵✵
✼✾✸✹
✼✾✸✺
✽✵✵✶
❊◆❆▼❊
✲✲✲✲✲✲✲✲✲✲
❆▲▲❊◆
❲❆❘❉
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❑■◆●
❚❯❘◆❊❘
❏❆▼❊❙
▼■▲▲❊❘
P❆❯▲
❙■▲❱❊❙❚❊❘
❏❖❇
❙❆▲
▼●❘
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
❙❆▲❊❙▼❆◆
✶✻✵✵
✼✻✾✽
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
❙❆▲❊❙▼❆◆
✶✷✺✵
✼✻✾✽
▼❆◆❆●❊❘
✷✽✺✵
✼✽✸✾
▼❆◆❆●❊❘
✷✹✺✵
✼✽✸✾
P❘❊❙■❉❊◆❚
✺✵✵✵
❙❆▲❊❙▼❆◆
✶✺✵✵
✼✻✾✽
❈▲❊❘❑
✾✺✵
✼✻✾✽
❈▲❊❘❑
✶✸✵✵
✼✼✽✷
❙❆▲❊❙▼❆◆
✶✵✵✵
✼✻✾✽
▼❆◆❆●❊❘
✶✵✵✵
✼✽✸✾
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✸✵
✸✵
✸✵
✸✵
✶✵
✶✵
✸✵
✸✵
✶✵
✸✵
✽✵
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❙❆▲❊❙
❙❆▲❊❙
❙❆▲❊❙
❙❆▲❊❙
❆❈❈❖❯◆❚■◆●
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❙❆▲❊❙
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❙✫❊
✶✶ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Com isso, encerramos o assunto sobre triggers. Como pôde ser visto,
este tipo de objeto é muito interessante e útil para implementar diversos tipos
de rotinas que possam ser executadas sem a intervenção direta do usuário e
com segurança, o que faz dele um artifício muito poderoso.
348
Capítulo 20
PL/SQL Tables (estruturas
homogêneas)
Conforme comentamos anteriormente, a PL/SQL contempla em sua estrutura, todos os recursos encontrados em outras linguagens de programação.
Um recurso muito bacana é o uso de dados intrínsecos, através das estruturas
homogenias, comumente, chamadas de vetor. Em PL/SQL chamamos este
recurso de PL/SQL Table.
Para quem não conhece vetores, um vetor é uma estrutura array de um
tipo definido de dado. Por exemplo, podemos ter um vetor de numéricos,
caracteres ou datas. Podemos imaginar um array, ou melhor, um vetor, como
se fosse a coluna de uma determinada tabela que possui um tipo definido, que
pudesse ser preenchida por vários valores.
A diferença entre um e outro é que os vetores são definidos apenas em
Casa do Código
memória, bem como os dados que são atribuídos a eles. Contudo, como estão
em memória, proporcionam uma velocidade maior de acesso aos dados, ao
contrário do uso de tabelas, no qual é necessário, na maioria das vezes, acessálos fisicamente no disco.
Para utilizarmos uma PL/SQL Table, temos que primeiro defini-la como
se fosse um tipo de dado sendo criado, chamado de type. Isso deve ser
feito na área de declaração ( declare) do bloco PL/SQL, sendo um bloco
anônimo ou através de uma procedure, function ou package. Após
a definição do type PL/SQL Table, é necessário declarar uma variável que
utilizará esta definição. Vale salientar que inicialmente a definição do type
não ocupa espaço na memória, apenas quando declaramos uma variável com
base neste type é que isto acontece.
Veja o exemplo a seguir.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
t②♣❡ ❞❡♣t♥♦t❛❜ ✐s t❛❜❧❡ ♦❢ ♥✉♠❜❡r ✐♥❞❡① ❜② ❜✐♥❛r②❴✐♥t❡❣❡r❀
✹
t②♣❡ ❞♥❛♠❡t❛❜ ✐s t❛❜❧❡ ♦❢ ❞❡♣t✳❞♥❛♠❡✪t②♣❡ ✐♥❞❡① ❜②
❜✐♥❛r②❴✐♥t❡❣❡r❀
✺
t②♣❡ ❧♦❝t❛❜
✐s t❛❜❧❡ ♦❢ ✈❛r❝❤❛r✷✭✷✵✵✮ ✐♥❞❡① ❜②
❜✐♥❛r②❴✐♥t❡❣❡r❀
✻
✲✲
✼
✇❞❡♣t♥♦t❛❜
❞❡♣t♥♦t❛❜❀
✽
✇❞♥❛♠❡t❛❜
❞♥❛♠❡t❛❜❀
✾
✇❧♦❝t❛❜
❧♦❝t❛❜❀
✶✵
✲✲
✶✶
✐❞①
❜✐♥❛r②❴✐♥t❡❣❡r ❞❡❢❛✉❧t ✵❀
✶✷ ❜❡❣✐♥
✶✸
✲✲
✶✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❧♦❝ ❢r♦♠ ❞❡♣t✮ ❧♦♦♣
✶✺
✐❞① ✿❂ ✐❞① ✰ ✶❀
✶✻
✇❞❡♣t♥♦t❛❜✭✐❞①✮ ✿❂ r✶✳❞❡♣t♥♦❀
✶✼
✇❞♥❛♠❡t❛❜✭✐❞①✮ ✿❂ r✶✳❞♥❛♠❡❀
✶✽
✇❧♦❝t❛❜✭✐❞①✮
✿❂ r✶✳❧♦❝❀
✶✾
❡♥❞ ❧♦♦♣❀
✷✵
✲✲
✷✶
❢♦r ✐ ✐♥ ✶✳✳✇❞❡♣t♥♦t❛❜✳❧❛st ❧♦♦♣
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣t♥♦t❛❜✭✐✮⑤⑤
350
Casa do Código
Capítulo 20. PL/SQL Tables (estruturas homogêneas)
✷✸
✷✹
✷✺
❡♥❞ ❧♦♦♣❀
✷✻ ❡♥❞❀
✷✼ ✴
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
❉❡♣❛rt❛♠❡♥t♦✿
✶✵
✸✵
✹✵
✽✵
✾✵
✾✾
✽✽
✹✶
✹✷
✬ ✲ ✬⑤⑤✇❞♥❛♠❡t❛❜✭✐✮⑤⑤
✬ ✲ ▲♦❝❛❧✿ ✬⑤⑤✇❧♦❝t❛❜✭✐✮✮❀
✲
✲
✲
✲
✲
✲
✲
✲
✲
❆❈❈❖❯◆❚■◆● ✲ ▲♦❝❛❧✿ ❋▲❖❘■❉❆
❙❆▲❊❙ ✲ ▲♦❝❛❧✿ ❈❍■❈❆●❖
❖P❊❘❆❚■❖◆❙ ✲ ▲♦❝❛❧✿ ❇❖❙❚❖◆
❙✫❊ ✲ ▲♦❝❛❧✿
❋■◆❆◆❈■❆▲ ✲ ▲♦❝❛❧✿
❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
●❊◆❊❘❆▲ ▲❊❉●❊❘ ✲ ▲♦❝❛❧✿
P❯❘❈❍❆❙■◆● ✲ ▲♦❝❛❧✿
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Pois bem, o exemplo anterior é muito simples. Ele seleciona dados da tabela dept. A intenção aqui não é mostrar exemplos complexos que dificultem o entendimento do assunto. Pelo contrário, utilizamos exemplos simples,
focando nos pontos que devemos aprender. Desta forma, analisando o programa, temos nas linhas 3 a 4, três definições de tabela PL/SQL. A definição
de uma tabela PL/SQL deve iniciar pelo comando type seguido do nome
do tipo que queremos criar. Por exemplo, na linha 3, criamos com o nome
deptnotab.
Logo após o nome, colocamos a expressão is table of, que vai nos
indicar de que tipo será nossa PL/SQL Table, que neste caso definimos que é
do tipo number. Depois de informarmos o tipo, devemos utilizar a cláusula
index by binary_integer, que é uma cláusula padrão para a criação de
PL/SQL Tables. Ela tem a a ver com o tipo de indexação (no caso, binária)
usada para a criação da tabela e acesso aos dados na memória.
As linhas 4 e 5 seguem o mesmo formato de definição, sendo que uma foi
definida com o mesmo tipo da coluna deptno da tabela dept e a outra com
o tipo varchar2(200). Veja que, nesse exemplo, a definição do type da
351
Casa do Código
tabela PL/SQL é parecida com as definições usadas em variáveis.
Nas linhas 7 a 8, estão declaradas variáveis dos tipos criados nas linhas 3 a
5, ou seja, variáveis definidas com o tipo PL/SQL Table. São estas, as variáveis
que serão manipuladas em nosso programa. Nas linhas 14 a 19, temos um
cursor for loop que lê todas as informações da tabela dept e as armazena
em nossas tabelas PL/SQL.
Uma observação importante é que, embora neste exemplo tenha sido criado um type de tabela PL/SQL para cada informação (código do departamento, nome do departamento e localização) é possível criar uma tabela
PL/SQL usando %rowtype referenciando cursores ou tabelas. Nesses casos,
é possível definir um type de tabela PL/SQL constituído por vários arrays,
ou melhor, campos, para uma única PL/SQL Table.
Note que, dessa forma, a tabela PL/SQL ficará limitada à definição da tabela ou cursor utilizados na declaração. Contudo, neste capítulo, estamos
falando de vetores, ou seja, estruturas homogêneas de dados. Assim sendo,
como nesse exemplo foram recuperados dados referentes a três colunas da
tabela dept, foi preciso definir três tabelas PL/SQL para guardá-los, e assim
mantermos os conceitos referentes a vetores.
Continuando, conforme pode ser visto nas linhas 16 a 18, a forma de armazenamento precisa ser do tipo indexada para que possamos navegar entre as
posições da tabela PL/SQL. Para isso, criamos uma variável chamada idx que
será alimentada dentro do loop e servirá como índice de navegação dentro
das nossas PL/SQL Tables. Para armazenar determinado valor, informamos
o nome da tabela PL/SQL seguido do indexador entre parênteses, conforme
pôde ser visto no exemplo (linhas 16 a 18).
Seguindo o exemplo, utilizamos outro for loop que lê nossas tabelas
PL/SQL e imprime os valores na tela (linhas 21 a 25). Algumas funções estão
disponíveis para o type PL/SQL Table. Uma delas é a função last que retorna o último registro preenchido no array. Também temos a função count
que retorna a quantidade de registros contidos na tabela. No exemplo, foi utilizada a função last para indicar a posição final do for loop, ou seja, ele
deve varrer a tabela PL/SQL da posição 1 até a última posição dela.
Repare que usamos o próprio indexador do for loop (i) para navegar pelos valores das tabelas, gravados anteriormente. Como nossas tabelas
352
Casa do Código
Capítulo 20. PL/SQL Tables (estruturas homogêneas)
foram preenchidas utilizando o mesmo for loop, ou seja, todas possuindo
a mesma quantidade de registros, nós utilizamos apenas uma delas para servir como base para sabermos a quantidade exata que deve ser lida pelo cursor
for loop. No entanto, através do indexador (i) do cursor, todos os registros de todas as tabelas foram lidos e utilizados na geração da saída feita pelo
dbms_output.
Veja a figura a seguir para melhor entendimento de como é realizada a
gravação e leitura dos dados, usando como base o programa do exemplo.
Cursor: gravação da tabela PL/SQL
Fig. 20.1: Esquema de gravação de uma PL/SQL Table
Cursor: leitura da tabela PL/SQL
353
Casa do Código
Fig. 20.2: Esquema de leitura de uma PL/SQL Table
Para concluir, seguem dois exemplos onde foram definidas PL/SQL Tables
com base em tabelas e cursores.
Exemplo utilizando cursor:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
❝✉rs♦r ❝✶ ✐s
✹
s❡❧❡❝t ❞✳❞❡♣❛rt♠❡♥t❴✐❞
✺
✱❞❡♣❛rt♠❡♥t❴♥❛♠❡
✻
✱❢✐rst❴♥❛♠❡
✼
✱❤✐r❡❴❞❛t❡
✽
✱s❛❧❛r②
✾
❢r♦♠ ❞❡♣❛rt♠❡♥ts ❞
✶✵
✱❡♠♣❧♦②❡❡s ❡
✶✶
✇❤❡r❡ ❞✳♠❛♥❛❣❡r❴✐❞ ❂ ❡✳❡♠♣❧♦②❡❡❴✐❞
✶✷
♦r❞❡r ❜② ❞❡♣❛rt♠❡♥t❴♥❛♠❡❀
354
Casa do Código
Capítulo 20. PL/SQL Tables (estruturas homogêneas)
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
✶✾
✷✵
✷✶
✷✷
✷✸
✷✹
✷✺
✷✻
✷✼
✲✲
t②♣❡ t❛❜ ✐s t❛❜❧❡ ♦❢ ❝✶✪r♦✇t②♣❡ ✐♥❞❡① ❜② ❜✐♥❛r②❴✐♥t❡❣❡r❀
✲✲
t❜❣❡r❡♥t❡ t❛❜❀
♥ ♥✉♠❜❡r❀
✲✲
❜❡❣✐♥
❢♦r r✶ ✐♥ ❝✶ ❧♦♦♣
t❜❣❡r❡♥t❡✭r✶✳❞❡♣❛rt♠❡♥t❴✐❞✮ ✿❂ r✶❀
❡♥❞ ❧♦♦♣❀
✲✲
♥ ✿❂ t❜❣❡r❡♥t❡✳❢✐rst❀
✲✲
✇❤✐❧❡ ♥ ❁❂ t❜❣❡r❡♥t❡✳❧❛st ❧♦♦♣
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣t♦✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❞❡♣❛rt♠❡♥t❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✬●❡r❡♥t❡✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❢✐rst❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✷✽
✬❉t✳ ❆❞♠✐✳✿ ✬⑤⑤t❜❣❡r❡♥t❡✭♥✮✳❤✐r❡❴❞❛t❡⑤⑤✬ ✬⑤⑤
✷✾
✸✵
✬❙❛❧✳✿ ✬⑤⑤t♦❴❝❤❛r✭t❜❣❡r❡♥t❡✭♥✮✳s❛❧❛r②✱
✬❢♠✩✾✾✾❣✾✾✾❣✾✾✵❞✵✵✬✮✮❀
✸✶
♥ ✿❂ t❜❣❡r❡♥t❡✳♥❡①t✭♥✮❀
✸✷
❡♥❞ ❧♦♦♣❀
✸✸ ❡♥❞❀
✸✹ ✴
❉❡♣t♦✿ ❆❞♠✐♥✐str❛t✐♦♥ ●❡r❡♥t❡✿ ❏❡♥♥✐❢❡r ❉t✳ ❆❞♠✐✳✿ ✶✼✴✵✾✴✾✼
❙❛❧✳✿ ✩✹✳✹✵✵✱✵✵
❉❡♣t♦✿ ▼❛r❦❡t✐♥❣ ●❡r❡♥t❡✿ ▼✐❝❤❛❡❧ ❉t✳ ❆❞♠✐✳✿ ✶✼✴✵✷✴✵✻
❙❛❧✳✿ ✩✶✸✳✵✵✵✱✵✵
❉❡♣t♦✿ P✉r❝❤❛s✐♥❣ ●❡r❡♥t❡✿ ❉❡♥ ❉t✳ ❆❞♠✐✳✿ ✵✼✴✶✷✴✵✹
❙❛❧✳✿ ✩✶✶✳✵✵✵✱✵✵
❉❡♣t♦✿ ❍✉♠❛♥ ❘❡s♦✉r❝❡s ●❡r❡♥t❡✿ ❙✉s❛♥ ❉t✳ ❆❞♠✐✳✿ ✵✼✴✵✻✴✵✹
❙❛❧✳✿ ✩✻✳✺✵✵✱✵✵
❉❡♣t♦✿ ❙❤✐♣♣✐♥❣ ●❡r❡♥t❡✿ ❆❞❛♠ ❉t✳ ❆❞♠✐✳✿ ✶✵✴✵✹✴✵✼
❙❛❧✳✿ ✩✽✳✷✵✵✱✵✵
❉❡♣t♦✿ ■❚ ●❡r❡♥t❡✿ ❆❧❡①❛♥❞❡r ❉t✳ ❆❞♠✐✳✿ ✵✸✴✵✶✴✵✵ ❙❛❧✳✿ ✩✾✳✵✵✵✱✵✵
❉❡♣t♦✿ P✉❜❧✐❝ ❘❡❧❛t✐♦♥s ●❡r❡♥t❡✿ ❍❡r♠❛♥♥ ❉t✳ ❆❞♠✐✳✿ ✵✼✴✵✻✴✵✹
❙❛❧✳✿ ✩✶✵✳✵✵✵✱✵✵
❉❡♣t♦✿ ❙❛❧❡s ●❡r❡♥t❡✿ ❏♦❤♥ ❉t✳ ❆❞♠✐✳✿ ✵✶✴✶✵✴✵✻ ❙❛❧✳✿ ✩✶✹✳✵✵✵✱✵✵
❉❡♣t♦✿ ❊①❡❝✉t✐✈❡ ●❡r❡♥t❡✿ ❙t❡✈❡♥ ❉t✳ ❆❞♠✐✳✿ ✶✼✴✵✻✴✾✼
355
Casa do Código
❙❛❧✳✿ ✩✷✹✳✵✵✵✱✵✵
❉❡♣t♦✿ ❋✐♥❛♥❝❡ ●❡r❡♥t❡✿ ◆❛♥❝② ❉t✳ ❆❞♠✐✳✿ ✶✼✴✵✽✴✵✹
❙❛❧✳✿ ✩✶✷✳✵✵✵✱✵✵
❉❡♣t♦✿ ❆❝❝♦✉♥t✐♥❣ ●❡r❡♥t❡✿ ❙❤❡❧❧❡② ❉t✳ ❆❞♠✐✳✿ ✵✼✴✵✻✴✵✹
❙❛❧✳✿ ✩✶✷✳✵✵✵✱✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
No exemplo anterior, temos um programa que lê as informações de departamento e seus gerentes. Para tal, criamos um cursor (linhas 3 a 12) que
busca cada departamento cadastrado na tabela departments que possua
gerente associado na tabela employees. São trazidas pelo cursor as informações: código do departamento, nome do departamento, primeiro nome do
gerente do departamento, data de admissão e salário do gerente.
Na linha 14, definimos um type PL/SQL Table chamado tab e atribuímos a ele o tipo c1%rowtype. Este tipo consiste em montar a mesma estrutura do cursor c1 para o tipo tab, ou seja, serão criados para a PL/SQL Table
os seguintes arrays: department_id, department_name, first_name,
hire_date e salary.
Nas linhas 20 a 22, encontra-se a abertura do cursor e atribuição dos resultados do mesmo para a tabela PL/SQL tbgerente, que foi declarada como
sendo do tipo tab na linha 16 do programa. Note que usamos como indexador o próprio valor do campo department_id, sendo que ele é único para
cada linha. Veja também, que atribuímos à PL/SQL Table o array r1. r1
possui os dados de todas as colunas do cursor. Logo, nossa tabela PL/SQL
recebe todos estes valores, respeitando a estrutura definida.
Na linha 24, temos o uso da função first indicando que queremos que
o ponteiro, que indica a posição em que o foco se encontra na PL/SQL Table,
volte para a primeira posição. Só para entendimento, cada vez que um dado
é carregado em uma linha da PL/SQL Table, o foco permanece nesta linha.
Este retorno para a primeira linha da tabela PL/SQL tem a ver com o loop
while que temos entre as linhas 26 a 32. No exemplo, com o for loop, nós
utilizamos a própria estrutura de repetição para controlar a faixa de início e
fim das linhas.
356
Casa do Código
Capítulo 20. PL/SQL Tables (estruturas homogêneas)
Como agora estamos utilizando o while, nós precisamos controlar isso.
Para tanto, testamos a variável N, que recebe a primeira posição do array na
linha 24. Logo, estamos solicitando que a estrutura while fique em loop enquanto não chegar a última linha do array. O comando utiliza a função last
da tabela PL/SQL. Veja também que, na linha 31, utilizamos a função next
para fazer com que o ponteiro vá para a próxima linha da tabela, fazendo
sucessivamente com que todas as linhas sejam varridas.
Exemplo utilizando tabela ( %rowtype):
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
t②♣❡ ❞❡♣t❛❜ ✐s t❛❜❧❡ ♦❢ ❞❡♣t✪r♦✇t②♣❡ ✐♥❞❡① ❜②
❜✐♥❛r②❴✐♥t❡❣❡r❀
✹
✲✲
✺
✇❞❡♣t❛❜
❞❡♣t❛❜❀
✻
✲✲
✼
✐❞①
❜✐♥❛r②❴✐♥t❡❣❡r ❞❡❢❛✉❧t ✵❀
✽ ❜❡❣✐♥
✾
✲✲
✶✵
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t✮ ❧♦♦♣
✶✶
✐❞① ✿❂ ✐❞① ✰ ✶❀
✶✷
✇❞❡♣t❛❜✭✐❞①✮ ✿❂ r✶❀
✶✸
❡♥❞ ❧♦♦♣❀
✶✹
✲✲
✶✺
❢♦r ✐ ✐♥ ✶✳✳✇❞❡♣t❛❜✳❧❛st ❧♦♦♣
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❞❡♣t♥♦⑤⑤
✶✼
✬ ✲ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❞♥❛♠❡⑤⑤
✶✽
✬ ✲ ▲♦❝❛❧✿ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❧♦❝✮❀
✶✾
❡♥❞ ❧♦♦♣❀
✷✵ ❡♥❞❀
✷✶ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵ ✲ ❆❈❈❖❯◆❚■◆● ✲ ▲♦❝❛❧✿ ❋▲❖❘■❉❆
❉❡♣❛rt❛♠❡♥t♦✿ ✸✵ ✲ ❙❆▲❊❙ ✲ ▲♦❝❛❧✿ ❈❍■❈❆●❖
❉❡♣❛rt❛♠❡♥t♦✿ ✹✵ ✲ ❖P❊❘❆❚■❖◆❙ ✲ ▲♦❝❛❧✿ ❇❖❙❚❖◆
❉❡♣❛rt❛♠❡♥t♦✿ ✽✵ ✲ ❙✫❊ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✾✵ ✲ ❋■◆❆◆❈■❆▲ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✾✾ ✲ ❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
357
Casa do Código
❉❡♣❛rt❛♠❡♥t♦✿ ✽✽ ✲ ❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
❉❡♣❛rt❛♠❡♥t♦✿ ✹✶ ✲ ●❊◆❊❘❆▲ ▲❊❉●❊❘ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✹✷ ✲ P❯❘❈❍❆❙■◆● ✲ ▲♦❝❛❧✿
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Esse exemplo é muito semelhante aos demais. A única diferença é a forma
como foi criado o type PL/SQL Table. Note que a tabela foi definida como
tendo a mesma estrutura da tabela dept. Logo, estamos criando em memória
a mesma estrutura da dept que existe fisicamente no banco de dados.
358
Capítulo 21
PL/SQL Records (estruturas
heterogêneas)
Vimos que em PL/SQL Table trabalhamos com dados intrínsecos através das
estruturas homogêneas. Em PL/SQL Records, vamos trabalhar com estruturas heterogêneas. Com PL/SQL Table, estávamos limitados a criar types Table constituídas apenas de um tipo de dado (numérico, caractere ou data), ou
utilizando tabelas e cursores, onde, embora, tivéssemos vários campos com
tipos de dados diferentes, cada qual possuía seus tipos já definidos, sem a
possibilidade de alterarmos conforme a necessidade.
Com o recurso de PL/SQL Records, podemos definir tipos e estruturas de
dados distintas dentro de um mesmo type, sem precisar criar vários types
para cada um, ou sem necessitar associá-los a tabelas ou cursores.
Veja o exemplo a seguir:
Casa do Código
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
t②♣❡ ❞❡♣r❡❝ ✐s r❡❝♦r❞ ✭ ❞❡♣t♥♦ ♥✉♠❜❡r✭✷✱✵✮
✹
✱❞♥❛♠❡ ✈❛r❝❤❛r✷✭✶✹✮
✺
✱❧♦❝
✈❛r❝❤❛r✷✭✶✸✮✮❀
✻
✲✲
✼
✇❞❡♣r❡❝
❞❡♣r❡❝❀
✽
✲✲
✾ ❜❡❣✐♥
✶✵
✲✲
✶✶
s❡❧❡❝t ✯
✶✷
✐♥t♦ ✇❞❡♣r❡❝
✶✸
❢r♦♠ ❞❡♣t
✶✹
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✶✵❀
✶✺
✲✲
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣r❡❝✳❞❡♣t♥♦⑤⑤
✬ ✲ ✬⑤⑤✇❞❡♣r❡❝✳❞♥❛♠❡⑤⑤
✶✼
✬ ✲ ▲♦❝❛❧✿ ✬⑤⑤✇❞❡♣r❡❝✳❧♦❝✮❀
✶✽
✶✾ ❡♥❞❀
✷✵ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵ ✲ ❆❈❈❖❯◆❚■◆● ✲ ▲♦❝❛❧✿ ❋▲❖❘■❉❆
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Nesse exemplo, começamos pela criação, linha 3, onde informamos a expressão type seguida pelo nome, deprec. Logo após, informamos o tipo
do type, is record, que o define como PL/SQL Record. Após isto, entre
parênteses, informamos qual a estrutura que este type terá. Aqui, definimos
que ele será constituído por três campos, deptno, dname e loc. Desta
forma, nos é permitido, através deste type, definir quantos campos quisermos e utilizar tipos diferentes para eles, possibilitando criar uma estrutura
heterogênea.
Vale salientar que, embora os nomes dos campos sejam semelhantes aos
da tabela dept existente no banco de dados, eles não estão referenciandoos. Aqui poderíamos colocar qualquer nome, respeitando apenas as mesmas
regras para definição de variáveis.
360
Casa do Código
Capítulo 21. PL/SQL Records (estruturas heterogêneas)
Depois da criação do type, declaramos uma variável chamada wdeprec
que será definida com este tipo (linha 7). Nas linhas 11 a 14, estamos selecionando os dados da tabela dept cujo departamento seja igual a 10. Estamos
utilizando a cláusula into, onde os dados vindos do select estão sendo
atribuídos ao nosso PL/SQL Record. Nas linhas 16 a 18, temos a impressão
do resultado contido em nosso type Record. Veja a imagem a seguir, onde
é mostrada de forma simbólica a definição e armazenamento dos dados em
memória no PL/SQL Record.
Fig. 21.1: Esquema de gravação de um PL/SQL Record
Você deve ter notado que não utilizamos estruturas de repetição e que,
ao contrário disto, nosso exemplo trouxe apenas uma linha de registro. Pois
bem, uma característica do type Record é que ele por si só pode guardar
apenas um registro por vez, ao contrário do type Table, no qual podemos
inserir várias linhas.
Desta forma, na maioria das vezes vemos os types Record sendo utilizados em conjunto com os types Table, sendo que este último nos permite
gravar várias linhas. Vamos utilizar o exemplo anterior, agora, trazendo todos
os dados da tabela dept e usando o recurso de type Table juntamente com
o type Record.
361
Casa do Código
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
t②♣❡ ❞❡♣r❡❝ ✐s r❡❝♦r❞ ✭ ❞❡♣t♥♦ ♥✉♠❜❡r✭✷✱✵✮
✹
✱❞♥❛♠❡ ✈❛r❝❤❛r✷✭✶✹✮
✺
✱❧♦❝
✈❛r❝❤❛r✷✭✶✸✮✮❀
✻
✲✲
✼
t②♣❡ ❞❡♣t❛❜ ✐s t❛❜❧❡ ♦❢ ❞❡♣r❡❝ ✐♥❞❡① ❜② ❜✐♥❛r②❴✐♥t❡❣❡r❀
✽
✲✲
✾
✇❞❡♣t❛❜
❞❡♣t❛❜❀
✶✵
✐❞①
❜✐♥❛r②❴✐♥t❡❣❡r ❞❡❢❛✉❧t ✵❀
✶✶
✲✲
✶✷ ❜❡❣✐♥
✶✸
✲✲
✶✹
❢♦r r✶ ✐♥ ✭s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t✮ ❧♦♦♣
✶✺
✲✲
✶✻
✐❞① ✿❂ ✐❞① ✰ ✶❀
✶✼
✇❞❡♣t❛❜✭✐❞①✮ ✿❂ r✶❀
✶✽
✲✲
✶✾
❡♥❞ ❧♦♦♣❀
✷✵
✲✲
✷✶
❢♦r ✐ ✐♥ ✶✳✳✇❞❡♣t❛❜✳❧❛st ❧♦♦♣
✷✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❞❡♣t♥♦⑤⑤
✷✸
✬ ✲ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❞♥❛♠❡⑤⑤
✷✹
✬ ✲ ▲♦❝❛❧✿ ✬⑤⑤✇❞❡♣t❛❜✭✐✮✳❧♦❝✮❀
✷✺
❡♥❞ ❧♦♦♣❀
✷✻ ❡♥❞❀
✷✼ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵ ✲ ❆❈❈❖❯◆❚■◆● ✲ ▲♦❝❛❧✿ ❋▲❖❘■❉❆
❉❡♣❛rt❛♠❡♥t♦✿ ✸✵ ✲ ❙❆▲❊❙ ✲ ▲♦❝❛❧✿ ❈❍■❈❆●❖
❉❡♣❛rt❛♠❡♥t♦✿ ✹✵ ✲ ❖P❊❘❆❚■❖◆❙ ✲ ▲♦❝❛❧✿ ❇❖❙❚❖◆
❉❡♣❛rt❛♠❡♥t♦✿ ✽✵ ✲ ❙✫❊ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✾✵ ✲ ❋■◆❆◆❈■❆▲ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✾✾ ✲ ❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
❉❡♣❛rt❛♠❡♥t♦✿ ✽✽ ✲ ❘❍ ✲ ▲♦❝❛❧✿ ❆❘●❊◆❚■◆❆
❉❡♣❛rt❛♠❡♥t♦✿ ✹✶ ✲ ●❊◆❊❘❆▲ ▲❊❉●❊❘ ✲ ▲♦❝❛❧✿
❉❡♣❛rt❛♠❡♥t♦✿ ✹✷ ✲ P❯❘❈❍❆❙■◆● ✲ ▲♦❝❛❧✿
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
362
Casa do Código
Capítulo 21. PL/SQL Records (estruturas heterogêneas)
❙◗▲❃
Conforme mencionado, neste exemplo empregamos o uso de dois recursos em um mesmo programa, para que pudéssemos definir uma estrutura
heterogênea e poder armazenar mais de um registro em memória.
Vale salientar que os type Tables e Records podem guardar qualquer tipo
de dados, não necessariamente, dados vindos de tabelas do banco de dados.
Podemos gerar e processar dados dentro de um programa e ir alimentando
dentro destes objetos sem ter a necessidade de varrer dados que estão armazenados em tabelas, por exemplo.
Mas, voltando ao exemplo, vemos que nas linhas 3 a 5, está criado o type
Record deprec, igualmente ao exemplo anterior. Já na linha 7 temos um
type Table criado com base no type Record deprec. Dessa forma, é possível termos registros em forma de tabela, podendo armazenar mais de uma
linha na PL/SQL Table, conforme a estrutura do PL/SQL Record criado. Veja
a seguir a imagem representativa do uso destes recursos juntos.
363
Casa do Código
Fig. 21.2: Esquema do uso combinado de PL/SQL Table e PL/SQL Record
Ficou visto que a forma de definição e manipulação dos type Tables e
Records é bastante semelhante. O entendimento dos conceitos apresentado
no capítulo referente a PL/SQL Tables se faz necessário para compreender
todo o contexto apresentado nestes dois capítulos. No mais, salientamos que
o uso destes recursos pode ajudar e muito na manipulação dos dados, principalmente, em grandes volumes, quando o desempenho pode ser prejudicado,
devido a muitos acessos a rede ou ao disco na busca pelas informações.
364
Capítulo 22
Pacote utl_file
Um recurso bem interessante e muito utilizado em PL/SQL é a leitura e escrita de arquivos. Em muitas empresas a exportação e importação de arquivos
são muito utilizadas para alimentar sistemas paralelos (também chamados de
sistemas satélites) ou para gerar informações gerenciais. A possibilidade de
extrair informações do sistema e trabalhá-las usando ferramentas específicas
para análise é uma prática muito comum.
Para este trabalho existe um pacote dentro do Oracle chamado
utl_file. Este pacote trabalha com recursos que possibilita a comunicação entre o banco de dados Oracle e o sistema operacional, fazendo com que
consigamos ler ou gerar arquivos externamente ao banco de dados.
Este pacote possui uma série de funções e procedimentos que são utilizados dentro dos blocos PL/SQL para a geração ou leitura de dados. De forma
bem estruturada e clara, é possível não só ler as informações como também
Casa do Código
trabalhar com elas, alterando-as e formatando-as antes de inseri-las em tabelas ou gravá-las em arquivo.
Algumas premissas devem ser observadas antes de utilizar este recurso. A
primeira delas é ter privilégio para executar o pacote utl_file. A segunda
premissa faz referência a como o utl_file faz a comunicação entre o banco
de dados e o sistema operacional, para obter acesso aos diretórios do servidor
onde serão gravados ou lidos os arquivos com os dados.
O banco de dados Oracle possui uma série de parametrizações que garante seu funcionamento. Estes parâmetros podem ser visualizados através
da view v$parameter. Esta view lista todos os parâmetros do banco de
dados Oracle. Um destes parâmetros é utl_file_dir, responsável por informar ao utl_file a quais diretórios ele tem acesso no servidor. A partir
daí, o pacote utl_file só terá acesso em gravar e ler arquivos nestes diretórios. Esses diretórios não necessitam estar no mesmo servidor do banco
de dados, entretanto, através de algum compartilhamento, os dois precisam
enxergar um ao outro.
As opções de configuração deste parâmetro são:
• utl_file_dir=C:\sistema\ERP: indica um diretório específico
para a gravação e leitura de arquivos (compatível com sistema Windows).
• utl_file_dir=/ora/dat: indica um diretório específico para a
gravação e leitura de arquivos (compatível com sistema Unix).
• utl_file_dir=C:\sistema\ERP, /ora/dat: indica vários diretórios, separados por vírgula, para a gravação e leitura de arquivos.
• utl_file_dir=* : indica que a gravação ou leitura de arquivos pode
ser realizada em todos os diretórios disponíveis no servidor.
Nota: mesmo que os diretórios já estejam devidamente configurados
para o parâmetro utl_file_dir, as permissões de acesso aos diretórios no nível de servidor também precisam ser realizadas.
366
Casa do Código
Capítulo 22. Pacote utl_file
Contudo, esta configuração em nível de parâmetro de banco de dados
é meio inconveniente, pois o DBA para alterar esta definição precisa parar o banco de dados para realizá-la. Nem todos os parâmetros do banco
de dados Oracle necessitam uma parada do sistema, mas para o parâmetro
utl_file_dir é obrigatório que isto seja feito. Cada vez que o utl_file
necessita acessar um diretório diferente é necessário realizar todo este trabalho.
Para evitar isto, a partir de versões mais novas do banco de dados a Oracle
disponibilizou um recurso chamado directory com o qual é possível criar
um objeto no banco de dados e apontá-lo para um diretório do servidor, sem
a necessidade de alterarmos isso via parâmetro de banco. Com isto, o trabalho
ficou muito mais simples, inclusive, não exige conhecimentos específicos de
DBA.
Desta forma, antes de tudo, vamos aprender como se cria um objeto
directory, para utilizarmos em nossa aplicação utl_file.
❙◗▲❃ ❝r❡❛t❡ ❞✐r❡❝t♦r② ❞✐r❴♣r✐♥❝✐♣❛❧ ❛s ✬❈✿❭t♠♣❭❛rq✉✐✈♦s✬❀
❉✐r❡tór✐♦ ❝r✐❛❞♦✳
❙◗▲❃
Usamos o comando create directory para criar um objeto que
aponte para o diretório onde queremos gravar ou ler determinados arquivos. Em seguida, informamos um nome para o objeto. Este é o nome que
será utilizado dentro dos nossos programas. Seguindo a expressão as vem o
caminho referente ao diretório. Para nossos exemplos usaremos este recurso.
Além de criamos o objeto, precisamos dar privilégios de acesso aos usuários do banco de dados. Caso queria disponibilizar acesso para todos os usuários do banco, dê privilégios através do usuário public.
❙◗▲❃ ❣r❛♥t r❡❛❞✱ ✇r✐t❡ ♦♥ ❞✐r❡❝t♦r② ❞✐r❴♣r✐♥❝✐♣❛❧ t♦ ❚❙◗▲❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃
367
Casa do Código
Atenção: para dar acesso ao objeto directory, é necessário estar
conectado com o usuário system, que é o usuário administrador do
banco de dados Oracle.
Para ver os objetos directory cadastrados, use o comando select:
❙◗▲❃ s❡❧❡❝t ✯
✷ ❢r♦♠ ❛❧❧❴❞✐r❡❝t♦r✐❡s
✸ ✇❤❡r❡ ❞✐r❡❝t♦r②❴♥❛♠❡ ❂ ✬❉■❘❴P❘■◆❈■P❆▲✬❀
❖❲◆❊❘ ❉■❘❊❈❚❖❘❨❴◆❆▼❊
❉■❘❊❈❚❖❘❨❴P❆❚❍
✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❙❨❙
❉■❘❴P❘■◆❈■P❆▲
❈✿❭t♠♣❭❛rq✉✐✈♦s
❙◗▲❃
Para alterar um objeto directory, utilizamos o comando replace.
Através dele podemos alterar o caminho do diretório.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ❞✐r❡❝t♦r② ❞✐r❴♣r✐♥❝✐♣❛❧ ❛s ✬❈✿❭t♠♣❭✬❀
❉✐r❡tór✐♦ ❝r✐❛❞♦✳
❙◗▲❃
Para dar privilégios de execução do utl_file é necessário estar conectado com o usuário sys.
❙◗▲❃ ❣r❛♥t ❡①❡❝✉t❡ ♦♥ ❯❚▲❴❋■▲❊ t♦ ❚❙◗▲❀
❈♦♥❝❡ssã♦ ❜❡♠✲s✉❝❡❞✐❞❛✳
❙◗▲❃
Nota: para conectar com o usuário sys utilize o comando concc
sys/<senha>@<string_banco> as sysdba;.
368
Casa do Código
Capítulo 22. Pacote utl_file
Muito bem. Agora já criamos nosso directory e já concedemos privilégio para o usuário. Vamos colocar a mão na massa. Para trabalhar com
arquivos, precisamos conhecer um pouco sobre as funções e procedimentos
que fazem parte deste pacote. Além disso, precisamos conhecer as exceções
que podem ser geradas em caso de erros.
Na sequência, veja funções e procedimentos no uso do utl_file.
fclose
Fecha o arquivo. Exemplo:
♣r♦❝❡❞✉r❡ ❢❝❧♦s❡✭❢✐❧❡ ✐♥ ♦✉t ❢✐❧❡❴t②♣❡✮❀
Onde: file é o nome do arquivo lido ou gerado.
fclose_all
Fecha todos os arquivos. Exemplo:
♣r♦❝❡❞✉r❡ ❢❝❧♦s❡❴❛❧❧❀
Neste caso todos os arquivos aberto serão fechados.
fflush
Descarrega todos os dados em buffer para serem gravados em disco imediatamente. Exemplo:
♣r♦❝❡❞✉r❡ ❢❢❧✉s❤✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✮❀
Onde: file é o nome do arquivo lido ou gerado.
fopen
Abre o arquivo. Exemplo:
❢✉♥❝t✐♦♥ ❢♦♣❡♥✭❧♦❝❛t✐♦♥ ✐♥ ✈❛r❝❤❛r✷✱
❢✐❧❡♥❛♠❡ ✐♥ ✈❛r❝❤❛r✷✱
♦♣❡♥♠♦❞❡ ✐♥ ✈❛r❝❤❛r✷✮
r❡t✉r♥ ❢✐❧❡❴t②♣❡❀✪✪
369
Casa do Código
Onde: location é o nome do diretório onde se encontra o arquivo ou
onde o arquivo deve ser gerado. filename é o nome do arquivo a ser lido
ou gerado. openmode indica qual modo deve ser aplicado no arquivo. R =
Read (ler), W = Write (escrever) ou A = Append (adicionar).
❢✉♥❝t✐♦♥ ❢♦♣❡♥✭❧♦❝❛t✐♦♥ ✐♥ ✈❛r❝❤❛r✷✱
❢✐❧❡♥❛♠❡ ✐♥ ✈❛r❝❤❛r✷✱
♦♣❡♥♠♦❞❡ ✐♥ ✈❛r❝❤❛r✷✱
♠❛①❴❧✐♥❡s✐③❡ ✐♥ ❜✐♥❛r②❴✐♥t❡❣❡r✮ r❡t✉r♥ ❢✐❧❡❴t②♣❡❀
Onde: location é o nome do diretório onde se encontra o arquivo
ou onde o arquivo deve ser gerado. filename nome do arquivo a ser lido
ou gerado. openmode indica qual modo deve ser aplicado no arquivo. R =
Read (ler), W = Write (escrever) ou A = Append (adicionar). max_linesize
permite especificar o tamanho máximo de linha. O intervalo permitido é de
1 até 32.767. Se você omitir esse parâmetro, o padrão 1.023 é usado.
get_line
Lê uma linha de um arquivo. Exemplo:
♣r♦❝❡❞✉r❡ ❣❡t❴❧✐♥❡✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✱
❜✉❢❢❡r ♦✉t ✈❛r❝❤❛r✷✮❀
Onde: file é o nome do arquivo onde a linha deve ser lida. buffer é
o lugar onde o conteúdo lido da linha deve ser inserido.
is_open
Verifica se um arquivo está aberto. Exemplo:
♣r♦❝❡❞✉r❡ ✐s❴♦♣❡♥✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✮ r❡t✉r♥ ❜♦♦❧❡❛♥❀
Onde: file é o nome do arquivo que deve ser verificado.
new_line
Grava um caractere newline em um arquivo. Exemplo:
370
Casa do Código
Capítulo 22. Pacote utl_file
♣r♦❝❡❞✉r❡ ♥❡✇❴❧✐♥❡✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✱
❧✐♥❡s ✐♥ ♥❛t✉r❛❧ ✿❂ ✶✮❀
Onde: file é o nome do arquivo que deve receber a nova linha. lines
é o número total de caracteres newline que você quer gravar no arquivo. O
padrão é gravar uma newline nova. Este argumento é opcional.
put
Grava uma string de caracteres em um arquivo, mas não coloca uma newline depois dela. Exemplo:
♣r♦❝❡❞✉r❡ ♣✉t✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✱
❜✉❢❢❡r ✐♥ ✈❛r❝❤❛r✷✮❀
Onde: file é o nome do arquivo que deve receber o conteúdo. buffer
é o conteúdo a ser gravado no arquivo.
put_line
Grava uma linha em um arquivo. Exemplo:
♣r♦❝❡❞✉r❡ ♣✉t❴❧✐♥❡✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✱
❜✉❢❢❡r ✐♥ ✈❛r❝❤❛r✷✮❀
Onde: file é o nome do arquivo que deve receber o conteúdo. buffer
contém o texto que você deseja gravar no arquivo. O número máximo de
caracteres que você pode gravar usando uma chamada se limita ao tamanho
de linha que você especificou na chamada de fopen e tem como padrão 1.023.
putf
Formata e grava saída. Essa é uma imitação bruta do procedimento
PRINTF() do C. Exemplo:
♣r♦❝❡❞✉r❡ ♣✉t❢✭❢✐❧❡ ✐♥ ❢✐❧❡❴t②♣❡✱
❢♦r♠❛t ✐♥ ✈❛r❝❤❛r✷✱
❛r❣✶ ✐♥ ✈❛r❝❤❛r✷ ❞❡❢❛✉❧t ♥✉❧❧✱
❛r❣✷ ✐♥ ✈❛r❝❤❛r✷ ❞❡❢❛✉❧t ♥✉❧❧✱
371
Casa do Código
❛r❣✸ ✐♥ ✈❛r❝❤❛r✷ ❞❡❢❛✉❧t ♥✉❧❧✱
❛r❣✹ ✐♥ ✈❛r❝❤❛r✷ ❞❡❢❛✉❧t ♥✉❧❧✱
❛r❣✺ ✐♥ ✈❛r❝❤❛r✷ ❞❡❢❛✉❧t ♥✉❧❧✮❀
Onde: file é o nome do arquivo que receberá o conteúdo. format
representa a string que você deseja gravar no arquivo. arg1 ao arg5 são
argumentos opcionais contendo os valores que são substituídos na string de
formato antes dela ser gravada no arquivo.
Exceções de fclose e fclose_all
• utl_file.invalid_filehandle: você passou um handle de arquivo que não representava um arquivo aberto.
• utl_file.write_error: o sistema operacional não pode gravar no
arquivo.
• utl_file.internal_error: um erro interno ocorreu.
Exceções de fopen
• utl_file.invalid_path: o diretório não é válido. Você deve verificar em utl_file_dir.
• utl_file.invalid_mode: um modo inválido foi especificado. O
modo open deve ser R, W ou A.
• utl_file.invalid_operation: o arquivo não pode ser aberto por
algum outro motivo. Verifique se o proprietário do software do Oracle
tem acesso ao diretório (isso pode ser uma questão de permissão) e
entre em contato com o administrador do seu banco de dados para
obter ajuda.
• utl_file.internal_error: um erro interno ocorreu.
372
Casa do Código
Capítulo 22. Pacote utl_file
Exceções de get_line
• utl_file.invalid_filehandle: você passou handle de arquivo
inválido. Possivelmente você esqueceu de abrir o arquivo primeiro.
• utl_file.invalid_operation: o arquivo não está aberto para leitura (modo R), ou existem problemas com as permissões de arquivo.
• utl_file.value_error: o buffer não é suficientemente longo para
conter a linha que está sendo lida do arquivo. O tamanho do buffer é
aumentado.
• utl_file.no_data_found: o final do arquivo foi atingido.
• utl_file.internal_error: ocorreu um erro interno do sistema
utl_file.
• utl_file.read_error: ocorreu um erro do sistema operacional
durante a leitura do arquivo.
Exceções de put, put_line, putf e fflush
• utl_file.invalid_filehandle: você usou um handle de arquivo
inválido. Essa exceção pode ser levantada quando você esquecer de
abrir o arquivo.
• utl_file.invalid_operation: você tentou gravar em um arquivo que não estava aberto para gravação (modo W ou A).
• utl_file.write_error: ocorreu um erro de sistema operacional,
tal como um erro de disco cheio, ao tentar gravar em um arquivo.
• utl_file.internal_error: ocorreu um erro interno.
Agora vamos ver um exemplo onde vamos ler os registros da tabela emp
e dept e gerar um arquivo para ser gravado no diretório definido em nosso
directory. Vamos gravar as informações no arquivo de forma linear e separando as informações por ponto e vírgula.
373
Casa do Código
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❛✳❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❡♠♣♥♦✱ ❡♥❛♠❡
✹
❢r♦♠ ❞❡♣t ❛
✺
✱❡♠♣ ❜
✻
✇❤❡r❡ ❛✳❞❡♣t♥♦ ❂ ❜✳❞❡♣t♥♦
✼
♦r❞❡r ❜② ❛✳❞❡♣t♥♦❀
✽
r✶ ❝✶✪r♦✇t②♣❡❀
✾
✲✲
✶✵
♠❡✉❴❛rq✉✐✈♦ ✉t❧❴❢✐❧❡✳❢✐❧❡❴t②♣❡❀
✶✶
✲✲
✶✷ ❇❊●■◆
✶✸
✲✲
✶✹
♠❡✉❴❛rq✉✐✈♦ ✿❂ ✉t❧❴❢✐❧❡✳❢♦♣❡♥✭✬❉■❘❴P❘■◆❈■P❆▲✬✱
✬❡♠♣r❡❣❛❞♦s✳t①t✬✱ ✬✇✬✮❀
✶✺
✲✲
✶✻
♦♣❡♥ ❝✶❀
✶✼
✲✲
✶✽
❧♦♦♣
✶✾
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✷✵
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✷✶
✉t❧❴❢✐❧❡✳♣✉t❴❧✐♥❡✭♠❡✉❴❛rq✉✐✈♦✱ r✶✳❞❡♣t♥♦⑤⑤✬❀✬⑤⑤
r✶✳❞♥❛♠❡⑤⑤✬❀✬⑤⑤
✷✷
✷✸
r✶✳❡♠♣♥♦⑤⑤✬❀✬⑤⑤
✷✹
r✶✳❡♥❛♠❡✮❀
✷✺
❡♥❞ ❧♦♦♣❀
✷✻
✲✲
✷✼
❝❧♦s❡ ❝✶❀
✷✽
✲✲
✷✾
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✵
✲✲
✸✶ ❡①❝❡♣t✐♦♥
✸✷
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♣❛t❤ t❤❡♥
✸✸
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❈❛♠✐♥❤♦ ♦✉ ♥♦♠❡ ❞♦ ❛rq✉✐✈♦
✐♥✈á❧✐❞♦✬✮❀
✸✺
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♠♦❞❡ t❤❡♥
✸✻
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬▼♦❞♦ ❞❡ ❛❜❡rt✉r❛ ✐♥✈á❧✐❞♦✬✮❀
374
Casa do Código
Capítulo 22. Pacote utl_file
✸✽ ❡♥❞❀
✸✾ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Analisando o programa, vemos que na linha 10 declaramos uma variável
do tipo utl_file.file_type que vai ser o ponteiro (handle) para o nosso
arquivo físico. Quando isso é feito, o Oracle monta uma estrutura de arquivo
em memória referente ao arquivo físico com que iremos trabalhar. Já na linha
14, atribuímos à variável declarada à abertura do arquivo passando como parâmetro o directory criado anteriormente, que faz referência ao local do
diretório onde o arquivo deve ser gravado, o nome do arquivo e, por último,
o modo, que neste caso é modo de escrita, representado por W. Quando executamos um fopen utilizando o modo escrita, caso não exista o arquivo ele
o cria.
Na linha 21, utilizamos a chamada put_line para inserir linhas ao arquivo. Neste caso, estamos concatenando uma série de informações vindas
das tabelas emp e dept e enviando para o arquivo. Após o termino da leitura das tabelas, ou seja, no final do cursor, fechamos o arquivo na linha 29.
Note que entre as linhas 31 a 37 estão tratadas as possíveis exceções relacionadas ao pacote utl_file. Segue o resultado:
375
Casa do Código
Fig. 22.1: Arquivo gerado através do pacote utl_file
Após termos visto o programa que gera as informações e as joga em um
arquivo, vamos ver a contrapartida onde lemos o arquivo gerado e mostramos
as informações na tela.
376
Casa do Código
Capítulo 22. Pacote utl_file
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
♠❡✉❴❛rq✉✐✈♦ ✉t❧❴❢✐❧❡✳❢✐❧❡❴t②♣❡❀
✹
❧✐♥❤❛
✈❛r❝❤❛r✷✭✸✷✵✵✵✮❀
✺
✲✲
✻
✇❞❡♣t♥♦ ❡♠♣✳❞❡♣t♥♦✪t②♣❡❀
✼
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✽
✇❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✾
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✶✵
✲✲
✶✶ ❜❡❣✐♥
✶✷
✲✲
✶✸
♠❡✉❴❛rq✉✐✈♦ ✿❂ ✉t❧❴❢✐❧❡✳❢♦♣❡♥✭✬❉■❘❴P❘■◆❈■P❆▲✬✱
✬❡♠♣r❡❣❛❞♦s✳t①t✬✱ ✬r✬✮❀
✶✹
✲✲
✶✺
❧♦♦♣
✶✻
✲✲
✶✼
✉t❧❴❢✐❧❡✳❣❡t❴❧✐♥❡✭♠❡✉❴❛rq✉✐✈♦✱❧✐♥❤❛✮❀
✶✽
✲✲
✶✾
❡①✐t ✇❤❡♥ ❧✐♥❤❛ ✐s ♥✉❧❧❀
✷✵
✲✲
✷✶
✇❞❡♣t♥♦ ✿❂
rtr✐♠✭s✉❜str✭❧✐♥❤❛✱✶✱✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✶✮ ✲✶✮✮✮❀
✷✷
✷✸
✇❞♥❛♠❡ ✿❂
rtr✐♠✭s✉❜str✭❧✐♥❤❛✱✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✶✮ ✰ ✶✮
✷✹
✱✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✷✮ ✲✶✮ ✲
✷✺
✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✶✮ ✰ ✭✶ ✲✶✮✮✮✮❀
✷✻
✇❡♠♣♥♦ ✿❂
✷✼
rtr✐♠✭s✉❜str✭❧✐♥❤❛✱✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✷✮ ✰ ✶✮
✷✽
✱✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✸✮ ✲✶✮ ✲
✷✾
✭✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✷✮ ✰ ✭✶ ✲✶✮✮✮✮❀
✸✵
✇❡♥❛♠❡ ✿❂ rtr✐♠✭rtr✐♠✭s✉❜str✭❧✐♥❤❛✱✭
✸✶
✐♥str✭❧✐♥❤❛✱✬❀✬✱✶✱✸✮ ✰ ✶✮✮✱❝❤r✭✶✸✮✮✮❀
✸✷
✲✲
✸✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣t♥♦✮❀
✸✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞♥❛♠❡✮❀
377
Casa do Código
✸✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✬⑤⑤✇❡♠♣♥♦✮❀
✸✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ✬⑤⑤✇❡♥❛♠❡✮❀
✸✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❴✬✮❀
✸✽
✲✲
✸✾
❡♥❞ ❧♦♦♣❀
✹✵
✲✲
✹✶
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✹✷
✲✲
✹✸ ❡①❝❡♣t✐♦♥
✹✹
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✹✺
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✹✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❋✐♥❛❧ ❞♦ ❆rq✉✐✈♦✳✬✮❀
✹✼
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♣❛t❤ t❤❡♥
✹✽
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✹✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❈❛♠✐♥❤♦ ♦✉ ♥♦♠❡ ❞♦ ❛rq✉✐✈♦
✐♥✈á❧✐❞♦✬✮❀
✺✵
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♠♦❞❡ t❤❡♥
✺✶
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✺✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬▼♦❞♦ ❞❡ ❛❜❡rt✉r❛ ✐♥✈á❧✐❞♦✬✮❀
✺✸ ❡♥❞❀
✺✹ ✴
Vamos analisar o código do programa. Na linha 3, declaramos uma variável do tipo utl_file.file_type que vai ser o ponteiro para o nosso
arquivo físico. Na linha criamos uma variável chamada linha que receberá
os dados de cada linha vinda do arquivo. Abrimos o arquivo através da função
fopen utilizando o modo R (leitura). Já na linha 17, utilizamos a chamada de
procedimento get_lines que lê uma linha (a primeira) do arquivo e guarda
seu valor dentro da variável linha. Neste caso, ele busca todo o conteúdo da
linha e joga dentro da variável, ou seja, todos os valores da linha concatenados
por ponto e vírgula.
Na linha 19, temos o seguinte código exit when linha is null.
Conforme visto nas exceções, vimos que ao chegar ao final de um arquivo
a exceção no_data_found é acionada, ou seja, quando não houver mais
linhas para ler, é gerada uma exceção informando que não há mais linhas
para serem lidas no arquivo. Contudo, dependendo o sistema operacional
e/ou da codificação do arquivo gerado, pode acontecer, no caso de termos
378
Casa do Código
Capítulo 22. Pacote utl_file
um caractere enter no final do arquivo, de o utl_file ler este caractere
e considerá-lo como uma linha. Caso o programa não esteja tratando esta
situação, erros podem ocorrer.
Desta forma, a linha 19 serve para tratar este tipo de situação. Caso a
exceção no_data_found não for acionada, esta cláusula garante a saída do
loop. Mas atenção: isso serve para arquivos que não estejam considerando
linhas em branco em sua estrutura. Caso linhas em branco façam parte da
formatação dos dados, esta linha não deve ser colocada. Depois, nas linhas
21 a 31 utilizamos as funções substr e instr para separar os dados, tendo
como base o caractere ponto e vírgula. Finalizamos a leitura do arquivo na
linha 41. Note que neste exemplo tratamos a exceção no_data_found, na
linha 44.
Veja o resultado.
❈ó❞✳
◆♦♠❡
❈ó❞✳
◆♦♠❡
❴
❈ó❞✳
◆♦♠❡
❈ó❞✳
◆♦♠❡
❴
❈ó❞✳
◆♦♠❡
❈ó❞✳
◆♦♠❡
❴
❈ó❞✳
◆♦♠❡
❈ó❞✳
◆♦♠❡
❴
❈ó❞✳
◆♦♠❡
❈ó❞✳
◆♦♠❡
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆●
❊♠♣r❡❣❛❞♦✿ ✼✼✽✷
❊♠♣r❡❣❛❞♦✿ ❈▲❆❘❑
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆●
❊♠♣r❡❣❛❞♦✿ ✼✾✸✹
❊♠♣r❡❣❛❞♦✿ ▼■▲▲❊❘
❉❡♣❛rt❛♠❡♥t♦✿ ✶✵
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆●
❊♠♣r❡❣❛❞♦✿ ✼✽✸✾
❊♠♣r❡❣❛❞♦✿ ❑■◆●
❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❊♠♣r❡❣❛❞♦✿ ✼✻✾✽
❊♠♣r❡❣❛❞♦✿ ❇▲❆❑❊
❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❊♠♣r❡❣❛❞♦✿ ✼✾✸✺
❊♠♣r❡❣❛❞♦✿ P❆❯▲
379
Casa do Código
❴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✾✵✵
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ❏❆▼❊❙
❴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✽✹✹
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ❚❯❘◆❊❘
❴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✻✺✹
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ▼❆❘❚■◆
❴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✺✷✶
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ❲❆❘❉
❴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✸✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✹✾✾
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ❆▲▲❊◆
❴
❋✐♥❛❧ ❞♦ ❆rq✉✐✈♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Por curiosidade, vamos apresentar o mesmo exemplo de geração e leitura
de arquivo utilizando a separação de informação não por ponto e vírgula, mas
sim, por número de caracteres fixos. Este método visa termos número fixos
para o tamanho das colunas. Vale lembrar que não muda em nada a forma
de utilizar o pacote utl_file. É apenas para mostrar uma forma diferente,
porém muito utilizada, de gerar layouts diferentes para arquivos textos
380
Casa do Código
Capítulo 22. Pacote utl_file
Geração do arquivo:
❙◗▲❃ ❞❡❝❧❛r❡
✷
❝✉rs♦r ❝✶ ✐s
✸
s❡❧❡❝t ❛✳❞❡♣t♥♦✱ ❞♥❛♠❡✱ ❡♠♣♥♦✱ ❡♥❛♠❡
✹
❢r♦♠ ❞❡♣t ❛
✺
✱❡♠♣ ❜
✻
✇❤❡r❡ ❛✳❞❡♣t♥♦ ❂ ❜✳❞❡♣t♥♦
✼
♦r❞❡r ❜② ❛✳❞❡♣t♥♦❀
✽
r✶ ❝✶✪r♦✇t②♣❡❀
✾
✲✲
✶✵
♠❡✉❴❛rq✉✐✈♦ ✉t❧❴❢✐❧❡✳❢✐❧❡❴t②♣❡❀
✶✶
✲✲
✶✷ ❇❊●■◆
✶✸
✲✲
✶✹
♠❡✉❴❛rq✉✐✈♦ ✿❂ ✉t❧❴❢✐❧❡✳❢♦♣❡♥✭✬❉■❘❴P❘■◆❈■P❆▲✬✱
✬❡♠♣r❡❣❛❞♦s✳t①t✬✱ ✬✇✬✮❀
✶✺
✲✲
✶✻
♦♣❡♥ ❝✶❀
✶✼
✲✲
✶✽
❧♦♦♣
✶✾
❢❡t❝❤ ❝✶ ✐♥t♦ r✶❀
✷✵
❡①✐t ✇❤❡♥ ❝✶✪♥♦t❢♦✉♥❞❀
✷✶
✉t❧❴❢✐❧❡✳♣✉t❴❧✐♥❡✭♠❡✉❴❛rq✉✐✈♦✱ r♣❛❞✭r✶✳❞❡♣t♥♦✱✷✱✬ ✬✮ ⑤⑤
r♣❛❞✭r✶✳❞♥❛♠❡✱✶✹✱✬ ✬✮ ⑤⑤
✷✷
✷✸
r♣❛❞✭r✶✳❡♠♣♥♦✱✹✱✬ ✬✮ ⑤⑤
r♣❛❞✭r✶✳❡♥❛♠❡✱✶✵✱✬ ✬✮
✷✹
✷✺
✮❀
✷✻
❡♥❞ ❧♦♦♣❀
✷✼
✲✲
✷✽
❝❧♦s❡ ❝✶❀
✷✾
✲✲
✸✵
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✶
✲✲
✸✷ ❡①❝❡♣t✐♦♥
✸✸
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♣❛t❤ t❤❡♥
✸✹
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❈❛♠✐♥❤♦ ♦✉ ♥♦♠❡ ❞♦ ❛rq✉✐✈♦
✐♥✈á❧✐❞♦✬✮❀
381
Casa do Código
✸✻
✸✼
✸✽
✸✾
✹✵
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♠♦❞❡ t❤❡♥
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬▼♦❞♦ ❞❡ ❛❜❡rt✉r❛ ✐♥✈á❧✐❞♦✬✮❀
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Leitura do arquivo:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
♠❡✉❴❛rq✉✐✈♦ ✉t❧❴❢✐❧❡✳❢✐❧❡❴t②♣❡❀
✹
❧✐♥❤❛
✈❛r❝❤❛r✷✭✸✷✵✵✵✮❀
✺
✲✲
✻
✇❞❡♣t♥♦ ❡♠♣✳❞❡♣t♥♦✪t②♣❡❀
✼
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✽
✇❡♠♣♥♦ ❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✾
✇❡♥❛♠❡ ❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✶✵
✲✲
✶✶ ❜❡❣✐♥
✶✷
✲✲
✶✸
♠❡✉❴❛rq✉✐✈♦ ✿❂ ✉t❧❴❢✐❧❡✳❢♦♣❡♥✭✬❉■❘❴P❘■◆❈■P❆▲✬✱
✬❡♠♣r❡❣❛❞♦s✳t①t✬✱ ✬r✬✮❀
✶✹
✲✲
✶✺
❧♦♦♣
✶✻
✲✲
✶✼
✉t❧❴❢✐❧❡✳❣❡t❴❧✐♥❡✭♠❡✉❴❛rq✉✐✈♦✱❧✐♥❤❛✮❀
✶✽
✲✲
✶✾
❡①✐t ✇❤❡♥ ❧✐♥❤❛ ✐s ♥✉❧❧❀
✷✵
✲✲
✷✶
✇❞❡♣t♥♦ ✿❂ rtr✐♠✭❧tr✐♠✭s✉❜str✭❧✐♥❤❛✱✶✱✷✮✮✮❀
✷✷
✇❞♥❛♠❡ ✿❂ rtr✐♠✭❧tr✐♠✭s✉❜str✭❧✐♥❤❛✱✸✱✶✹✮✮✮❀
✷✸
✇❡♠♣♥♦ ✿❂ rtr✐♠✭❧tr✐♠✭s✉❜str✭❧✐♥❤❛✱✶✼✱✹✮✮✮❀
✷✹
✇❡♥❛♠❡ ✿❂ rtr✐♠✭❧tr✐♠✭s✉❜str✭❧✐♥❤❛✱✷✶✱✶✵✮✮✮❀
✷✺
✲✲
✷✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞❡♣t♥♦✮❀
✷✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞♥❛♠❡✮❀
382
Casa do Código
Capítulo 22. Pacote utl_file
✷✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✬⑤⑤✇❡♠♣♥♦✮❀
✷✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ✬⑤⑤✇❡♥❛♠❡✮❀
✸✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❴✬✮❀
✸✶
✲✲
✸✷
❡♥❞ ❧♦♦♣❀
✸✸
✲✲
✸✹
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✺
✲✲
✸✻ ❡①❝❡♣t✐♦♥
✸✼
✇❤❡♥ ♥♦❴❞❛t❛❴❢♦✉♥❞ t❤❡♥
✸✽
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✸✾
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬❋✐♥❛❧ ❞♦ ❆rq✉✐✈♦✳✬✮❀
✹✵
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♣❛t❤ t❤❡♥
✹✶
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✹✷
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭
✬❈❛♠✐♥❤♦ ♦✉ ♥♦♠❡ ❞♦ ❛rq✉✐✈♦ ✐♥✈á❧✐❞♦✬✮❀
✹✸
✇❤❡♥ ✉t❧❴❢✐❧❡✳✐♥✈❛❧✐❞❴♠♦❞❡ t❤❡♥
✹✹
✉t❧❴❢✐❧❡✳❢❝❧♦s❡✭♠❡✉❴❛rq✉✐✈♦✮❀
✹✺
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡ ✭✬▼♦❞♦ ❞❡ ❛❜❡rt✉r❛ ✐♥✈á❧✐❞♦✬✮❀
✹✻ ❡♥❞❀
✹✼ ✴
❈ó❞✳ ❉❡♣❛rt❛♠❡♥t♦✿ ✶✵
◆♦♠❡ ❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆●
❈ó❞✳ ❊♠♣r❡❣❛❞♦✿ ✼✼✽✷
◆♦♠❡ ❊♠♣r❡❣❛❞♦✿ ❈▲❆❘❑
✳✳✳✳
❴
❋✐♥❛❧ ❞♦ ❆rq✉✐✈♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Conforme pôde ser visto nesse exemplo, a leitura toma como base, posições fixas que indicam a localização exata de cada informação na linha,
extraindo-as.
383
Capítulo 23
SQL dinâmico
Na maioria das vezes, trabalharemos com comandos SQL previamente definidos dentro de nossos programas. Geralmente, o corpo dos comandos não
se altera, apenas os parâmetros que passamos a eles. Podemos ter o mesmo
comando SQL diversas vezes dentro do nosso programa, mas mediante a passagem de parâmetros com valores distintos podemos ter resultados diferentes.
Contudo, pode acontecer de, dependendo da situação, não termos estes
comandos SQL definidos, ou seja, mediante determinadas ações talvez precisemos modificar a estrutura do comando SQL para atender as necessidades,
mas com um detalhe: tudo isso em tempo de execução.
Para isso, a linguagem PL/SQL disponibiliza um recurso chamado de SQL
dinâmico que nos dá a possibilidade de executar um comando SQL a partir de
uma string, ou seja, o comando passa a ser uma string de caracteres armazenados em uma variável. Através de um comando, a variável é lida e o SQL que
está dentro dela é executado. Isso é feito através do procedimento execute
Casa do Código
immediate. Por meio deste procedimento, podemos executar comandos de
insert, delete, update, select, create, alter, drop, bem como
executar procedimentos e funções. É possível também realizar passagem de
parâmetros para esses comandos. Veja os exemplos a seguir.
Uso com insert:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇✐♥s❡rt❴❡♠♣ ✈❛r❝❤❛r✷✭✹✵✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✹
✇✐♥s❡rt❴❞❡♣t ✈❛r❝❤❛r✷✭✹✵✵✵✮ ❞❡❢❛✉❧t ♥✉❧❧❀
✺
✲✲
✻
✇❡♠♣♥♦
❡♠♣✳❡♠♣♥♦✪t②♣❡❀
✼
✇❡♥❛♠❡
❡♠♣✳❡♥❛♠❡✪t②♣❡❀
✽
✇❥♦❜
❡♠♣✳❥♦❜✪t②♣❡❀
✾
✇♠❣r
❡♠♣✳♠❣r✪t②♣❡❀
✶✵
✇❤✐r❡❞❛t❡ ❡♠♣✳❤✐r❡❞❛t❡✪t②♣❡❀
✶✶
✇s❛❧
❡♠♣✳s❛❧✪t②♣❡❀
✶✷
✇❝♦♠♠
❡♠♣✳❝♦♠♠✪t②♣❡❀
✶✸
✇❞❡♣t♥♦
❡♠♣✳❞❡♣t♥♦✪t②♣❡❀
✶✹
✲✲
✶✺ ❜❡❣✐♥
✶✻
✲✲
✶✼
✇❡♠♣♥♦
✿❂ ✾✾✾✾❀
✶✽
✇❡♥❛♠❡
✿❂ ✬❇❖◆❖✬❀
✶✾
✇❥♦❜
✿❂ ✬❙❆▲❊❙▼❆◆✬❀
✷✵
✇♠❣r
✿❂ ✼✻✾✽❀
✷✶
✇❤✐r❡❞❛t❡ ✿❂ ❙❨❙❉❆❚❊❀
✷✷
✇s❛❧
✿❂ ✶✵✵✵❀
✷✸
✇❝♦♠♠
✿❂ ✵❀
✷✹
✇❞❡♣t♥♦
✿❂ ✸✵❀
✷✺
✲✲
✷✻
✇✐♥s❡rt❴❡♠♣ ✿❂ ✬✐♥s❡rt ✐♥t♦ ❡♠♣ ✭ ❡♠♣♥♦
✷✼
✱❡♥❛♠❡
✷✽
✱❥♦❜
✷✾
✱♠❣r
✸✵
✱❤✐r❡❞❛t❡
✸✶
✱s❛❧
✸✷
✱❝♦♠♠
✸✸
✱❞❡♣t♥♦✮
386
Casa do Código
✸✹
✸✺
✸✻
✸✼
✸✽
✸✾
✹✵
✹✶
✹✷
✹✸
✹✹
✹✺
✹✻
✹✼
✹✽
✹✾
✺✵
✺✶
✺✷
Capítulo 23. SQL dinâmico
✈❛❧✉❡s ✭ ✿❡♠♣♥♦
✱✿❡♥❛♠❡
✱✿❥♦❜
✱✿♠❣r
✱✿❤✐r❡❞❛t❡
✱✿s❛❧
✱✿❝♦♠♠
✱✿❞❡♣t♥♦✮✬❀
✲✲
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✇✐♥s❡rt❴❡♠♣ ✉s✐♥❣ ✇❡♠♣♥♦
✱✇❡♥❛♠❡
✱✇❥♦❜
✱✇♠❣r
✱✇❤✐r❡❞❛t❡
✱✇s❛❧
✱✇❝♦♠♠
✱✇❞❡♣t♥♦❀
✲✲
✇✐♥s❡rt❴❞❡♣t ✿❂
✬✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭✿❞❡♣t♥♦✱ ✿❞♥❛♠❡✱ ✿❧♦❝✮✬❀
✺✸
✲✲
✺✹
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✇✐♥s❡rt❴❞❡♣t ✉s✐♥❣ ✾✾✱ ✬❘❍✬✱ ✬❇❘❆❙■▲✬❀
✺✺
✲✲
✺✻ ❡♥❞❀
✺✼ ✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo, na linha 26, temos a variável winsert_emp que recebe
como string o comando insert. Note que os valores que serão inseridos
(linha 34 a 41) estão representados por variáveis chamadas bind. Este tipo
de variável é caracterizado por iniciar com dois pontos antes do seu nome.
Quando declaramos uma variável do tipo bind a PL/SQL interpreta que algum valor deve ser informado para ela, em um dado momento. Caso este
valor não seja passado por parâmetro é aberto um prompt para que ele seja
digitado.
387
Casa do Código
Nas linhas 43 a 50, temos o comando execute immediate. Ele aparece
precedido da string ou variável referente ao comando que deve ser executado.
Caso parâmetros devam ser passados, utilizamos a cláusula using para isto.
Veja no exemplo, que estamos utilizando using para passar os parâmetros
para o comando insert, substituindo as variáveis bind. Esta substituição
acontece de forma sequencial.
Além da inserção de empregados, também temos, no mesmo bloco
PL/SQL, a inserção de departamentos. Embora bem parecido com a inserção de empregado, este exemplo serve para mostrar que os valores referentes aos parâmetros podem ser passados diretamente no comando execute
immediate. Veja o resultado na sequência:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✹✾✾
✼✺✷✶
✾✾✾✾
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✽✸✾
✼✽✹✹
✼✾✵✵
✼✾✸✹
✼✾✸✺
❊◆❆▼❊
✲✲✲✲✲✲✲
❆▲▲❊◆
❲❆❘❉
❇❖◆❖
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❑■◆●
❚❯❘◆❊❘
❏❆▼❊❙
▼■▲▲❊❘
P❆❯▲
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
❈❖▼▼
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✵✴✵✷✴✽✶
✶✻✵✵
✸✵✻
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✷✴✵✷✴✽✶
✶✷✺✵
✺✶✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✺✴✶✵✴✶✶
✶✵✵✵
✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✽✴✵✾✴✽✶
✶✷✺✵
✶✹✷✽
▼❆◆❆●❊❘
✼✽✸✾ ✵✶✴✵✺✴✽✶
✷✽✺✵
✷✽✺
▼❆◆❆●❊❘
✼✽✸✾ ✵✾✴✵✻✴✽✶
✷✹✺✵
✷✹✺
P❘❊❙■❉❊◆❚
✶✼✴✶✶✴✽✶
✺✵✵✵
✺✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✵✽✴✵✾✴✽✶
✶✺✵✵
✶✺✵
❈▲❊❘❑
✼✻✾✽ ✵✸✴✶✷✴✽✶
✾✺✵
✾✺
❈▲❊❘❑
✼✼✽✷ ✷✸✴✵✶✴✽✷
✶✸✵✵
✶✸✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✶✺✴✵✸✴✽✵
✶✵✵✵
✶✵✵
❉❊P❚◆❖ P❈❴❈❖▼❴❙❆▲
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✸✵
✶✾✱✶✷✺
✸✵
✹✵✱✽
✸✵
✸✵
✶✶✹✱✷✹
✸✵
✶✵
✶✵
✸✵
✶✵
388
Casa do Código
Capítulo 23. SQL dinâmico
✸✵
✶✵
✸✵
✶✵
✶✶ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✸✵
✹✵
✽✵
✾✵
✾✾
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❖P❊❘❆❚■❖◆❙
❙✫❊
❋■◆❆◆❈■❆▲
❘❍
▲❖❈
✲✲✲✲✲✲✲✲✲✲✲✲✲
❋▲❖❘■❉❆
❈❍■❈❆●❖
❇❖❙❚❖◆
❇❘❆❙■▲
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃ ❈❖▼▼■❚❀
❱❛❧✐❞❛çã♦ ❝♦♠♣❧❡t❛✳
❙◗▲❃
Uso com delete e update:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
❞❡❝❧❛r❡
✲✲
❜❡❣✐♥
✲✲
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬❞❡❧❡t❡ ❢r♦♠ ❡♠♣
✇❤❡r❡ ❡♠♣♥♦ ❂ ✿❡♠♣♥♦ ✬ ✉s✐♥❣ ✾✾✾✾❀
✲✲
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬✉♣❞❛t❡ ❞❡♣t s❡t ❧♦❝ ❂ ✿❧♦❝
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿❞❡♣♥t♦✬ ✉s✐♥❣ ✬❆❯❙❚❘❆▲■❆✬✱ ✾✾❀
✲✲
❡♥❞❀
✴
389
Casa do Código
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Nesse exemplo, estamos mostrando a exclusão e atualização de registros
via execute immediate. A seguir temos o resultado:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣❀
❊▼P◆❖
✲✲✲✲✲✲✲✲✲✲
✼✹✾✾
✼✺✷✶
✼✻✺✹
✼✻✾✽
✼✼✽✷
✼✽✸✾
✼✽✹✹
✼✾✵✵
✼✾✸✹
✼✾✸✺
❊◆❆▼❊
✲✲✲✲✲✲✲
❆▲▲❊◆
❲❆❘❉
▼❆❘❚■◆
❇▲❆❑❊
❈▲❆❘❑
❑■◆●
❚❯❘◆❊❘
❏❆▼❊❙
▼■▲▲❊❘
P❆❯▲
❏❖❇
▼●❘ ❍■❘❊❉❆❚❊
❙❆▲
❈❖▼▼
✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✵✴✵✷✴✽✶
✶✻✵✵
✸✵✻
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✷✴✵✷✴✽✶
✶✷✺✵
✺✶✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✷✽✴✵✾✴✽✶
✶✷✺✵
✶✹✷✽
▼❆◆❆●❊❘
✼✽✸✾ ✵✶✴✵✺✴✽✶
✷✽✺✵
✷✽✺
▼❆◆❆●❊❘
✼✽✸✾ ✵✾✴✵✻✴✽✶
✷✹✺✵
✷✹✺
P❘❊❙■❉❊◆❚
✶✼✴✶✶✴✽✶
✺✵✵✵
✺✵✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✵✽✴✵✾✴✽✶
✶✺✵✵
✶✺✵
❈▲❊❘❑
✼✻✾✽ ✵✸✴✶✷✴✽✶
✾✺✵
✾✺
❈▲❊❘❑
✼✼✽✷ ✷✸✴✵✶✴✽✷
✶✸✵✵
✶✸✵
❙❆▲❊❙▼❆◆
✼✻✾✽ ✶✺✴✵✸✴✽✵
✶✵✵✵
✶✵✵
❉❊P❚◆❖ P❈❴❈❖▼❴❙❆▲
✲✲✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲
✸✵
✶✾✱✶✷✺
✸✵
✹✵✱✽
✸✵
✶✶✹✱✷✹
✸✵
✶✵
✶✵
✸✵
✶✵
✸✵
✶✵
✸✵
✶✵
✶✵ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t❀
390
Casa do Código
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✸✵
✹✵
✽✵
✾✵
✾✾
Capítulo 23. SQL dinâmico
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❖P❊❘❆❚■❖◆❙
❙✫❊
❋■◆❆◆❈■❆▲
❘❍
▲❖❈
✲✲✲✲✲✲✲✲✲✲✲✲✲
❋▲❖❘■❉❆
❈❍■❈❆●❖
❇❖❙❚❖◆
❆❯❙❚❘❆▲■❆
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃ ❈❖▼▼■❚❀
❱❛❧✐❞❛çã♦ ❝♦♠♣❧❡t❛✳
❙◗▲❃
Uso com os comandos create e alter. execute immediate pode
ser usado também para a criação e alteração dinâmica de tabelas:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
❞❡❝❧❛r❡
✲✲
❜❡❣✐♥
✲✲
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬❝r❡❛t❡ t❛❜❧❡ ❢✉♥❝
✭❝❞❴❢✉♥❝ ♥✉♠❜❡r✱ ♥♠❴❢✉♥❝ ✈❛r❝❤❛r✷✭✺✵✮✮✬❀
✲✲
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬❛❧t❡r t❛❜❧❡ ❢✉♥❝
♠♦❞✐❢② ❝❞❴❢✉♥❝ ♥✉♠❜❡r ♥♦t ♥✉❧❧✬❀
✲✲
❡♥❞❀
✴
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ ❞❡s❝ ❢✉♥❝
◆♦♠❡
◆✉❧♦❄
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❈❉❴❋❯◆❈
◆❖❚ ◆❯▲▲
◆▼❴❋❯◆❈
❚✐♣♦
✲✲✲✲✲✲✲✲✲✲✲✲✲
◆❯▼❇❊❘
❱❆❘❈❍❆❘✷✭✺✵✮
❙◗▲❃
391
Casa do Código
Por meio do uso do execute immediate é possível retornar informações provenientes de comandos SQL. Veja este exemplo da execução de um
update:
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❛t✉❛❧✐③❛❴❞❡♣t ✈❛r❝❤❛r✷✭✷✵✵✵✮❀
✹
✲✲
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✻
✇❧♦❝❴r❡ ❞❡♣t✳❧♦❝✪t②♣❡❀
✼
✲✲
✽
✇❧♦❝
❞❡♣t✳❧♦❝✪t②♣❡
❞❡❢❛✉❧t ✬❈❍■▲❊✬❀
✾
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡ ❞❡❢❛✉❧t ✾✾❀
✶✵ ❜❡❣✐♥
✶✶
✲✲
✶✷
✇❛t✉❛❧✐③❛❴❞❡♣t ✿❂ ✬✉♣❞❛t❡ ❞❡♣t s❡t ❧♦❝ ❂ ✿✶
✇❤❡r❡ ❞❡♣t♥♦ ❂ ✿✷
✶✸
r❡t✉r♥✐♥❣ ❞♥❛♠❡✱ ❧♦❝ ✐♥t♦ ✿✸✱ ✿✹✬❀
✶✹
✲✲
✶✺
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✇❛t✉❛❧✐③❛❴❞❡♣t ✉s✐♥❣ ✇❧♦❝✱ ✇❞❡♣t♥♦
✶✻
✱♦✉t ✇❞♥❛♠❡✱ ♦✉t ✇❧♦❝❴r❡❀
✶✼
✲✲
✶✽
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬▲♦❝❛❧✐③❛çã♦ ❛t✉❛❧✐③❛❞❛ ♣❛r❛ ♦
❞❡♣❛rt❛♠❡♥t♦ ✬⑤⑤
✇❞♥❛♠❡⑤⑤✬ ✭▲♦❝✿ ✬⑤⑤✇❧♦❝⑤⑤✬✮✳✬✮❀
✶✾
✷✵
✲✲
✷✶ ❡♥❞❀
✷✷ ✴
▲♦❝❛❧✐③❛çã♦ ❛t✉❛❧✐③❛❞❛ ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ❘❍ ✭▲♦❝✿ ❈❍■▲❊✮✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✸✵
✹✵
392
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❖P❊❘❆❚■❖◆❙
▲❖❈
✲✲✲✲✲✲✲✲✲✲✲✲✲
❋▲❖❘■❉❆
❈❍■❈❆●❖
❇❖❙❚❖◆
Casa do Código
✽✵ ❙✫❊
✾✵ ❋■◆❆◆❈■❆▲
✾✾ ❘❍
Capítulo 23. SQL dinâmico
❈❍■▲❊
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Analisando esse exemplo, temos na linha 12 a variável watualiza_dept
recebendo a string referente ao comando update. Também é possível observar que, na linha 13, está incluída a cláusula returning seguida de dois campos, os quais serão o nosso retorno, seguida da cláusula into informando
duas variáveis bind, as quais receberão os valores retornados.
Uma observação importante, é que na linha 15 e 16, referentes ao comando
execute immediate, temos duas passagens de parâmetros do tipo in (entrada) e duas do tipo out (saída), sendo que estas duas últimas guardam
nosso retorno. Vale lembrar que quando não informado o tipo da variável na
cláusula using, por padrão, seu tipo será de entrada ( in).
Veja outro exemplo utilizando retorno de informação, mas agora com o
uso da cláusula returning também no execute immediate. Note que
através desta notação não necessitamos informar o tipo das variáveis de retorno.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇❛t✉❛❧✐③❛❴❞❡♣t ✈❛r❝❤❛r✷✭✷✵✵✵✮❀
✹
✲✲
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✻
✇❧♦❝❴r❡ ❞❡♣t✳❧♦❝✪t②♣❡❀
✼
✲✲
✽
✇❧♦❝
❞❡♣t✳❧♦❝✪t②♣❡
❞❡❢❛✉❧t ✬❆❘●❊◆❚■◆❆✬❀
✾
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡ ❞❡❢❛✉❧t ✾✾❀
✶✵ ❜❡❣✐♥
✶✶
✲✲
✶✷
✇❛t✉❛❧✐③❛❴❞❡♣t ✿❂ ✬✉♣❞❛t❡ ❞❡♣t s❡t ❧♦❝ ❂ ✿✶ ✇❤❡r❡
❞❡♣t♥♦ ❂ ✿✷
✶✸
r❡t✉r♥✐♥❣ ❞♥❛♠❡✱ ❧♦❝ ✐♥t♦ ✿✸✱ ✿✹✬❀
✶✹
✲✲
393
Casa do Código
✶✺
✶✻
✶✼
✶✽
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✇❛t✉❛❧✐③❛❴❞❡♣t ✉s✐♥❣ ✇❧♦❝✱ ✇❞❡♣t♥♦
r❡t✉r♥✐♥❣ ✐♥t♦ ✇❞♥❛♠❡✱ ✇❧♦❝❴r❡❀
✲✲
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬▲♦❝❛❧✐③❛çã♦ ❛t✉❛❧✐③❛❞❛ ♣❛r❛ ♦
❞❡♣❛rt❛♠❡♥t♦ ✬⑤⑤
✶✾
✇❞♥❛♠❡⑤⑤✬ ✭▲♦❝✿ ✬⑤⑤✇❧♦❝⑤⑤✬✮✳✬✮❀
✷✵
✲✲
✷✶ ❡♥❞❀
✷✷ ✴
▲♦❝❛❧✐③❛çã♦ ❛t✉❛❧✐③❛❞❛ ♣❛r❛ ♦ ❞❡♣❛rt❛♠❡♥t♦ ❘❍ ✭▲♦❝✿ ❆❘●❊◆❚■◆❆✮✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✸✵
✹✵
✽✵
✾✵
✾✾
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❖P❊❘❆❚■❖◆❙
❙✫❊
❋■◆❆◆❈■❆▲
❘❍
▲❖❈
✲✲✲✲✲✲✲✲✲✲✲✲✲
❋▲❖❘■❉❆
❈❍■❈❆●❖
❇❖❙❚❖◆
❆❘●❊◆❚■◆❆
✻ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
O exemplo a seguir mostra o uso do execute immediate na execução
dinâmica de um comando delete:
❙◗▲❃ ❝r❡❛t❡ ❢✉♥❝t✐♦♥ r♦✇s❴❞❡❧❡t❡❞ ✭ t❛❜❧❡❴♥❛♠❡ ✐♥ ✈❛r❝❤❛r✷
✷
✱❝♦♥❞✐t✐♦♥ ✐♥ ✈❛r❝❤❛r✷✮ r❡t✉r♥ ✐♥t❡❣❡r ❛s
✸ ❜❡❣✐♥
✹
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬❞❡❧❡t❡ ❢r♦♠ ✬ ⑤⑤ t❛❜❧❡❴♥❛♠❡ ⑤⑤ ✬
✇❤❡r❡ ✬ ⑤⑤ ❝♦♥❞✐t✐♦♥❀
✺
r❡t✉r♥ sq❧✪r♦✇❝♦✉♥t❀
✻ ❡♥❞❀
✼ ✴
394
Casa do Código
Capítulo 23. SQL dinâmico
❋✉♥çã♦ ❝r✐❛❞❛✳
❙◗▲❃ ❞❡❝❧❛r❡
✷
✇♥r❴❧✐♥❤❛s ♥✉♠❜❡r❀
✸ ❜❡❣✐♥
✹
✇♥r❴❧✐♥❤❛s ✿❂ r♦✇s❴❞❡❧❡t❡❞✭✬❊▼P✬✱✬ ❡♠♣♥♦ ❂ ✼✾✸✺✬✮❀
✺
✲✲
✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬▲✐♥❤❛s ❡①❝❧✉í❞❛s✿ ✬⑤⑤✇♥r❴❧✐♥❤❛s✮❀
✼
✲✲
✽ ❡♥❞❀
✾ ✴
▲✐♥❤❛s ❡①❝❧✉í❞❛s✿ ✶
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Note que utilizamos o cursor implícito sql%rowcount para retornar
a quantidade de linhas excluídas. Através deste recurso também é possível
executar procedimentos PL/SQL. Para isso, criamos uma procedure para
realizar inserções na tabela dept.
❙◗▲❃ ❝r❡❛t❡ ♦r r❡♣❧❛❝❡ ♣r♦❝❡❞✉r❡ ❝r✐❛❴❞❡♣t ✭
♣❞❡♣t♥♦ ✐♥
♥✉♠❜❡r
✷
✱♣❞♥❛♠❡ ✐♥
✈❛r❝❤❛r✷
✸
✱♣❧♦❝
✐♥
✈❛r❝❤❛r✷
✹
✱♣st❛t✉s ✐♥ ♦✉t ✈❛r❝❤❛r✷✮ ✐s
✺ ❜❡❣✐♥
✻
✲✲
✼
✐♥s❡rt ✐♥t♦ ❞❡♣t ✈❛❧✉❡s ✭♣❞❡♣t♥♦✱ ♣❞♥❛♠❡✱ ♣❧♦❝✮❀
✽
✲✲
✾
♣st❛t✉s ✿❂ ✬❖❑✬❀
✶✵
✲✲
✶✶
❝♦♠♠✐t❀
✶✷
✲✲
✶✸ ❡①❝❡♣t✐♦♥
✶✹
✇❤❡♥ ♦t❤❡rs t❤❡♥
✶✺
♣st❛t✉s ✿❂ sq❧❡rr♠❀
395
Casa do Código
✶✻ ❡♥❞❀
✶✼ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃
Agora chamamos a procedure criada através de outro bloco PL/SQL,
utilizando uma chamada dinâmica.
❙◗▲❃ ❞❡❝❧❛r❡
✷
✲✲
✸
✇✐♥s❡r❡❴❞❡♣t ✈❛r❝❤❛r✷✭✷✵✵✵✮❀
✹
✲✲
✺
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡ ❞❡❢❛✉❧t ✬❘❍✬❀
✻
✇❧♦❝
❞❡♣t✳❧♦❝✪t②♣❡
❞❡❢❛✉❧t ✬❆❘●❊◆❚■◆❆✬❀
✼
✇❞❡♣t♥♦ ❞❡♣t✳❞❡♣t♥♦✪t②♣❡ ❞❡❢❛✉❧t ✽✽❀
✽
✲✲
✾
✇st❛t✉s ✈❛r❝❤❛r✷✭✹✵✵✵✮❀
✶✵
✲✲
✶✶ ❜❡❣✐♥
✶✷
✲✲
✶✸
✇✐♥s❡r❡❴❞❡♣t ✿❂ ✬❜❡❣✐♥ ❝r✐❛❴❞❡♣t✭✿❛✱ ✿❜✱ ✿❝✱ ✿❞✮❀ ❡♥❞❀✬❀
✶✹
✲✲
✶✺
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✇✐♥s❡r❡❴❞❡♣t
✶✻
✉s✐♥❣ ✐♥ ✇❞❡♣t♥♦✱ ✐♥ ✇❞♥❛♠❡✱ ✐♥ ✇❧♦❝✱ ✐♥ ♦✉t ✇st❛t✉s❀
✶✼
✲✲
✶✽
✐❢ ✇st❛t✉s ❂ ✬❖❑✬ t❤❡♥
✶✾
✲✲
✷✵
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦ ✐♥s❡r✐❞♦ ❝♦♠
s✉❝❡ss♦✳✬✮❀
✷✶
✲✲
✷✷
❡❧s❡
✷✸
✲✲
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊rr♦ ❛♦ ✐♥s❡r✐r ❞❡♣❛rt❛♠❡♥t♦✳
❊rr♦✿ ✬⑤⑤✇st❛t✉s✮❀
✷✺
✲✲
✷✻
❡♥❞ ✐❢❀
✷✼ ❡♥❞❀
396
Casa do Código
Capítulo 23. SQL dinâmico
✷✽ ✴
❉❡♣❛rt❛♠❡♥t♦ ✐♥s❡r✐❞♦ ❝♦♠ s✉❝❡ss♦✳
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Veja o resultado:
❙◗▲❃ s❡❧❡❝t ✯ ❢r♦♠ ❞❡♣t❀
❉❊P❚◆❖
✲✲✲✲✲✲✲✲✲✲
✶✵
✸✵
✹✵
✽✵
✾✵
✾✾
✽✽
❉◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❆❈❈❖❯◆❚■◆●
❙❆▲❊❙
❖P❊❘❆❚■❖◆❙
❙✫❊
❋■◆❆◆❈■❆▲
❘❍
❘❍
▲❖❈
✲✲✲✲✲✲✲✲✲✲✲✲✲
❋▲❖❘■❉❆
❈❍■❈❆●❖
❇❖❙❚❖◆
❆❘●❊◆❚■◆❆
❆❘●❊◆❚■◆❆
✼ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
A seguir, diferentes usos de SQL dinâmico para comandos select,
com retorno de informações. Nestes exemplos, não utilizaremos execute
immediate; em vez disso, usaremos cursores do tipo ref cursor.
23.1
Ref cursor
Uma variável do tipo ref cursor, como é comumente chamada, é utilizada para referenciar a estrutura de uma query, de forma dinâmica, ou seja,
ela não está ligada exatamente a um único comando SQL, diferente do uso
de cursores, no qual ao declararmos, necessitamos informar um comando
select específico.
Variáveis do tipo ref cursor, por não terem uma estrutura predefinida, podem ser usadas várias vezes dentro de um programa para diferentes comandos select e para um número ilimitado de linhas. Variáveis
397
23.1. Ref cursor
Casa do Código
do tipo ref cursor podem ainda serem definidas como parâmetros em
procedures. Sua declaração é semelhante à declaração de variáveis do tipo
tabela ou registro ( Index-By Table, Record).
A principal vantagem no uso de variáveis do tipo ref cursor se dá pelo
fato de ela apenas apontar para a estrutura ou linha retornada pelo comando
select. Sendo assim, o resultado não é armazenado, apenas referenciado.
Isso é muito útil na passagem de informações entre vários sistemas, pois não
há uma passagem de informações propriamente dita, apenas o compartilhamento através do que chamamos de um ponteiro.
❙◗▲❃ ❞❡❝❧❛r❡
✷
t②♣❡ ❡♠♣❝✉rt②♣ ✐s r❡❢ ❝✉rs♦r❀
✸
❡♠♣❴❝✈
❡♠♣❝✉rt②♣❀
✹
✲✲
✺
♠②❴❡♥❛♠❡ ✈❛r❝❤❛r✷✭✶✺✮❀
✻
♠②❴s❛❧
♥✉♠❜❡r
❞❡❢❛✉❧t ✶✵✵✵❀
✼ ❜❡❣✐♥
✽
♦♣❡♥ ❡♠♣❴❝✈ ❢♦r
✬s❡❧❡❝t ❡♥❛♠❡✱ s❛❧ ❢r♦♠ ❡♠♣ ✇❤❡r❡ s❛❧ ❃ ✿s✬ ✉s✐♥❣ ♠②❴s❛❧❀
✾
❧♦♦♣
✶✵
❢❡t❝❤ ❡♠♣❴❝✈ ✐♥t♦ ♠②❴❡♥❛♠❡✱ ♠②❴s❛❧❀
✶✶
✶✷
❡①✐t ✇❤❡♥ ❡♠♣❴❝✈✪♥♦t❢♦✉♥❞❀
✶✸
✲✲
✶✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭
✬❊♠♣r❡❣❛❞♦✿ ✬⑤⑤♠②❴❡♥❛♠❡⑤⑤✬ ❙❛❧ár✐♦✿ ✬⑤⑤♠②❴s❛❧✮❀
✶✺
✲✲
✶✻
❡♥❞ ❧♦♦♣❀
✶✼ ❡♥❞❀
✶✽ ✴
❊♠♣r❡❣❛❞♦✿ ❆▲▲❊◆ ❙❛❧ár✐♦✿ ✶✻✵✵
❊♠♣r❡❣❛❞♦✿ ❲❆❘❉ ❙❛❧ár✐♦✿ ✶✷✺✵
❊♠♣r❡❣❛❞♦✿ ▼❆❘❚■◆ ❙❛❧ár✐♦✿ ✶✷✺✵
❊♠♣r❡❣❛❞♦✿ ❇▲❆❑❊ ❙❛❧ár✐♦✿ ✷✽✺✵
❊♠♣r❡❣❛❞♦✿ ❈▲❆❘❑ ❙❛❧ár✐♦✿ ✷✹✺✵
❊♠♣r❡❣❛❞♦✿ ❑■◆● ❙❛❧ár✐♦✿ ✺✵✵✵
❊♠♣r❡❣❛❞♦✿ ❚❯❘◆❊❘ ❙❛❧ár✐♦✿ ✶✺✵✵
❊♠♣r❡❣❛❞♦✿ ▼■▲▲❊❘ ❙❛❧ár✐♦✿ ✶✸✵✵
398
Casa do Código
Capítulo 23. SQL dinâmico
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Neste exemplo, estamos utilizando um ref cursor que recebe uma
string de um comando SQL (linha 8). Utilizamos as cláusulas open e for
para atribuir o comando à variável ref cursor emp_cv. Depois, utilizamos um loop simples (linha 9) para manipular as informações, que são atribuídas a duas variáveis através da cláusula into (linha 10). Note que também
utilizamos a cláusula using para passagem de parâmetro.
❙◗▲❃ ❞❡❝❧❛r❡
✷
t②♣❡ ❡♠♣❝✉rt②♣ ✐s r❡❢ ❝✉rs♦r❀
✸
❡♠♣❴❝✈ ❡♠♣❝✉rt②♣❀
✹
❡♠♣❴r❡❝ ❡♠♣✪r♦✇t②♣❡❀
✺
✲✲
✻
sq❧❴st♠t ✈❛r❝❤❛r✷✭✷✵✵✮❀
✼
♠②❴❥♦❜ ✈❛r❝❤❛r✷✭✶✺✮ ✿❂ ✬❈▲❊❘❑✬❀
✽ ❜❡❣✐♥
✾
sq❧❴st♠t ✿❂ ✬s❡❧❡❝t ✯ ❢r♦♠ ❡♠♣ ✇❤❡r❡ ❥♦❜ ❂ ✿❥✬❀
✶✵
✲✲
✶✶
♦♣❡♥ ❡♠♣❴❝✈ ❢♦r sq❧❴st♠t ✉s✐♥❣ ♠②❴❥♦❜❀
✶✷
❧♦♦♣
✶✸
❢❡t❝❤ ❡♠♣❴❝✈ ✐♥t♦ ❡♠♣❴r❡❝❀
✶✹
❡①✐t ✇❤❡♥ ❡♠♣❴❝✈✪♥♦t❢♦✉♥❞❀
✶✺
✲✲
✶✻
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❊♠♣r❡❣❛❞♦✿ ✬⑤⑤❡♠♣❴r❡❝✳❡♥❛♠❡⑤⑤✬
❙❛❧ár✐♦✿ ✬⑤⑤❡♠♣❴r❡❝✳s❛❧✮❀
✶✼
✲✲
✶✽
❡♥❞ ❧♦♦♣❀
✶✾
❝❧♦s❡ ❡♠♣❴❝✈❀
✷✵ ❡♥❞❀
✷✶ ✴
❊♠♣r❡❣❛❞♦✿ ❏❆▼❊❙ ❙❛❧ár✐♦✿ ✾✺✵
❊♠♣r❡❣❛❞♦✿ ▼■▲▲❊❘ ❙❛❧ár✐♦✿ ✶✸✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
399
23.1. Ref cursor
Casa do Código
❙◗▲❃
Esse exemplo é bem semelhante ao anterior. A diferença está nas linhas 4
e 13. Declaramos uma variável do tipo tabela, utilizando a estrutura da tabela
emp (linha 4), que receberá o resultado do select através da cláusula into
na linha 13.
O próximo exemplo mostra que podemos montar um comando SQL através de strings passadas por parâmetro.
❙◗▲❃ ❝r❡❛t❡ ♣r♦❝❡❞✉r❡ ♣r✐♥t❴t❛❜❧❡ ✭t❛❜❴♥❛♠❡ ✈❛r❝❤❛r✷✮ ✐s
✷
t②♣❡ r❡❢❝✉rt②♣ ✐s r❡❢ ❝✉rs♦r❀
✸
❝✈ r❡❢❝✉rt②♣❀
✹
✇❞♥❛♠❡ ❞❡♣t✳❞♥❛♠❡✪t②♣❡❀
✺
✇❧♦❝
❞❡♣t✳❧♦❝✪t②♣❡❀
✻ ❜❡❣✐♥
✼
♦♣❡♥ ❝✈ ❢♦r ✬s❡❧❡❝t ❞♥❛♠❡✱ ❧♦❝ ❢r♦♠ ✬ ⑤⑤ t❛❜❴♥❛♠❡❀
✽
✲✲
✾
❧♦♦♣
✶✵
❢❡t❝❤ ❝✈ ✐♥t♦ ✇❞♥❛♠❡✱ ✇❧♦❝❀
✶✶
❡①✐t ✇❤❡♥ ❝✈✪♥♦t❢♦✉♥❞❀
✶✷
✲✲
✶✸
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❉❡♣❛rt❛♠❡♥t♦✿ ✬⑤⑤✇❞♥❛♠❡⑤⑤✬
▲♦❝❛❧✐③❛çã♦✿ ✬⑤⑤✇❧♦❝✮❀
✶✹
✲✲
✶✺
❡♥❞ ❧♦♦♣❀
✶✻
✲✲
✶✼
❝❧♦s❡ ❝✈❀
✶✽
✲✲
✶✾ ❡♥❞❀
✷✵ ✴
Pr♦❝❡❞✐♠❡♥t♦ ❝r✐❛❞♦✳
❙◗▲❃ ❜❡❣✐♥ ♣r✐♥t❴t❛❜❧❡ ✭t❛❜❴♥❛♠❡ ❂❃ ✬❉❊P❚✬✮❀ ❡♥❞❀
✷ ✴
❉❡♣❛rt❛♠❡♥t♦✿ ❆❈❈❖❯◆❚■◆● ▲♦❝❛❧✐③❛çã♦✿ ❋▲❖❘■❉❆
❉❡♣❛rt❛♠❡♥t♦✿ ❙❆▲❊❙ ▲♦❝❛❧✐③❛çã♦✿ ❈❍■❈❆●❖
❉❡♣❛rt❛♠❡♥t♦✿ ❖P❊❘❆❚■❖◆❙ ▲♦❝❛❧✐③❛çã♦✿ ❇❖❙❚❖◆
❉❡♣❛rt❛♠❡♥t♦✿ ❙✫❊ ▲♦❝❛❧✐③❛çã♦✿
400
Casa do Código
Capítulo 23. SQL dinâmico
❉❡♣❛rt❛♠❡♥t♦✿ ❋■◆❆◆❈■❆▲ ▲♦❝❛❧✐③❛çã♦✿
❉❡♣❛rt❛♠❡♥t♦✿ ❘❍ ▲♦❝❛❧✐③❛çã♦✿ ❆❘●❊◆❚■◆❆
❉❡♣❛rt❛♠❡♥t♦✿ ❘❍ ▲♦❝❛❧✐③❛çã♦✿ ❆❘●❊◆❚■◆❆
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Já no exemplo a seguir temos um mix de variável ref cursor e variáveis table e record. Aqui utilizamos a cláusula bulk collect, que é
responsável por preparar toda a coleção de saída de dados. Esta cláusula pode
ser usada junto com a cláusula into nos comandos select into, fetch
into, returning into e variáveis table. Esta cláusula não pode ser
usada para variáveis do tipo record. Dessa forma, caso tenhamos informações referentes a várias colunas, será necessária a criação de uma variável do
tipo table para cada uma.
❙◗▲❃ ❞❡❝❧❛r❡
✷
t②♣❡ ❡♠♣❝✉rt②♣ ✐s r❡❢ ❝✉rs♦r❀
✸
t②♣❡ ♥✉♠❧✐st ✐s t❛❜❧❡ ♦❢ ♥✉♠❜❡r❀
✹
t②♣❡ ♥❛♠❡❧✐st ✐s t❛❜❧❡ ♦❢ ✈❛r❝❤❛r✷✭✶✺✮❀
✺
✲✲
✻
❡♠♣❴❝✈ ❡♠♣❝✉rt②♣❀
✼
❡♠♣♥♦s ♥✉♠❧✐st❀
✽
❡♥❛♠❡s ♥❛♠❡❧✐st❀
✾
✲✲
✶✵
s❛❧s ♥✉♠❧✐st❀
✶✶ ❜❡❣✐♥
✶✷
♦♣❡♥ ❡♠♣❴❝✈ ❢♦r ✬s❡❧❡❝t ❡♠♣♥♦✱ ❡♥❛♠❡ ❢r♦♠ ❡♠♣✬❀
✶✸
❢❡t❝❤ ❡♠♣❴❝✈ ❜✉❧❦ ❝♦❧❧❡❝t ✐♥t♦ ❡♠♣♥♦s✱ ❡♥❛♠❡s❀
✶✹
❝❧♦s❡ ❡♠♣❴❝✈❀
✶✺
✲✲
✶✻
❢♦r r ✐♥ ✶✳✳❡♠♣♥♦s✳❝♦✉♥t ❧♦♦♣
✶✼
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❈ó❞✳✿ ✬⑤⑤❡♠♣♥♦s✭r✮⑤⑤✬ ✲
❊♠♣r❡❣❛❞♦✿ ✬⑤⑤❡♥❛♠❡s✭r✮✮❀
✶✽
❡♥❞ ❧♦♦♣❀
✶✾
✲✲
✷✵
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬s❡❧❡❝t s❛❧ ❢r♦♠ ❡♠♣✬
✷✶
❜✉❧❦ ❝♦❧❧❡❝t ✐♥t♦ s❛❧s❀
401
23.1. Ref cursor
Casa do Código
✷✷
✲✲
✷✸
❢♦r r ✐♥ ✶✳✳s❛❧s✳❝♦✉♥t ❧♦♦♣
✷✹
❞❜♠s❴♦✉t♣✉t✳♣✉t❴❧✐♥❡✭✬❙❛❧ár✐♦✿ ✬⑤⑤s❛❧s✭r✮✮❀
✷✺
❡♥❞ ❧♦♦♣❀
✷✻ ❡♥❞❀
✷✼ ✴
❈ó❞✳✿ ✼✹✾✾ ✲ ❊♠♣r❡❣❛❞♦✿ ❆▲▲❊◆
❈ó❞✳✿ ✼✺✷✶ ✲ ❊♠♣r❡❣❛❞♦✿ ❲❆❘❉
❈ó❞✳✿ ✼✻✺✹ ✲ ❊♠♣r❡❣❛❞♦✿ ▼❆❘❚■◆
❈ó❞✳✿ ✼✻✾✽ ✲ ❊♠♣r❡❣❛❞♦✿ ❇▲❆❑❊
❈ó❞✳✿ ✼✼✽✷ ✲ ❊♠♣r❡❣❛❞♦✿ ❈▲❆❘❑
❈ó❞✳✿ ✼✽✸✾ ✲ ❊♠♣r❡❣❛❞♦✿ ❑■◆●
❈ó❞✳✿ ✼✽✹✹ ✲ ❊♠♣r❡❣❛❞♦✿ ❚❯❘◆❊❘
❈ó❞✳✿ ✼✾✵✵ ✲ ❊♠♣r❡❣❛❞♦✿ ❏❆▼❊❙
❈ó❞✳✿ ✼✾✸✹ ✲ ❊♠♣r❡❣❛❞♦✿ ▼■▲▲❊❘
❈ó❞✳✿ ✼✾✸✺ ✲ ❊♠♣r❡❣❛❞♦✿ P❆❯▲
❙❛❧ár✐♦✿ ✶✻✵✵
❙❛❧ár✐♦✿ ✶✷✺✵
❙❛❧ár✐♦✿ ✶✷✺✵
❙❛❧ár✐♦✿ ✷✽✺✵
❙❛❧ár✐♦✿ ✷✹✺✵
❙❛❧ár✐♦✿ ✺✵✵✵
❙❛❧ár✐♦✿ ✶✺✵✵
❙❛❧ár✐♦✿ ✾✺✵
❙❛❧ár✐♦✿ ✶✸✵✵
❙❛❧ár✐♦✿ ✶✵✵✵
Pr♦❝❡❞✐♠❡♥t♦ P▲✴❙◗▲ ❝♦♥❝❧✉í❞♦ ❝♦♠ s✉❝❡ss♦✳
❙◗▲❃
Na linha 2, temos a definição de uma variável do tipo ref cursor que
receberá um comando SQL. Já nas linhas 3 e 4, temos a declaração de duas
variáveis do tipo table. Esta declaração define dois tipos array, um array
numérico e outro de caracteres. Nas linhas 7 e 8, são declaradas duas variáveis com base nestes tipos. Nas linhas 12 e 13, foi utilizado um cursor que lê
as informações de um select dinâmico que, através do bulk collect,
carrega as informações para as variáveis do tipo array.
402
Casa do Código
Capítulo 23. SQL dinâmico
Note que não foi necessário utilizar loop para atribuir as linhas vindas do
select. O bulk collect já faz esta atribuição. Nas linhas 16 e 18, utilizamos um for loop para ler os dados das variáveis array. Observe que o for
loop toma como base a quantidade de linhas que o array possui. Neste caso,
utilizamos o count de uma das variáveis para determinar valor final do for
loop, mesmo porque carregamos as duas variáveis em um mesmo momento
e utilizando o mesmo select. Logo, a quantidade de dados carregados nas
duas variáveis é a mesma.
Dentro no mesmo programa temos outra execução dinâmica (linhas 20 a
21), onde é possível usar o bulk collect também para receber o resultado
vindo através da execução via execute immediate.
Por último, um exemplo de function para retornar a quantidade
de registros em uma determinada tabela, passada por parâmetro, usando
execute immediate com retorno utilizando into.
❙◗▲❃
❝r❡❛t❡ ❢✉♥❝t✐♦♥ r♦✇❴❝♦✉♥t✭t❛❜❴♥❛♠❡ ✈❛r❝❤❛r✷✮ r❡t✉r♥ ✐♥t❡❣❡r ❛s
✷
r♦✇s ✐♥t❡❣❡r❀
✸ ❜❡❣✐♥
✹
❡①❡❝✉t❡ ✐♠♠❡❞✐❛t❡ ✬s❡❧❡❝t ❝♦✉♥t✭✯✮ ❢r♦♠ ✬ ⑤⑤
t❛❜❴♥❛♠❡ ✐♥t♦ r♦✇s❀
✺
r❡t✉r♥ r♦✇s❀
✻ ❡♥❞❀
✼ ✴
❋✉♥çã♦ ❝r✐❛❞❛✳
❙◗▲❃ s❡❧❡❝t r♦✇❴❝♦✉♥t✭✬❊▼P✬✮ ❢r♦♠ ❞✉❛❧❀
❘❖❲❴❈❖❯◆❚✭✬❊▼P✬✮
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
✶✵
❙◗▲❃
403
Capítulo 24
Apêndice: SQL – Primeiros
passos
24.1 Como iniciar no SQL
Uma das dificuldades que encontramos quando estamos aprendendo uma
linguagem de programação é saber por onde começar. No caso do aprendizado da SQL, não seria diferente. É uma situação normal. Até sentirmos
segurança e termos conhecimento suficiente sobre a linguagem, é interessante
termos um roteiro contendo os primeiros passos para iniciar um programa
ou comando SQL.
Desta forma, demonstro aqui uma técnica que utilizo bastante, mesmo
tendo um bom conhecimento na linguagem. Na verdade, já está implícito
na minha forma de pensar, tanto que acabo executando-a mentalmente, en-
24.1. Como iniciar no SQL
Casa do Código
quanto escrevo nesta linguagem. Este método não foi retirado de nenhum
livro, foi algo que, entendendo a lógica, fui seguindo e deu certo. Espero que
ajude vocês.
Vamos tomar como exemplo a questão a seguir:
Escreva um select que apresente as colunas, nome da região
( REGION_NAME: tabela REGIONS), nome da cidade ( CITY: tabela
LOCATIONS), nome do departamento ( DEPARTMENT_NAME: tabela
DEPARTMENTS) e o nome dos empregados ( FIRST_NAME), mas somente
daqueles que possuam o salário maior que 11.000. Ordene os dados pelos
mesmos campos do select, seguindo a mesma ordem do enunciado.
Primeiro passo
Identifico no enunciado as fontes de dados, ou seja, as tabelas que farão
parte do comando SQL.
Neste nosso exemplo, as tabelas são: REGIONS, COUNTRIES, LOCATIONS, DEPARTMENTS e EMPLOYEES, pois o enunciado nos diz isto. Contudo, se ele não diz os nomes das tabelas, pelo menos deve mencionar do que
se tratam tais informações, por exemplo, empregados, departamentos, países
etc.
Se você tiver o MER (Modelo Entidade Relacionamento, veja anexos 26)
fica mais fácil, pois nele você consegue verificar a localização de tais informações referentes aos nomes das tabelas ou os nomes dos campos os quais o
enunciado pede. Exemplo: REGION_NAME, CITY etc.
Caso não tenha o MER, você pode localizar tais tabelas no banco de dados, executando um select na user_tables ou all_tables para tentar
localizá-las através dos seus nomes. Tendo as localizado, você pode executar
o comando desc em cima de cada uma delas para visualizar suas colunas e
identificar as informações solicitadas. Veja o exemplo a seguir:
❙◗▲❃ s❡❧❡❝t t❛❜❧❡❴♥❛♠❡
✷ ❢r♦♠ ✉s❡r❴t❛❜❧❡s❀
❚❆❇▲❊❴◆❆▼❊
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❊▼P
406
Casa do Código
Capítulo 24. Apêndice: SQL – Primeiros passos
❉❊P❚
❇❖◆❯❙
❙❆▲●❘❆❉❊
❉❯▼▼❨
❘❊●■❖◆❙
▲❖❈❆❚■❖◆❙
❉❊P❆❘❚▼❊◆❚❙
❏❖❇❙
❊▼P▲❖❨❊❊❙
❏❖❇❴❍■❙❚❖❘❨
❈❖❯◆❚❘■❊❙
✷✸ ❧✐♥❤❛s s❡❧❡❝✐♦♥❛❞❛s✳
❙◗▲❃
Caso você queira ver se há comentários sobre tais tabelas, por exemplo, indicando sua finalidade, você pode executar um select na
user_tab_comments ou all_tab_comments, pesquisando pelo nome
da tabela. Lembrando que utilizando a tabela com prefixo all você deve
informar a que usuário, ou melhor, a qual dono, a tabela pertence. Veja o
exemplo:
❙◗▲❃ s❡❧❡❝t ❝♦♠♠❡♥ts
✷ ❢r♦♠ ✉s❡r❴t❛❜❴❝♦♠♠❡♥ts
✸ ✇❤❡r❡ t❛❜❧❡❴♥❛♠❡ ❂ ✬❊▼P▲❖❨❊❊❙✬❀
❈❖▼▼❊◆❚❙
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❡♠♣❧♦②❡❡s t❛❜❧❡✳ ❈♦♥t❛✐♥s ✶✵✼ r♦✇s✳ ❘❡❢❡r❡♥❝❡s ✇✐t❤ ❞❡♣❛rt♠❡♥ts✱
❥♦❜s✱ ❥♦❜❴❤✐st♦r② t❛❜❧❡s✳ ❈♦♥t❛✐♥s ❛ s❡❧❢ r❡❢❡r❡♥❝❡✳
❙◗▲❃
Segundo passo
Conectado ao banco de dados, através de uma ferramenta, exemplo
SQL*Plus, faço um breve reconhecimento das tabelas envolvidas no enun407
Casa do Código
24.1. Como iniciar no SQL
ciado.
Seguindo o exemplo, vamos analisar através do comando desc as tabelas e colunas que identificamos, como as tabelas EMPLOYEES e DEPARTMENTS.
❙◗▲❃ ❞❡s❝ ❡♠♣❧♦②❡❡s
◆♦♠❡
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❊▼P▲❖❨❊❊❴■❉
❋■❘❙❚❴◆❆▼❊
▲❆❙❚❴◆❆▼❊
❊▼❆■▲
P❍❖◆❊❴◆❯▼❇❊❘
❍■❘❊❴❉❆❚❊
❏❖❇❴■❉
❙❆▲❆❘❨
❈❖▼▼■❙❙■❖◆❴P❈❚
▼❆◆❆●❊❘❴■❉
❉❊P❆❘❚▼❊◆❚❴■❉
❇■❘❚❍❴❉❆❚❊
❍■❘❊❴❉❆❚❊❴❇❑P
❙◗▲❃ ❞❡s❝ ❞❡♣❛rt♠❡♥ts
◆♦♠❡
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❉❊P❆❘❚▼❊◆❚❴■❉
❉❊P❆❘❚▼❊◆❚❴◆❆▼❊
▼❆◆❆●❊❘❴■❉
▲❖❈❆❚■❖◆❴■❉
❚✐♣♦
◆✉❧♦❄
✲✲✲✲✲✲✲✲ ✲✲✲✲✲✲✲✲✲✲✲✲✲
◆❖❚ ◆❯▲▲ ◆❯▼❇❊❘✭✻✮
❱❆❘❈❍❆❘✷✭✷✵✮
◆❖❚ ◆❯▲▲ ❱❆❘❈❍❆❘✷✭✷✺✮
◆❖❚ ◆❯▲▲ ❱❆❘❈❍❆❘✷✭✷✺✮
❱❆❘❈❍❆❘✷✭✷✵✮
◆❖❚ ◆❯▲▲ ❉❆❚❊
◆❖❚ ◆❯▲▲ ❱❆❘❈❍❆❘✷✭✶✵✮
◆❯▼❇❊❘✭✽✱✷✮
◆❯▼❇❊❘✭✷✱✷✮
◆❯▼❇❊❘✭✻✮
◆❯▼❇❊❘✭✹✮
❉❆❚❊
❉❆❚❊
◆✉❧♦❄
✲✲✲✲✲✲✲✲
◆❖❚ ◆❯▲▲
◆❖❚ ◆❯▲▲
❚✐♣♦
✲✲✲✲✲✲✲✲✲✲✲✲✲
◆❯▼❇❊❘✭✹✮
❱❆❘❈❍❆❘✷✭✸✵✮
◆❯▼❇❊❘✭✻✮
◆❯▼❇❊❘✭✹✮
❙◗▲❃
Terceiro passo
Inicio a escrita do comando SQL, preenchendo a cláusula select com
as colunas que devo mostrar, e a cláusula from informando às tabelas que
vou precisar para recuperar todas as informações.
s❡❧❡❝t r✳r❡❣✐♦♥❴♥❛♠❡
408
Casa do Código
Capítulo 24. Apêndice: SQL – Primeiros passos
✱❧✳❝✐t②
✱❞✳❞❡♣❛rt♠❡♥t❴♥❛♠❡
✱❡✳❢✐rst❴♥❛♠❡
❢r♦♠ r❡❣✐♦♥s
r
❝
✱❝♦✉♥tr✐❡s
✱❧♦❝❛t✐♦♥s
❧
✱❞❡♣❛rt♠❡♥ts ❞
✱❡♠♣❧♦②❡❡s
❡
Note que nem sempre são mencionadas no enunciado todas as tabelas de
que precisaremos para retornar todas as informações. Desta forma, precisamos consultar novamente o MER, para entender quais são todas as ligações
e de quais objetos vamos necessitar. Vale salientar que entre as tabelas, na
maioria dos casos, existe uma ou mais colunas que são as responsáveis pelas ligações entre elas. Necessitamos fazer estas ligações para que o resultado
retornado seja o resultado correto, e a integridade seja mantida.
Outro fator importante: sempre utilizo apelidos (aliasl) para identificar
as tabelas e colunas em um comando SQL. Isso serve para evitar erros de
colunas ambíguas (colunas com nomes iguais entre as tabelas, pois, neste caso,
o Oracle não sabe dizer quem é quem), e para tornar a leitura do comando
SQL mais inteligível.
Quarto passo
Fazer as ligações entre as tabelas que estamos utilizando na cláusula
from.
✶✵
✶✶
✶✷
✶✸
✇❤❡r❡
❛♥❞
❛♥❞
❛♥❞
r✳r❡❣✐♦♥❴✐❞
❝✳❝♦✉♥tr②❴✐❞
❧✳❧♦❝❛t✐♦♥❴✐❞
❞✳❞❡♣❛rt♠❡♥t❴✐❞
❂
❂
❂
❂
❝✳r❡❣✐♦♥❴✐❞
❧✳❝♦✉♥tr②❴✐❞
❞✳❧♦❝❛t✐♦♥❴✐❞
❡✳❞❡♣❛rt♠❡♥t❴✐❞
Caso não se tenha o MER, podemos fazer um select nas views
user_constraints e user_cons_columns, para tentar localizar as ligações entre as tabelas. Exemplo:
❙◗▲❃ s❡❧❡❝t ❝♦♥s✳t❛❜❧❡❴♥❛♠❡⑤⑤✬✳✬⑤⑤❝♦♥s❴❝♦❧✳❝♦❧✉♠♥❴♥❛♠❡⑤⑤
✷
✬ ❢❛③ ❧✐❣❛çã♦ ❝♦♠ ✬⑤⑤
409
24.1. Como iniciar no SQL
Casa do Código
✸
❝♦♥s❴❞❡♣❡♥❞✳t❛❜❧❡❴♥❛♠❡⑤⑤✬✳
✬⑤⑤❝♦♥s❴❝♦❧❴❞❡♣❡♥❞✳❝♦❧✉♠♥❴♥❛♠❡⑤⑤✬ ✬⑤⑤
✬❛tr❛✈és ❞❛ ❝❤❛✈❡ ✬⑤⑤❝♦♥s✳❝♦♥str❛✐♥t❴♥❛♠❡ ✧
✹
❉❡♣❡♥❞ê♥❝✐❛s✧
✺ ❢r♦♠ ✲✲ t❛❜❡❧❛ ♣❡sq✉✐s❛
✻
✉s❡r❴❝♦♥str❛✐♥ts ❝♦♥s
✼
✱✉s❡r❴❝♦♥s❴❝♦❧✉♠♥s ❝♦♥s❴❝♦❧
✽
✲✲ t❛❜❡❧❛ ❞❡♣❡♥❞❡♥❝✐❛
✾
✱✉s❡r❴❝♦♥str❛✐♥ts ❝♦♥s❴❞❡♣❡♥❞
✶✵
✱✉s❡r❴❝♦♥s❴❝♦❧✉♠♥s ❝♦♥s❴❝♦❧❴❞❡♣❡♥❞
✶✶ ✇❤❡r❡ ❝♦♥s✳❝♦♥str❛✐♥t❴♥❛♠❡ ❂ ❝♦♥s❴❝♦❧✳❝♦♥str❛✐♥t❴♥❛♠❡
✶✷ ❛♥❞
❝♦♥s✳t❛❜❧❡❴♥❛♠❡
❂ ❝♦♥s❴❝♦❧✳t❛❜❧❡❴♥❛♠❡
✶✸ ❛♥❞
❝♦♥s✳t❛❜❧❡❴♥❛♠❡
❂
✬❊▼P▲❖❨❊❊❙✬ ✲✲ t❛❜❡❧❛ ♣❛r❛ ♣❡sq✉✐s❛
✶✹ ❛♥❞
❝♦♥s✳❝♦♥str❛✐♥t❴t②♣❡ ❂
✬❘✬ ✲✲ ❋♦r❡✐❣♥ ❦❡② ✭❧✐❣❛çã♦ ❡♥tr❡ ❛s t❛❜❡❧❛s✮
✶✺ ✲✲
✶✻ ❛♥❞
❝♦♥s❴❞❡♣❡♥❞✳❝♦♥str❛✐♥t❴♥❛♠❡ ❂
❝♦♥s❴❝♦❧❴❞❡♣❡♥❞✳❝♦♥str❛✐♥t❴♥❛♠❡
✶✼ ❛♥❞
❝♦♥s❴❞❡♣❡♥❞✳t❛❜❧❡❴♥❛♠❡
❂
❝♦♥s❴❝♦❧❴❞❡♣❡♥❞✳t❛❜❧❡❴♥❛♠❡
✶✽ ❛♥❞
❝♦♥s❴❞❡♣❡♥❞✳❝♦♥str❛✐♥t❴♥❛♠❡ ❂ ❝♦♥s✳r❴❝♦♥str❛✐♥t❴♥❛♠❡
✶✾ ♦r❞❡r ❜② ✶
✷✵ ✴
❉❡♣❡♥❞ê♥❝✐❛s
✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲✲
❊▼P▲❖❨❊❊❙✳❉❊P❆❘❚▼❊◆❚❴■❉ ❢❛③ ❧✐❣❛çã♦ ❝♦♠
❉❊P❆❘❚▼❊◆❚❙✳❉❊P❆❘❚▼❊◆❚❴■❉ ❛tr❛✈és ❞❛ ❝❤❛✈❡
❊▼P❴❉❊P❚❴❋❑
❊▼P▲❖❨❊❊❙✳❏❖❇❴■❉ ❢❛③ ❧✐❣❛çã♦ ❝♦♠ ❏❖❇❙✳❏❖❇❴■❉ ❛tr❛✈és ❞❛ ❝❤❛✈❡
❊▼P❴❏❖❇❴❋❑
❊▼P▲❖❨❊❊❙✳▼❆◆❆●❊❘❴■❉ ❢❛③ ❧✐❣❛çã♦ ❝♦♠ ❊▼P▲❖❨❊❊❙✳❊▼P▲❖❨❊❊❴■❉
❛tr❛✈és ❞❛ ❝❤❛✈❡ ❊▼P❴▼❆◆❆●❊❘❴❋❑
❙◗▲❃
Observação:
410
Você pode utilizar este select sempre que possível.
Casa do Código
Capítulo 24. Apêndice: SQL – Primeiros passos
Guarde-o!
Quinto passo
Colocar as demais críticas (restrições) solicitadas pelo enunciado.
✶✹ ❛♥❞
❡✳s❛❧❛r②❃ ✶✶✵✵✵
✶✺ ♦r❞❡r ❜② r✳r❡❣✐♦♥❴♥❛♠❡
✶✻
✱❧✳❝✐t②
✶✼
✱❞✳❞❡♣❛rt♠❡♥t❴♥❛♠❡
✶✽
✱❡✳❢✐rst❴♥❛♠❡❀
Segue o comando SQL completo:
❙◗▲❃
✷
✸
✹
✺
✻
✼
✽
✾
✶✵
✶✶
✶✷
✶✸
✶✹
✶✺
✶✻
✶✼
✶✽
s❡❧❡❝t r✳r❡❣✐♦♥❴♥❛♠❡
✱❧✳❝✐t②
✱❞✳❞❡♣❛rt♠❡♥t❴♥❛♠❡
✱❡✳❢✐rst❴♥❛♠❡
❢r♦♠ r❡❣✐♦♥s
r
✱❝♦✉♥tr✐❡s
❝
✱❧♦❝❛t✐♦♥s
❧
✱❞❡♣❛rt♠❡♥ts ❞
✱❡♠♣❧♦②❡❡s
❡
✇❤❡r❡ r✳r❡❣✐♦♥❴✐❞
❂ ❝✳r❡❣✐♦♥❴✐❞
❛♥❞ ❝✳❝♦✉♥tr②❴✐❞
❂ ❧✳❝♦✉♥tr②❴✐❞
❛♥❞ ❧✳❧♦❝❛t✐♦♥❴✐❞ ❂ ❞✳❧♦❝❛t✐♦♥❴✐❞
❛♥❞ ❞✳❞❡♣❛rt♠❡♥t❴✐❞ ❂ ❡✳❞❡♣❛rt♠❡♥t❴✐❞
❛♥❞ ❡✳s❛❧❛r②❃ ✶✶✵✵✵
♦r❞❡r ❜② r✳r❡❣✐♦♥❴♥❛♠❡
✱❧✳❝✐t②
✱❞✳❞❡♣❛rt♠❡♥t❴♥❛♠❡
✱❡✳❢✐rst❴♥❛♠❡❀
Observações: para os demais comandos, como o insert, o delete e
o update, podemos seguir o mesmo raciocínio. Primeiramente, identificamos as tabelas, as colunas para as ligações e restrições, se for o caso, e depois
escrevemos o comando.
411
Capítulo 25
Referências bibliográficas
• DATE, C. J. Introdução a Sistemas de Bancos de Dados. Rio de Janeiro:
Campus, 1991.
• FERNANDES, Lúcia. Oracle 9i Para Desenvolvedores - Curso Completo.
Rio de Janeiro: Axcel Books, 2002.
• GENNICK, Jonathan, LUERS, Tom. Aprenda em 21 dias PL/SQL. 2. ed.
Rio de Janeiro: Campus, 2000.
• HEUSER, Carlos Alberto. Projeto de Banco de Dados. 4. ed. Porto
Alegre: Sagra Luzzatto, 2001.
• LIMA, Adilson da Silva. Erwin 4.0 Modelagem de Dados. 2. ed. São
Paulo: Érica, 2002.
Casa do Código
• LONEY, Kevin et al. Oracle 9i: O Manual do DBA. Rio de Janeiro: Campus, 2002.
• MOLINARI, Leonardo. BTO Otimização da Tecnologia de Negócio. São
Paulo: Érica, 2003.
• ORACLE Database Online Documentation 10g Release 1 (10.1). Disponível em: <http://www.oracle.com/pls/db10g/portal.portal_demo3?
selected=1> . Acesso em: 16 mar. 2011.
• Oracle Database New Features Guide 11g, Release 2 (11.2)
• Oracle Database Advanced Application Developer’s Guide 11g Release
2 (11.2)
• Oracle Database PL/SQL Language Reference 11g Release 2 (11.2)
• Oracle Database Reference 11g Release 2 (11.2)
• Oracle Database SQL Language Reference 11g Release 2 (11.2)
• Oracle Database Concepts 11g, Release 2 (11.2)
• Oracle Database PL/SQL Packages and Types Reference 11g Release 2
(11.2)
• Oracle Database SQL Developer User’s Guide Release 3.1
414
Capítulo 26
Casa do Código
Anexos
Fig. 26.1: Esquema da base de dados SCOTT utilizada nos exemplos
416
Casa do Código
Capítulo 26. Anexos
Fig. 26.2: Esquema da base de dados HR utilizada nos exemplos
417