Você está na página 1de 140

LABORATÓRIO

DE
BANCO DE DADOS
Se eu tivesse oito horas para derrubar
uma árvore, passaria seis afiando meu
machado (Abraham Lincoln).

Ma. Simone Maria Viana Romano

2019
L A B O R A T O R I O D E B A N C O D E D A D O S

SUMÁRIO

INFORMAÇÕES IMPORTANTES ....................................................................................... 7


OBJETIVO ........................................................................................................................... 7
EMENTA .............................................................................................................................. 7
BIBLIOGRAFIA ................................................................................................................... 7
SOFTWARES UTILIZADOS ................................................................................................ 7
FALTAS PERMITIDAS NO SEMESTRE ............................................................................. 7
ABONO DE FALTAS ........................................................................................................... 7
CONTATO ........................................................................................................................... 8
DIAS QUE ESTOU NA INSTITUIÇÃO ............................................................................... 8
DATAS DA AVALIAÇÃO DO SEMESTRE .......................................................................... 8
FORMA DE AVALIAÇÃO E CONTEÚDO ......................................................................... 8
PERDA DE ATIVIDADE ..................................................................................................... 9
ERROS DA APOSTILA ........................................................................................................ 9
TRABALHO SEMESTRAL ................................................................................................... 9
ACESSANDO O BANCO DE DADOS ORACLE ................................................................ 9
PROBLEMAS DE CONEXÃO ............................................................................................ 12
MUDAR A PORTA DO ORACLEXE:................................................................................. 13
PARTE GRÁFICA SERVIDOR FATEC.............................................................................. 13
PARTE GRÁFICA LOCAL .................................................................................................. 14
DICIONÁRIO DE DADOS - ESQUEMA HR: ..................................................................... 17
ORACLE 11G RELEASE EXPRESS EDITION ................................................................ 23
INSTALAÇÃO ..................................................................................................................... 23
REVISÃO DE BANCO DE DADOS .................................................................................... 28
SUBCONSULTA (SUBQUERIE) ......................................................................................... 29
UMA LINHA ........................................................................................................................ 29
MÚLTIPLAS LINHAS ......................................................................................................... 30
SELECT COM IN............................................................................................................... 30
SELECT COM ANY ........................................................................................................... 30
SELECT COM ALL ............................................................................................................ 31
SUBCONSULTA NA CLÁUSULA FROM ......................................................................... 31
COMPARAÇÕES DE COLUNA ......................................................................................... 31
SUBCONSULTA ESCALAR ............................................................................................... 32
SUBCONSULTA CORRELACIONADA ............................................................................ 33
EXISTS ................................................................................................................................. 33
NOT EXISTS ........................................................................................................................ 33
UPDATE CORRELACIONADA ......................................................................................... 34
DELETE CORRELACIONADA .......................................................................................... 34
EXERCÍCIOS PRÁTICOS ................................................................................................... 35
RECUPERAÇÃO HIERÁRQUICA ..................................................................................... 36

2
L A B O R A T O R I O D E B A N C O D E D A D O S

FORMATANDO RELATÓRIOS HIERÁRQUICOS .......................................................... 37


COMPACTANDO RAMIFICAÇÕES ................................................................................. 37
MANIPULANDO DADOS – OUTROS CONCEITOS ...................................................... 38
MERGE ................................................................................................................................. 38
TRANSAÇÃO → SAVEPOINT ........................................................................................... 38
INSERT MULTITABELAS ................................................................................................. 39
SEQUÊNCIAS ........................................................................................................................ 43
SINÔNIMOS ........................................................................................................................... 44
CRIANDO SINÔNIMOS...................................................................................................... 44
CONFIRMANDO A CRIAÇÃO DE SINÔNIMOS ............................................................. 45
ELIMINANDO SINÔNIMOS .............................................................................................. 45
INDICES ................................................................................................................................. 45
CRIANDO UM ÍNDICE ARVORE B .................................................................................. 46
QUANDO DEVEMOS CRIAR UM ÍNDICE ....................................................................... 46
QUANDO NÃO DEVEMOS CRIAR UM ÍNDICE ............................................................. 47
CONFIRMAÇÃO DOS ÍNDICES ........................................................................................ 47
REMOÇÃO DE UM ÍNDICE ............................................................................................... 47
ALTERAR UM ÍNDICE ....................................................................................................... 47
VIEWS ..................................................................................................................................... 48
APAGAR A VISÃO: DROP VIEW ....................................................................................... 49
VIEW COMPLEXA .............................................................................................................. 49
OPERAÇÕES DML .............................................................................................................. 49
WITH CHECK OPTION....................................................................................................... 49
WITH READ ONLY ............................................................................................................. 50
ANÁLISE TOP-N ................................................................................................................. 50
VIEW MATERIALIZADA................................................................................................... 50
EXERCÍCIOS PRÁTICOS ................................................................................................... 52
OBJETO-RELACIONAL ..................................................................................................... 53
TIPO OBJETO ...................................................................................................................... 53
HERANÇA............................................................................................................................ 53
TABELAS ANINHADAS (NESTED TABLE) .................................................................... 54
CRIAÇÃO DE TIPOS DE ARRAY ...................................................................................... 56
OPERADOR VALUE ........................................................................................................... 56
TIPOS REFERÊNCIA .......................................................................................................... 57
EXERCÍCIO PRÁTICO ........................................................................................................ 57
ARQUITETURA ORACLE .................................................................................................. 58
COMPONENTES DE ARQUITETURA ORACLE ............................................................. 58
ESTRUTURA DE ARMAZENAMENTO LÓGICA.................................................................... 63
EXERCÍCIOS ....................................................................................................................... 65
DICIONÁRIO DE DADOS ................................................................................................... 66
USUÁRIOS E PRIVILÉGIOS .............................................................................................. 70
CRIANDO USUARIOS ........................................................................................................ 70

3
L A B O R A T O R I O D E B A N C O D E D A D O S

CONSULTAR USUÁRIOS EXISTENTES ......................................................................... 70


PARA ALTERAR A SENHA DE ACESSO ......................................................................... 70
EXCLUINDO UM USUÁRIO .............................................................................................. 71
PRIVILÉGIOS DE SISTEMA .............................................................................................. 71
PRIVILÉGIOS DE CONEXÃO PARA USUARIO CRIADO.............................................. 71
PARA VISUALIZAR OS PRIVILÉGIOS DE SISTEMA ATUAIS .................................... 71
PARA VISUALIZAR OS PRIVILÉGIOS DE SISTEMA .................................................... 71
PARA VISUALIZAR OS PRIVILÉGIOS DE OBJETO ...................................................... 71
PARA CONCEDER PRIVILÉGIOS .................................................................................... 71
PARA RETIRAR ALGUM PRIVILÉGIO DE SISTEMA.................................................... 71
PRIVILÉGIOS DE OBJETO ................................................................................................ 72
ROLES .................................................................................................................................. 72
CRIANDO ROLES (DESDE QUE POSSUA PRIVILÉGIO) ..................................... 72
PARA VISUALIZAR ROLES ......................................................................................... 72
CONSULTANDO PRIVILEGIOS CONCEDIDOS ............................................................. 72
PRÁTICA DE LABORATÓRIO .......................................................................................... 73
PL/SQL – VISÃO GERAL .................................................................................................... 74
CONCEITOS GERAIS ......................................................................................................... 74
ESTRUTURA DO PL/SQL................................................................................................... 75
DECLARAÇÃO.................................................................................................................... 75
IDENTIFICADORES ........................................................................................................... 76
VARIÁVEIS DE SUBSTITUIÇÃO OU DE HOST (LIGAÇÃO). ....................................... 76
TIPOS DE DADOS ESCALARES ....................................................................................... 76
TIPOS DE DADOS DO PL/SQL .......................................................................................... 76
O QUE É NULL? .................................................................................................................. 77
ATRIBUTO %TYPE ............................................................................................................ 78
DBMS_OUTPUT.PUT_LINE .............................................................................................. 79
COMENTÁRIOS .................................................................................................................. 79
OPERADORES EM PL/SQL ................................................................................................ 79
DIRETRIZES E SINTAXE DE BLOCO .............................................................................. 80
VARIÁVEIS DE TIPO DE DADOS LOB ............................................................................ 80
FUNÇÕES SQL EM PL/SQL ............................................................................................... 81
BLOCOS ANINHADOS E ESCOPO DE VARIÁVEL ........................................................ 81
EXERCÍCIOS PRÁTICOS ................................................................................................... 82
INSTRUÇÕES PL/SQL ......................................................................................................... 83
SELECT INTO ................................................................................................................... 83
INSERT, UPDATE e DELETE........................................................................................... 83
EXERCÍCIOS PRÁTICOS ................................................................................................... 84
ESTRUTURAS DE CONTROLE ......................................................................................... 86
INSTRUÇÃO IF .................................................................................................................... 86
LOOPS (LAÇOS) .................................................................................................................. 87
EXERCÍCIOS PRÁTICOS ................................................................................................... 89
CURSORES EXPLÍCITOS ................................................................................................... 91
CURSORES IMPLÍCITOS ................................................................................................... 91
CURSORES EXPLÍCITOS .................................................................................................. 91

4
L A B O R A T O R I O D E B A N C O D E D A D O S

CONTROLANDO CURSORES EXPLÍCITOS ................................................................... 92


DECLARANDO O CURSOR ............................................................................................... 92
ABRINDO O CURSOR ........................................................................................................ 93
EXTRAINDO DADOS DO CURSOR.................................................................................. 93
FECHANDO O CURSOR..................................................................................................... 94
ATRIBUTOS DO CURSOR EXPLÍCITO............................................................................ 94
CONTROLANDO VÁRIAS EXTRAÇÕES ........................................................................ 94
ATRIBUTO %ISOPEN ........................................................................................................ 95
ATRIBUTOS %NOTFOUND E %ROWCOUNT ................................................................ 95
EXERCÍCIOS PRÁTICOS ................................................................................................... 96
EXCEÇÕES ............................................................................................................................ 97
CAPTURANDO UMA EXCEÇÃO ...................................................................................... 97
PROPAGANDO UMA EXCEÇÃO ...................................................................................... 98
TIPOS DE EXCEÇÃO .......................................................................................................... 98
CAPTURANDO ERROS PREDEFINIDOS......................................................................... 99
EXCEÇÃO PREDEFINIDA ............................................................................................... 100
EXCEÇÃO ZERO_DIVIDE ............................................................................................... 101
EXCEÇÃO DUP_VAL_ON_INDEX ................................................................................. 101
EXCEÇÃO INVALID_NUMBER ..................................................................................... 101
EXCEÇÃO OTHERS.......................................................................................................... 102
CAPTURANDO ERROS NÃO PREDEFINIDOS ............................................................. 102
ERROS NÃO PREDEFINIDOS ......................................................................................... 103
FUNÇÕES DE CAPTURA DE EXCEÇÕES ..................................................................... 103
CAPTURANDO EXCEÇÕES DEFINIDAS PELO USUÁRIO ......................................... 104
PROCEDIMENTO RAISE_APPLICATION_ERROR ...................................................... 105
EXERCÍCIOS PRÁTICOS ................................................................................................. 105
PROCEDURES..................................................................................................................... 106
MODOS DE PARÂMETRO ............................................................................................... 106
PARÂMETRO IN ................................................................................................................ 106
EXECUÇÃO DA PROCEDURE ........................................................................................ 107
SHOW ERRORS ................................................................................................................. 107
PARÂMETRO OUT ........................................................................................................... 108
PARÂMETRO IN OUT ...................................................................................................... 108
PARÂMETRO DEFAULT ................................................................................................. 109
ESPECIFICAR PARÂMETROS ........................................................................................ 109
DECLARANDO SUBPROGRAMAS ................................................................................ 109
REMOVENDO PROCEDIMENTOS ................................................................................. 110
INFORMAÇÕES SOBRE PROCEDURES ........................................................................ 110
INFORMAÇÕES SOBRE FUNÇÕES AS FUNCTONS CRIADAS NESTE USUARIO . 110
CÓDIGO DA FUNCAO CRIADA NESTE USUARIO...................................................... 110
EXERCÍCIOS PRÁTICOS ................................................................................................. 111
FUNCTIONS......................................................................................................................... 112
LOCAIS PARA CHAMAR FUNÇÕES DEFINIDAS ........................................................ 114
CHAMANDO FUNÇÕES A PARTIR DE EXPRESSÕES ................................................ 114
REMOVENDO FUNÇÕES ................................................................................................ 114
INFORMAÇÕES SOBRE FUNÇÕES AS FUNCTONS CRIADAS NESTE USUARIO . 114
CÓDIGO DA FUNCAO CRIADA NESTE USUARIO...................................................... 114

5
L A B O R A T O R I O D E B A N C O D E D A D O S

PROCEDIMENTO OU FUNÇÃO ...................................................................................... 115


EXEMPLO DE FUNÇÃO................................................................................................... 115
EXERCÍCIOS PRÁTICOS ................................................................................................. 116
PACKAGES .......................................................................................................................... 118
CRIANDO O PACOTE....................................................................................................... 119
EXECUTANDO UM PROCEDIMENTO DO PACOTE ................................................... 121
REMOVENDO PACOTES ................................................................................................. 121
INFORMAÇÕES DE FUNÇÕES E PROCEDURES EM PACOTES................................ 121
PACOTES FORNECIDOS PELO SERVIDOR ORACLE ................................................. 122
EXERCÍCIOS PRÁTICOS ................................................................................................. 122
TRIGGERS ........................................................................................................................... 123
COMPONENTES ............................................................................................................... 123
TEMPO DE GATILHO....................................................................................................... 124
TIPOS DE GATILHO ......................................................................................................... 124
CRIANDO UMA TRIGGER DE LINHA ........................................................................... 125
QUALIFICADORES: OLD(ANTIGO) E NEW(NOVO) ................................................... 126
RESULTADO DO QUALIFICADOR: ANTES E DEPOIS .............................................. 127
RESTRIÇÃO NA TRIGGER DE LINHA .......................................................................... 127
TRIGGER INSTEAD OF .................................................................................................... 127
ALTERANDO TRIGGERS ................................................................................................ 128
APAGANDO TRIGGERS .................................................................................................. 128
TRIGGER DE BANCO DE DADOS .................................................................................. 128
CRIANDO TRIGGER NAS INSTRUÇÕES DDL ............................................................. 128
EVENTOS DDL ............................................................................................................... 128
TRIGGER QUE ARMAZENA INFORMACOES DA DDL .............................................. 129
TRIGGER QUE ARMAZENA LOG .................................................................................. 130
EXERCÍCIOS PRÁTICOS ................................................................................................. 132
UTL_FILE............................................................................................................................. 133
XML COM PL/SQL ............................................................................................................. 137
XMLQUERY().................................................................................................................... 139
EXERCÍCIOS PRÁTICOS ................................................................................................. 140

6
L A B O R A T O R I O D E B A N C O D E D A D O S

INFORMAÇÕES IMPORTANTES

OBJETIVO
Implementar soluções de Banco de Dados por meio de tecnologias emergentes.

EMENTA
Tecnologias emergentes de mercado que serão aplicadas em laboratório com uso
de comandos da linguagem SQL e PL/SQL.

BIBLIOGRAFIA
• ALVES, William Pereira, Banco de Dados: Teoria e Desenvolvimento,
Érica, 2009.
• BJARKI, Hólm Et., Oracle 9i Java Programando: Soluções para
Desenvolvedores Que Trabalham com PL/SQL e Java AL, Alta Books,
2002.
• BRYLA, Bob, OCP Oracle Database 11g: Administração II, Porto Alegre:
Bookman, 2010.
• CHANG, Ben, Oracle XML: O manual oficial, Campus, 2001.
• ELMASRI, Ramez; Navathe, Shamkant B. , Sistemas de banco de dados,
Imprensa Oficial ,6 ed, 2011.
• PRICE, Jason, Oracle Database 11g Sql: Domine Sql e Pl/sql no Banco
de Dados Oracle, Bookman, 2009.
• RAMAKRISHNAN, Raghu, Sistemas de Gerenciamento de Banco de
Dados, Mc Graw Hill, 2008.
• Revista SQL MAGAZINE (http://www.sqlmagazine.com.br);
• Site: www.profissionaloracle.com.br;
• Estudo de Caso com script:
http://chinookdatabase.codeplex.com/releases/view/55169

SOFTWARES UTILIZADOS
• DBDesigner 4- software opensource;
• Oracle Data Modeler;
• BR Modelo – software freeware;
• Oracle 10G Express Edition1 (www.oracle.com.br2);
• Oracle 11G Express Edition (www.oracle.com.br3)

FALTAS PERMITIDAS NO SEMESTRE


• Quatro (4) aulas semanais e poderá ter vinte (20) faltas no semestre.

ABONO DE FALTAS
• Somente com atestado médico.

1 Software gratuito.
2 Necessário ter cadastro no site da Oracle, porém é gratuito.
3 Necessário ter cadastro no site da Oracle, porém é gratuito.

7
L A B O R A T O R I O D E B A N C O D E D A D O S

• No final do semestre, no caso de o aluno ter nota e ter entregado no mínimo


70% das atividades poderá eliminar as faltas através de atividade extra.
• Falta ou atraso do professor, o aluno não tem a falta lançada.

CONTATO

• Email: simone.romano@fatec.sp.gov.br ou simone@fatecpg.com.br


• TODOS OS EMAILS ENVIADOS SERÃO RESPONDIDOS EM UM PRAZO DE 48
HORAS. CASO NÃO HAJA RESPOSTA, FAVOR ENVIAR NOVAMENTE E POR
FAVOR IDENTIFICAR A FACULDADE, O CURSO, A DISCIPLINA E O PERÍODO.
• Solicito que todos deixem o email atualizado na secretaria da Fatec pois é por
este email que consta no seu cadastro que eu entro em contato, avisando
faltas, reposições, assuntos gerais, etc.

DIAS QUE ESTOU NA INSTITUIÇÃO


• TERÇA-FEIRA E SEXTA-FEIRA: TARDE;
• QUARTA-FEIRA E QUINTA-FEIRA: NOITE;
• SABADO: MANHÃ.

DATAS DA AVALIAÇÃO DO SEMESTRE


• P1 – 10/04/2019 (DAS 19h AS 20h50) e 12/04/2019 (DAS 14h as 16h);
• P2 – 05/06/2019 (DAS 19h AS 20H50) e 07/06/2019 (DAS 14h AS 16h).
• SUBSTITUTIVA: Data, Horário e local da prova marcada e enviada por email.
• EXAME/TCC: Data, Horário e local da prova a ser marcada e enviado por email.
PREVISTO PARA 12/06/2019 (SABADO) e 14/06/2019 (TARDE)

FORMA DE AVALIAÇÃO E CONTEÚDO


Sempre o conteúdo das avaliações será o apresentado até uma semana antes das
provas bimestrais, podendo ter eventualmente uma revisão antes da avaliação.
Todas as Tarefas Avaliativas terão pontuação desde que realizadas em sala de aula
ou entregues na próxima aula (somente quando o aluno esteve presente).

FORMA DE AVALIAÇÃO (PORTARIA Nº 61/2018 (AGO/2018):


Avaliação 1 (P1) – Prova presencial (data determinada em calendário letivo);
Avaliação 2 (P2) – Prova presencial (data determinada em calendário letivo);
Trabalho Prático (TRA) – atividade(s) prática(s) proposta(s) aos discentes a critério
do docente da disciplina. Cálculo: (P1 + P2 + TRA)/3 = MF
Nota final (MF) no semestre menor que 6,0 (seis inteiros) poderá realizar Prova
Substitutiva (data determinada em calendário letivo). Sendo:
§ 1 - A nota obtida na Prova Substitutiva maior que a menor nota obtida na P1 ou
P2, esta substituirá a referida nota menor, alterando para mais a MF anterior;
§ 2º - A nota obtida na Prova Substitutiva menor que a menor nota obtida na P1
ou P2, não haverá substituição, permanecendo a MF anterior.
Se desejar melhorar (aumentar) a nota final (MF) mesmo tendo alcançado valor
igual a superior a 6,0 (seis inteiros) poderá realizar Prova Substitutiva (data
determinada em calendário letivo). Sendo:
§ 1 - A nota obtida na Prova Substitutiva maior que a menor nota obtida na P1 ou
P2, esta substituirá a referida nota menor, alterando para mais a MF anterior;
§ 2º - A nota obtida na Prova Substitutiva menor que a menor nota obtida na P1
ou P2, não haverá substituição, permanecendo a MF anterior;

8
L A B O R A T O R I O D E B A N C O D E D A D O S

Será atribuída nota zero ao aluno que utilizar de meios ilícitos nos procedimentos
de avaliação do rendimento escolar.
Para aprovação, sendo todos os cursos presenciais, frequência mínima de 75%
(setenta e cinco por cento) no nosso caso, máximo 20 faltas por semestre, sendo
que falta do professor não acarreta falta ao aluno.

PERDA DE ATIVIDADE
ATENÇÃO!!!! CASO O ALUNO FALTE – INDEPENDENTE DE TER ATESTADO OU TER
ATESTADO – NÃO SERÁ ACEITO A TAREFA POIS O MESMO NÃO ASSISTIU A AULA.

ERROS DA APOSTILA
Caso seja encontrado erro na apostila, favor enviar por e-mail.

TRABALHO SEMESTRAL
Haverá dois trabalhos (um para cada bimestre), com valor de 5,0 pontos.
Dois cursos com emissão de certificado, cada um com data máxima para término
até 07/06/2019 (data da P2)

CURSO DA ORACLE ACADEMY


Programação de Banco de Dados com SQL
Conteúdo: Introdução, SELECT e WHERE, ORDER BY e Introdução a Funções de
Uma Única Linha, Junções, Funções de Grupo, Subconsultas, Garantindo
Consultas de Qualidade , DML, DDL, Constraints, Views, Sequências e Sinônimos,
Privilégios e Expressões Regulares.
Link a ser enviado por email. Com certificado de participação em pdf emitido pela
Oracle.

MICROSOFT POWER BI PARA DATA SCIENCE


Todos os dados, em qualquer lugar e a qualquer tempo. Esse é o slogan oficial do
Power BI no site da Microsoft. O Power BI traz consigo o conceito de self-service
BI, colocando nas mãos de qualquer profissional interessado em análise de dados,
a chance de criar visualizações e dashboards de alto nível, a partir da análise de
dados e com poucos cliques. O Power BI é um serviço de Business Analytics
baseado em nuvem que oferece uma visão única dos dados comerciais mais
críticos. É possível monitorar a saúde do negócio da empresa usando um
Dashboard interativo e em tempo real, criar relatórios interativos com o Power BI
Desktop e acessar os dados com aplicativos nativos do Power BI Mobile. É fácil,
rápido e gratuito. Mas esse curso oferece muito mais que o Power BI. Oferece a
chance de você incorporar modelos de Data Science a sua análise, integrando o
Power BI com o Microsoft R e usar uma das linguagens mais poderosas para análise
estatística, a linguagem R. Se você já é um profissional de BI é a sua chance de
iniciar sua transição para o incrível mundo das análises preditivas com Data
Science e Machine Learning.

Emissão de certificado em PDF após avaliação online. Deverá ser entregue


impresso no dia da P2 (prazo máximo).
Link: https://www.datascienceacademy.com.br/course?courseid=microsoft-
power-bi-para-data-science

ACESSANDO O BANCO DE DADOS ORACLE

9
L A B O R A T O R I O D E B A N C O D E D A D O S

Em nosso laboratório utilizamos a máquina virtual BANCO DE DADOS. Lá


encontram-se todos os softwares de modelagem e o SGBD Oracle.
Independentemente de ser o Oracle 10G ou Oracle 11G, vamos utilizar o
software linha de comando SQL.
Em nosso laboratório utilizamos a máquina virtual BANCO DE DADOS. Lá
encontram-se todos os softwares de modelagem e o SGBD Oracle.
Para acessar, clique no banco de dados Oracle Database 10G Express Edition
ou Oracle Database 11G Express Edition que se encontra em Todos os Programas
e acesse o software:

Figura 1 - Opções do Oracle Express Edition (feito pelo Autor)

Ao acessar este software é como se o mesmo estivesse acabado de ser


instalado. Portanto o procedimento abaixo deverá SEMPRE SER FEITO!!!!!
Obs. No seu computador, este procedimento deverá ser feito somente uma
vez. Passos:
Na tela abaixo faça o que se pede, digitando no prompt SQL:

Figura 2 - Tela principal do software Linha de Comando SQL (feito pelo Autor)

1. Conectar com o usuário administrativo:


CONNECT / AS SYSDBA

2. Desbloquear o usuário HR e colocar uma senha para ele:

10
L A B O R A T O R I O D E B A N C O D E D A D O S

ALTER USER HR IDENTIFIED BY HR ACCOUNT UNLOCK;


3. Conectar com este usuário. Obs. O fato de ter desbloqueado você ainda
continua conectado como SYSTEM:
CONNECT HR/HR

4. Deverá aparecer a mensagem. Conectado. Para confirmar digite:


SHOW USER

5. Iniciar um arquivo toda a aula com o comando SPOOL:


SPOOL C:\LBD_AULA01.TXT

ESTE COMANDO IRÁ CRIAR NA UNIDADE C:> UM ARQUIVO CHAMADO


BD_AULA01.TXT QUE DEVERÁ SER FINALIZADO COM SPOOL OFF. CASO
CONTRÁRIO VOCE PERDE TODO O SEU CONTEUDO QUE FICA NA MEMÓRIA.

6. Finalizar o arquivo no TÉRMINO DA AULA:


SPOOL OFF

Caso queira trocar a cor e o tamanho da fonte, na barra de título da janela,


clique com o botão direito do mouse e escolha a opção PROPRIEDADES:

Figura 3 – Tela principal do software Linha de Comando SQL – Propriedades (feito pelo Autor)

Escolha as abas COR e FONTE para mudar as características:

11
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 4 – Tela principal do software Linha de Comando SQL – Propriedades – Fonte (feito pelo Autor)

PROBLEMAS DE CONEXÃO

Caso no momento da conexão ocorra algum erro, efetuar os procedimentos


abaixo:

a. INTERROMPER O BANCO DE DADOS, esperar até chegar o prompt


conforme a tela abaixo:

12
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 5 - Tela Interromper o Banco de Dados – Fonte (feito pelo Autor)

b. Em seguida, clicar em INICIAR BANCO DE DADOS e esperar até retornar


ao prompt conforma a figura a seguir:

Figura 6 - Tela Iniciar o banco de dados – Fonte (feito pelo Autor)

MUDAR A PORTA DO ORACLEXE:


No menu iniciar aceder a: Oracle 10g.../Executar Linha de Comandos SQL
a. Escrever CONNECT
b. Username: SYSTEM e password: a que foi definida na instalação
c. Executar o comando: exec dbms_xdb.sethttpport(XXXX);
Obs.: onde XXXX é a porta desejada, por ex: 8087

PARTE GRÁFICA SERVIDOR FATEC


No laboratório digitar o seguinte endereço:
http://192.168.10.21:8080/apex/f?p=4550:11:3852338722054224::NO:::
Obs.: Este endereço só é acessado nas dependências da Fatec de Praia
Grande.

13
L A B O R A T O R I O D E B A N C O D E D A D O S

PARTE GRÁFICA LOCAL

Selecione , surge a tela abaixo, escolha Português (Brasil):

Figura 7 - Tela principal Oracle 11G Express Edition Gráfico (feito pelo Autor)

Selecione APPLICATION EXPRESS, surge a tela a seguir para ser preenchida


conforme abaixo:

Figura 8 – Tela do Application Express (feito pelo Autor)

14
L A B O R A T O R I O D E B A N C O D E D A D O S

Caso queira usar uma conta já cadastrada anteriormente, clique em

e surge a tela a seguir:

Figura 9 - Tela do Application Express de contas já cadastradas (Feito pelo autor)

Selecione o idioma português (Brasil), digite o nome do espaço, usuário e


senha e pressione o botão LOGIN, surge a tela a seguir:

Figura 10 - Tela do Espaço de Trabalho do Usuário HR (Feito pelo autor)

15
L A B O R A T O R I O D E B A N C O D E D A D O S

Selecione a opção BROWSER DE OBJETOS e surge a tela a seguir:

Figura 11 - Tela do Espaço de Trabalho do Usuário HR (Feito pelo autor)

Selecione a opção CRIAR e surge a tela a seguir:

Figura 12 - Tela do Espaço de Trabalho do Usuário HR (Feito pelo autor)

16
L A B O R A T O R I O D E B A N C O D E D A D O S

Ao selecionar um tipo de objeto do lado esquerdo, surge as procedures,


clique em um dos arquivos e surge a tela abaixo com o código:

Figura 13 - Texto do código da procedure (Feito pelo autor)

DICIONÁRIO DE DADOS - ESQUEMA HR:

Quadro 1 - Tabelas do Esquema HR (feito pelo Autor)

DEPARTMENTS (departamento)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
DEPARTMENT_ID NUMBER (4) – PK Código do departamento
DEPARTMENT_NAME VARCHAR2(30) Nome do departamento
MANAGER_ID NUMBER (6) Código do gerente do
departamento
LOCATION_ID NUMBER (4) – FK Código da localização do
departamento
REGIONS (região)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
REGION_ID NUMBER – PK Código da região
REGION_NAME VARCHAR2(25) Nome da região
JOBS (cargo)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
JOB_ID VARCHAR2(10) – Código do cargo
PK
JOB_TITLE VARCHAR2(35) Nome do cargo
MIN_SALARY NUMBER (6) Menor salário do cargo
MAX_SALARY NUMBER (6) Maior salário do cargo

17
L A B O R A T O R I O D E B A N C O D E D A D O S

LOCATIONS (localização)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
LOCATION_ID NUMBER (4) – PK Código da localização
STREET_ADDRESS VARCHAR2(40) Endereço da localização
POSTAL_CODE VARCHAR2(12) Código postal da localização
CITY VARCHAR2(30) Nome da cidade
STATE_PROVINCY VARCHAR2(25) Nome do estado
COUNTRY_ID CHAR (2) – FK Identificação do país
COUNTRIES (país)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
COUNTRY_ID CHAR (2) – PK Identificação do país
COUNTRY_NAME VARCHAR2(40) Nome do país
REGION_ID NUMBER – FK Identificação da região
EMPLOYEES (empregado)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
EMPLOYEE_ID NUMBER (6) – PK
Identificação do empregado
FIRST_NAME VARCHAR2(20)
Primeiro nome do empregado
LAST_NAME VRCHAR2(25)
Último nome do empregado
EMAIL VARCHAR2(25)
Email do empregado
PHONE_NUMBER VARCHAR2(20)
Telefone do empregado
HIRE_DATE DATE
Data de admissão do
empregado
JOB_ID VARCHAR2(10) Cargo do empregado
SALARY NUMBER (8,2) Salário do empregado
COMMISSION_PCT NUMBER (2,2) Percentual de comissão do
empregado
MANAGER_ID NUMBER (6) Identificação do gerente do
empregado
DEPARTMENT_ID NUMBER (4) - FK Identificação do departamento
JOB_HISTORY(histórico_cargos)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
EMPLOYEE_ID NUMBER (6) – PK Identificação do empregado
START_DATE DATE Data início do empregado no
cargo
END_DATE DATE Data final do empregado no
cargo
JOB_ID VARCHAR2(10) – Identificação do cargo
FK
DEPARTMENT_ID NUMBER (4) – FK Identificação do departamento

18
L A B O R A T O R I O D E B A N C O D E D A D O S

MODELO LÓGICO DE DADOS DO ESQUEMA HR

Figura 14– Modelo Lógico de Dados do Esquema HR (feito pelo Autor)

19
L A B O R A T O R I O D E B A N C O D E D A D O S

OUTROS ESQUEMAS

USUÁRIO LOJA:
Quadro 2 - Tabelas do Esquema LOJA

CUSTOMERS (cliente)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CUSTOMER_ID INTEGER (PK)
Identificação do cliente
FIRST_NAME VARCHAR2(10)
Nome do Cliente
LAST_NAME VARCHAR2(10)
Sobrenome do cliente
DOB DATE Data de Nascimento do
cliente
PHONE VARCHAR2(12) Número do telefone do cliente
PRODUCT_TYPES (tipos de produtos)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
PRODUCT_TYPE_ID INTEGER(PK) Identificação do tipo do
produto
NAME VARCHAR2(10) Nome do tipo do produto
PRODUCTS (produtos)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
PRODUCT_ID INTEGER(PK)
Identificação do produto
PRODUCT_TYPE_ID INTEGER(FK)
Identificação do tipo do
produto
NAME VARCHAR2(30) Nome do produto
DESCRIPTION VARCHAR2(50) Descrição do produto
PRICE NUMBER(5,2) Valor do produto
PURCHASES(compras feitas por um cliente)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
PRODUCT_ID INTEGER(PK) – Identificação do produto
FK
CUSTOMER_ID INTEGER(PK) – Identificação do cliente
FK
QUANTITY INTEGER Quantidade de produto
adquirida
EMPLOYEES (empregado)
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
EMPLOYEE_ID INTEGER – PK
Identificação do empregado
FIRST_NAME VARCHAR2(10)
Primeiro nome do empregado
LAST_NAME VRCHAR2(10)
Último nome do empregado
TITLE VARCHAR2(20)
Cargo do empregado
SALARY NUMBER(6,0)
Salário do empregado
MANAGER_ID INTEGERIdentificação do gerente do
empregado
SALARY_GRADES(níveis salariais)
NOME DA COLUNA TIPO DESCRIÇÃO
SALARY_GRADE_ID INTEGER (PK) Identificação da faixa salarial
LOW_SALARY NUMBER(6,0) Início da faixa salarial
HIGH_SALARY NUMBER(6,0) Fim da faixa salarial

20
L A B O R A T O R I O D E B A N C O D E D A D O S

USUÁRIO COMPLETO
Quadro 3 - Tabelas do Esquema COMPLETO

EMPRESA
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
EMP_CODIGO INTEGER(PK) Código da empresa
EMP_NOME VARCHAR2(30) Nome da empresa
EMP_ENDERECO VARCHAR2(100) Endereço da empresa
EMP_TELEFONE VARCHAR2(15) Telefone da empresa
FILIAL
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
EMP_CODIGO INTEGER (PK FK) Código da empresa
FILIAL_NRO INTEGER(PK) Código da filial
FILIAL_LOCAL VARCHAR2(30) Local da filial
FILIAL_DATA_ABERTURA DATE Data da abertura da filial
FUNCIONARIO
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
FUN_CODIGO INTEGER(PK) Código do funcionário
PRIMEIRO_NOME VARCHAR2(30) Nome do funcionário
SOBRENOME VARCHAR2(30) Sobrenome do funcionário
FUN_ENDERECO VARCHAR2(100) Endereço do funcionário
FUN_SEXO CHAR (1) Sexo do funcionário (f ou
m)
FUN_NIVER DATE Data do aniversário do
funcionário
FUN_SALARIO FLOAT Salário do funcionário
TIPO_FUNCIONARIO VARCHAR2(10) Função do funcionário
(secretario/motorista)
EMP_CODIGO INTEGER (FK) Código da empresa
COD_SUPERVISOR INTEGER Código do supervisor do
funcionário
MOTORISTA
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
FUN_CODIGO INTEGER(PK) Código do funcionário
NUM_CARTEIRA INTEGER Código da carteira de
motorista
CLASSE CHAR (1) Classe da carteira (B ou D)
SECRETARIO
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
FUN_CODIGO INTEGER(PK) Código do funcionário
NUM_CERTIFICACAO INTEGER Número do certificado
DATA_EXPEDICAO DATE Data da expedição do
certificado
CLIENTE
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CLI_CODIGO INTEGER(PK) Código do cliente
CLI_NOME VARCHAR2(30) Nome do cliente
CLI_TELEFONE VARCHAR2(15) Telefone do cliente

21
L A B O R A T O R I O D E B A N C O D E D A D O S

EMP_CODIGO INTEGER (FK) Código da empresa


ALUGA
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CLI_CODIGO INTEGER(PK) Código do cliente
CAR_CHASSI VARCHAR2(30) Chassi do veículo alugado
DIRIGE
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CAR_CHASSI VARCHAR2(30) Chassi do veículo alugado
(PK)
FUN_CODIGO INTEGER (PK) Código do funcionário
DATA DATE (PK) Data do aluguel do veículo
NRO_HORAS INTEGER Quantidade de horas
dirigidas
CARRO
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CAR_CHASSI VARCHAR2(30) Chassi do veículo
(PK)
CAR_MODELO VARCHAR2(30) Modelo do veículo
CAR_ANO INTEGER Ano do veículo
EMP_CODIGO INTEGER (FK) Código da empresa
DEPENDENTE
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
FUN_CODIGO INTEGER (PK FK) Código do funcionário
DEP_NOME VARCHAR2(50) Nome do dependente
(PL)
DEP_SEXO VARCHAR2(10) Sexo do dependente
DEP_DATA_NIVER DATE Data de aniversário do
dependente
PARENTESCO VARCHAR2(20) Parentesco do dependente
CLIENTE_LOCACAO
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
CLI_CODIGO INTEGER (PK FK) Código do cliente
DATA DATE Data da locação
NF_NUMERO INTEGER Número da locação
NF_VALOR FLOAT Valor da locação
DESCONTO FLOAT Desconto na locação
VALOR_LOCACAO
NOME DA COLUNA TIPO E TAMANHO DESCRIÇÃO
DATA_REAJUSTE DATE (PK) Data do reajuste do valor
CAR_ANO INTEGER (PK) Ano do carro
CAR_MODELO VARCHAR2(30) Modelo do carro
(PK)
VALOR FLOAT Valor do reajuste

22
L A B O R A T O R I O D E B A N C O D E D A D O S

ORACLE 11G RELEASE EXPRESS EDITION


Em 2011, a ORACLE disponibilizou esta versão gratuita que possui recursos
client-server com algumas limitações para a sua utilização. Baseada no código do
11g Release 2 e é mais “leve”.
Além disso, a versão XE não traz alguns dos recursos presentes no 11g
“normal”, como a tecnologia Oracle RAC (Real Application Clusters), nem algumas
opções de segurança, como o Oracle Database Vault e o SecureFiles Encryption.
Também há limitação de quantidade de dados - o usuário no banco de dados
XE não deve ultrapassar 11 GB e ele não pode usar mais de 1 GB de memória
RAM. Os interessados em mais capacidade devem migrar para a versão paga.

INSTALAÇÃO

O arquivo para instalação é o OracleXE112_Win32.zip, deverá ser extraído


em uma pasta, clique em DISK1 e execute o arquivo SETUP.EXE. Surge a tela
abaixo:

Figura 15 - Tela para Instalação do Oracle (feito pelo Autor)

Ao surgir a tela de apresentação do programa abaixo, clique no botão


PROXIMO:

23
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 14 – Tela para Instalação do Oracle (feito pelo Autor)

A seguir, selecione ACEITO OS TERMOS DE ACORDO DE LICENÇA e clique no


botão AVANÇAR:

Figura 15 – Tela de Contrato de Licença Oracle (feito pelo Autor)

Nesta etapa poderá ser escolhida uma outra pasta de destino e clique em
Próximo:

24
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 16 – Tela de Destino do Programa Oracle (feito pelo Autor)

Nesta etapa especifique uma senha para as contas administrativas SYS e


SYSTEM. Obs. Muito importante!!!!

Figura 17 – Tela de Senhas Administrativas (feito pelo Autor)

Nesta tela são exibidas as informações de resumo que serão usadas na


instalação, clique no botão INSTALAR:

25
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 18 – Tela de Resumo das Configurações (feito pelo Autor)

Agora o assistente vai iniciar a instalação... Aguarde!!!

Figura 19 – Tela de Status da Instalação (feito pelo Autor)

Pronto!!! O Oracle está instalado, clique no botão CONCLUIR:

26
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 20 – Tela de Finalização da Instalação (feito pelo Autor)

27
L A B O R A T O R I O D E B A N C O D E D A D O S

REVISÃO DE BANCO DE DADOS

Nesta aula fazendo uma revisão de banco de dados como tarefa avaliativa.
Estudo de Caso: Com base no modelo abaixo faça o que se pede a seguir:

a) Criar um fluxo de dados;


b) Identificar os candidatos a objetos;
c) Criar o modelo lógico de dados com navegação no modelo;
d) Criar um script contendo:
a. Criar as tabelas que atendam o modelo com todas as restrições;
b. Inserir no mínimo cinco registros de forma implícita e explicita nas
tabelas;
c. Atualizar o valor das mercadorias que iniciem com a letra A ou C em
10% de aumento;
d. Exibir com os comandos: básico, funções de linha, funções de grupo
e junção de tabelas (com descritivo e resultado).

28
L A B O R A T O R I O D E B A N C O D E D A D O S

SUBCONSULTA (SUBQUERIE)

Consiste em uma consulta utilizada dentro de um comando SQL. Há várias


situações em que as subconsultas são necessárias, como por exemplo:
Mostrar os funcionários que recebam mais que a média dos salários;
Atualizar em 10% o salário do funcionário que mais recebe etc.
Uma subconsulta pode ser utilizada dentro de um comando SELECT, UPDATE,
CREATE TABLE, DELETE ou INSERT. Uma subconsulta não possui uma cláusula
ORDER BY. Há os seguintes tipos de subconsultas:
• UMA LINHA → retorna apenas um valor;
• MÚLTIPLAS LINHAS → podem retornar um ou mais valores, mas em uma
coluna;
• MÚLTIPLAS COLUNAS → retornam um ou mais valores em mais de uma
coluna;
• CORRELATAS → utilizam campos da consulta externa como parâmetro para
consulta interna.
Observações:
• As subconsultas sempre serão entre parênteses;
• Coloque no lado direito da condição de comparação;
• Não é necessário a ORDER BY na subconsulta (somente para análise TOP-N).
Podemos ainda utilizar os operadores:

Quadro 4 – Tipos de Operadores de Subquerie (feito pelo Autor)

OPERADOR OBSERVAÇÃO
=, <>, >, <, >=, Usado em subconsulta de uma linha.
<=
IN Teste se um valor pertence a um conjunto de
valores.
NOT IN Teste se um valor não pertence a um conjunto
de valores.
ANY Verifica se um determinado argumento casa
com qualquer membro de um conjunto.
ALL Verifica se um determinado argumento casa
com todos os membros de um conjunto.
EXISTS Usado em subconsulta correlatas, vê se um dado
valor existe em um conjunto, levando em conta
valores nulos. Este fato não é considerado pelo
operador in.
NOT EXISTS Nega o anterior.

UMA LINHA
SELECT last_name, salary
FROM employees
WHERE salary = (SELECT MAX (salary) FROM employees);

29
L A B O R A T O R I O D E B A N C O D E D A D O S

SELECT last_name, salary


FROM employees
WHERE salary > (SELECT salary FROM employees
WHERE last_name = 'Abel');

UPDATE employees
SET salary = 1.1 * salary
WHERE salary = (SELECT MIN (salary) FROM employees);

CREATE TABLE emp_dept AS


SELECT e.last_name Nome, d.department_name Depto, e.salary Salario
FROM employees e, departments d
WHERE d.department_id = e.department_id
AND salary > (SELECT AVG(salary) FROM employees);

DELETE FROM emp_dept


WHERE salario = (SELECT MIN(salario) FROM emp_dept);

INSERT INTO emp_dept (nome, salario)


SELECT last_name, salary
FROM employees
WHERE salary < (SELECT AVG(salary) FROM employees);

MÚLTIPLAS LINHAS

SELECT COM IN
Exemplo: Localize os funcionários que recebem o mesmo salário que o salário
mínimo dos departamentos.
SELECT last_name, salary, department_id
FROM employees
WHERE salary IN (SELECT MIN(salary)
FROM employees
GROUP BY department_id);

SELECT COM ANY

Exemplo: Exibir os funcionários cujo salário é menor que o de qualquer escriturário


e que não são escriturários.
SELECT employee_id, last_name, job_id

30
L A B O R A T O R I O D E B A N C O D E D A D O S

FROM employees
WHERE salary < ANY (SELECT salary
FROM employees
WHERE job_id = 'ST_CLERK')
AND job_id <> 'ST_CLERK';

Obs.: < ANY: significa menos do que o máximo.


> ANY: significa mais do que o mínimo.

SELECT COM ALL


Exemplo: Exibir os funcionários cujo salário é maior que os salários médios de
todos os departamentos.
SELECT employee_id, last_name, job_id
FROM employees
WHERE salary > ALL (SELECT AVG(salary)
FROM employees GROUP BY department_id);
Obs.: > ALL: significa mais do que o máximo.
< ALL: significa menos do que o mínimo.

SUBCONSULTA NA CLÁUSULA FROM

Exemplo: Exibir o nome, salário dos funcionários, número de departamento


e salário médio de todos os funcionários que recebem mais que o salário médio
nos seus departamentos:
SELECT e.last_name, e.salary, e.department_id, b.salavg
FROM emp e, (SELECT department_id, avg(salary) salavg
FROM employees
GROUP BY department_id) b
WHERE e.department_id = b.department_id
AND e.salary > b.salavg;

COMPARAÇÕES DE COLUNA
As comparações de coluna em sub-consultas de várias colunas podem ser
emparelhadas ou não-emparelhadas.

COMPARAÇÃO EMPARELHADA
Exemplo: Exibir os detalhes dos funcionários que são gerenciados pelo
mesmo gerente e que trabalham no mesmo departamento que os funcionários
com employee_id 178 ou 174:

31
L A B O R A T O R I O D E B A N C O D E D A D O S

SELECT employee_id, manager_id, department_id


FROM employees
WHERE (manager_id, department_id) IN
(SELECT manager_id, department_id
FROM employees
WHERE employee_id IN (174, 178))
AND employee_id NOT IN (174,178);

COMPARAÇÃO NÃO-EMPARELHADA
Exemplo: Exibir os detalhes dos funcionários que são gerenciados pelo
mesmo gerente e que trabalham no mesmo departamento que os funcionários
com employee_id 141 ou 174:
SELECT employee_id, manager_id, department_id FROM employees
WHERE (manager_id IN (SELECT manager_id
FROM employees
WHERE employee_id IN (174, 141))
AND (department_id IN (SELECT department_id
FROM employees
WHERE employee_id IN (174,141));
AND employee_id NOT IN (174,141);

SUBCONSULTA ESCALAR

Uma expressão de sub-consulta escalar é uma sub-consulta que retorna


exatamente um valor de coluna de uma linha. Podem ser usadas em:
• Condição e uma parte de expressão de DECODE e CASE;
• Todas as cláusulas SELECT, exceto GROUP BY.
Exemplo: A consulta interna retorna o valor 20 (id do departamento com o id
do local 1800). A consulta externa usa o resultado da consulta interna para exibir
o id do funcionário, sobrenomes e o nome do local:
SELECT employee_id, last_name,
(CASE WHEN department_id = (SELECT department_id
FROM departments
WHERE location_id = 1800)
THEN 'Canada' ELSE 'USA' END)
FROM employees;

Exemplo: Ordena a saída com base na coluna department_id:


SELECT employee_id, last_name,
FROM employees e
ORDER BY (SELECT department_name
FROM departments d
WHERE e.department_id = d.department_id);

32
L A B O R A T O R I O D E B A N C O D E D A D O S

SUBCONSULTA CORRELACIONADA

É quando a subconsulta faz referência a uma coluna de uma tabela


referenciada na instrução mãe. Ela é avaliada uma vez para cada linha processada
pela instrução mãe. A instrução mãe pode ser um SELECT, UPDATE ou DELETE.
Exemplo: Localize todos os funcionários que ganham acima do salário médio de
seus respectivos departamentos:
SELECT last_name, salary, department_id
FROM employees e
WHERE salary > (SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id);

Exemplo: Exibir detalhes dos funcionários que mudaram de cargo no mínimo


duas vezes:
SELECT e.employee_id, last_name, e.job_id
FROM employees e
WHERE 2 <= (SELECT COUNT(*)
FROM job_history
WHERE employee_id = e.employee_id);

EXISTS

Testa a existência de linhas no conjunto de resultados da sub-consulta. Este


operador garante que a consulta interna seja interrompida quando encontra no
mínimo uma ocorrência.
Exemplo: Localize os funcionários com no mínimo uma pessoa subordinada a
eles:
SELECT employee_id, last_name, job_id, department_id
FROM employees e
WHERE EXISTS (SELECT 'x' FROM employees
WHERE manager_id = e.employee_id);

Também podemos usar o operador IN:


SELECT employee_id, last_name, job_id, departament_id
FROM employees
WHERE employee_id IN (SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL);

NOT EXISTS
Testa a existência de linhas no conjunto de resultados da sub-consulta. Este
operador garante que a consulta interna seja interrompida quando encontra no
mínimo uma ocorrência.

33
L A B O R A T O R I O D E B A N C O D E D A D O S

Exemplo: Localize os funcionários com no mínimo uma pessoa subordinada a


eles:
SELECT employee_id, last_name, job_id, department_id
FROM employees e
WHERE NOT EXISTS (SELECT 'x' FROM employees
WHERE department_id = d.department_id);

Solução Alternativa:
SELECT department_id, department_name
FROM departments
WHERE department_id NOT IN (SELECT department_id FROM employees);

Obs.: NOT IN é avaliado como FALSO, se um dos elementos for nulo.

UPDATE CORRELACIONADA
Podemos utilizar subconsulta correlacionada para atualizar as linhas de uma
tabela com base nas linhas de outra tabela. Exemplo: Altere o padrão da tabela
EMPLOYEES adicionando uma coluna para armazenar o nome do departamento e
preenche a tabela usando uma atualização correlacionada:
ALTER TABLE employee
ADD (department_name VARCHAR2(14));

UPDATE employees e
SET department_name = (SELECT department_name
FROM departaments d
WHERE e.department_id = d.department_id);

DELETE CORRELACIONADA

Podemos utilizar uma subconsulta correlacionada para deletar linhas de uma


tabela com base nas linhas de outra tabela. Exemplo: Delete somente as linhas da
tabela EMPLOYEES que também existem na tabela JOB_HISTORY:
DELETE FROM employees e
WHERE employee_id = (SELECT employee_id
FROM job_history
WHERE employee_id = e.employee_id);

34
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS
1. Crie uma consulta para exibir o sobrenome e a data de admissão de todos os
funcionários no mesmo departamento do funcionário com sobrenome Zlotkey.
Exclua Zlotkey.
2. Cria uma consulta para exibir o número e o nome de todos os funcionários que
recebam mais que o salário médio. Classifique os resultados, por salário, em
ordem decrescente.
3. Crie uma consulta que exiba o número e o sobrenome de todos os funcionários
que trabalhem em um departamento com qualquer funcionário cujo sobrenome
contenha uma letra u.
4. Exiba o sobrenome do funcionário, o número do departamento e o cargo de
todos os funcionários cuja localização do departamento seja 1700.
5. Exiba o sobrenome e o salário dos funcionários que se reportem a King.
6. Exiba o número do departamento, o sobrenome e o cargo de todos os
funcionários do departamento de Executive (executivo).
7. Exibir o número, o sobrenome e o salário de todos os funcionários que recebam
mais que o salário médio e trabalhem em um departamento com qualquer
funcionário cujo nome contenha um u.
8. Localize todos os funcionários que não são supervisores.
9. Crie uma consulta para exibir o sobrenome, o numero do departamento e o
salário de qualquer funcionário cujo salário coincidam com o numero de
departamento e salário de qualquer funcionário que receba comissão.
10. Crie uma consulta para exibir o sobrenome, a data de admissão e o salário de
todos os funcionários que tenham o mesmo salário e a mesma comissão do
funcionário com sobrenome Kochhar. Obs. Não exibir Kochhar no conjunto de
resultados.
11. Crie uma consulta para exibir os funcionários que recebem um salário mais alto
do que o salário dos gerentes de vendas JOB_ID = ‘SA_MAN’. Classifique os
resultados dos salários do maior para o menor.
12. Exibir os detalhes do ID dos funcionários, o sobrenome e o ID do departamento
dos funcionários que vivem em cidades que começam com a letra T.
13. Descubra todos os funcionários que não são supervisores:
a) Utilizar o operador NOT EXISTS;
b) Pode ser feito com o operador NOT IN? Como ou por que não?
14. Crie uma consulta para exibir os sobrenomes dos funcionários que recebam
menos que o salário médio nos respectivos departamentos.
15. Crie uma consulta para exibir os sobrenomes dos funcionários que tem um ou
mais colegas de trabalho nos respectivos departamentos com datas de
admissão posteriores, mas com salários mais altos.

35
L A B O R A T O R I O D E B A N C O D E D A D O S

RECUPERAÇÃO HIERÁRQUICA

Podemos recuperar dados com base em um relacionamento hierárquico


natural entre as linhas de uma tabela. Um banco de dados relacional não armazena
registros de forma hierárquica. No entanto, onde existir um relacionamento
hierárquico entre as linhas de uma tabela simples, um processo denominado
PERCURSO DE ÁRVORE permitirá a construção da hierarquia. É um método para
elaborar um relatório das ramificações de uma árvore, em ordem.

King
employee_id =
100 (PAI)
De Hann Zlotkey Hartstein
Kochhar
manager_id=10 Mourgos manager_id=10 manager_id=10
manager_id=10 0 0 0
0 manager_id=10
(FILHO) 0 (FILHO) (FILHO)
(FILHO)
(FILHO)
Whalen Higgins Hunold
Rajs Davies Matos Vargas Abel Taylor Grant Fay

Ernst

Lorentz

Sintaxe:
SELECT [LEVEL] coluna
FROM tabela
WHERE condição
[START WITH condição]
[CONNECT BY PRIOR condição];

Onde:
• LEVEL: retorna 1 para uma linha-raiz e 2 para um filho de uma raiz e
assim por diante.
• START WITH: especifica as linhas-raiz da hierarquia (onde começar). É
obrigatória para uma consulta hierárquica verdadeira.
• CONNECT BY PRIOR: especifica as colunas nas quais existe o
relacionamento entre linhas mãe e linhas filhas. Obrigatória.

PERCORRENDO A ÁRVORE DE BAIXO PARA CIMA


Exemplo: Exibe uma lista de gerentes começando com o funcionário com ID
número 101:
SELECT employee_if, last_name, job_id, manager_id FROM employees
START WITH employee_id = 101
CONNECT BY PRIOR manager_id = employee_id;

36
L A B O R A T O R I O D E B A N C O D E D A D O S

PERCORRENDO A ÁRVORE DE CIMA PARA BAIXO


Exemplo: Exibe os nomes dos funcionários e seus respectivos gerentes. Use
o funcionário King como ponto inicial:
SELECT last_name || ' se reporta ao ' || PRIOR last_name FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id;

FORMATANDO RELATÓRIOS HIERÁRQUICOS

Crie um relatório que exiba os níveis de gerenciamento da empresa,


começando com o nível mais alto e recuando cada um dos níveis a seguir:
COLUMN org FORMAT A12
SELECT LPAD(last_name, LENGTH(last_name)+LEVEL*2)-2, '_' ) org
FROM employees
START WITH last_name = 'King'
CONNECT BY PRIOR employee_id = manager_id;

Obs.: A linha com LPAD define o formato da exibição.

Explicação do funcionamento da linha:


• King (nível 1) → Portanto (2*1)-2 = 2 – 2 = 0 (assim não precisa ser
preenchido com o caractere _ e na coluna 1);
• Kochhar (nível 2) → Portanto (2*2)-2 = 4 – 2 = 2 (assim é preenchido
com dois caracteres _ _ e recuado).
COMPACTANDO RAMIFICAÇÕES

Podemos usar WHERE e CONNECT BY para compactar ramificações da árvore,


ou seja, para controlar as linhas ou os nós que serão exibidos.
Exemplo: Percorre a árvore de cima para baixo e elimine o funcionário Higgins
no resultado, mas, exiba os filhos:
SELECT department_id, employee_id, last_name, job_id, salary
FROM employees
WHERE last_name != 'Higgins'
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id;

SELECT department_id, employee_id, last_name, job_id, salary


FROM employees
START WITH manager_id IS NULL
CONNECT BY PRIOR employee_id = manager_id
AND last_name != 'Higgins';

37
L A B O R A T O R I O D E B A N C O D E D A D O S

MANIPULANDO DADOS – OUTROS CONCEITOS

MERGE
O SQL foi estendido de modo a incluir a instrução MERGE. Quando usar essa
instrução, podemos atualizar ou inserir uma linha condicionalmente em uma
tabela, evitando várias instruções UPDATE. A decisão referente à atualização ou
inserção da tabela de destino se baseia em uma condição na cláusula ON. Este
comando combina o INSERT e o UPDATE, por isto, precisamos possuir estes dois
privilégios. Com este comando não é possível atualizar a mesma linha da tabela
de destino várias vezes na mesma instrução. Sintaxe:
MERGE INTO tabela apelido_tabela
USING (tabela|view|subconsulta) apelido
ON (condição_junção)
WHEN MATCHED THEN
UPDATE SET coluna1 = valor1, coluna2 = valor2
WHEN NOT MATCHED THEN
INSERT (coluna1, coluna2)
VALUES (valor1, valor2);

Exemplo: Inserir/atualizar a tabela COPY_EMP para que corresponda à


EMPLOYEES:
MERGE INTO copy_emp c
USING employees e
ON (c.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email = e.email,
c.phone_number = e.phone_number,
c.hire_date = e.hire_date,
c.job_id = e.job_id,
c.salary = e.salary,
c.commission_pct = e.commission_pct,
c.manager_id = e.manager_id,
c.department_id = e.department_id
WHEN NOT MATCHED THEN
INSERT VALUES (e.employee_id, e.first_name, e.last_name, e.email,
e.phone_number, e.hire_date,e.job_id,e.salary,
e.commission_pct, e.manager_id, e.department_id);

TRANSAÇÃO → SAVEPOINT
Já vimos que os comandos DML (INSERT, UPDATE, DELETE e MERGE)
precisam de confirmação de transação (COMMIT) ou cancelamento da mesma
(ROLLBACK). O comando SAVEPOINT marca um ponto de salvamento na transação
atual. Podemos ainda utilizar o comando ROLLBACK TO SAVEPOINT para efetuar
o cancelamento da transação atual até o ponto de salvamento especificado,
descartando, portanto, todas as alterações e/ou pontos de salvamento criados
depois do ponto de salvamento especificado para o rollback. Se for omitida a
cláusula TO SAVEPOINT, a instrução ROLLBACK será efetuado o rollback da

38
L A B O R A T O R I O D E B A N C O D E D A D O S

transação inteira. Como estes pontos de salvamento são lógicos, não há como
listá-los. Passos:
• Faça um comando DML;
• Crie um marcador em uma transação atual usando a instrução SAVEPOINT;
• Faça o cancelamento deste marcador usando a instrução ROLLBACK TO
SAVEPOINT.
INSERT MULTITABELAS
Podemos inserir linhas calculadas derivadas das linhas retornadas da
avaliação de uma subconsulta em uma ou mais tabelas. Pode desempenhar uma
função muito útil em um cenário de data warehouse.
Tipos de Instruções:
INSERT incondicional;
ALL INSERT condicional;
FIRST INSERT condicional;
INSERT de criação de pivôs.

Sintaxe:
INSERT [ALL] [condição da cláusula INSERT]
[ valores da cláusula do INSERT] (subconsulta)

Onde (condição da cláusula INSERT):


[ALL] [FIRST]
[WHEN condição THEN] [valores da clausula INSERT]
[ELSE [valores da cláusula INSERT]]

INSERT ALL INCONDICIONAL

CREATE TABLE sal_history (empid, hiredate, sal)


AS
SELECT employee_id, hire_date, salary
FROM employees;

CREATE TABLE mgr_history (empid, mgr, sal)


AS
SELECT employee_id, manager_id, salary
FROM employees;

TRUNCATE TABLE mgr_history;

TRUNCATE TABLE sal_history;

39
L A B O R A T O R I O D E B A N C O D E D A D O S

Exemplo: Selecione os valores de employee_id, hire_date, salary e


manager_id da tabela EMPLOYEES para os funcionários cujo employee_id é maior
que 200. Inserir estes valores nas tabelas: SAL_HISTORY e MGR_HISTORY usando
um INSERT mult-itabelas:
INSERT ALL
INTO sal_history VALUES (empid, hiredate, sal)
INTO mgr_history VALUES (empid, mgr, sal)
SELECT employee_id empid, hire_date hiredate, salary sal, manager_id mgr
FROM employees
WHERE employee_id > 200;

INSERT ALL CONDICIONAL

Exemplo: Selecione os valores de employee_id, hire_date, salary e


manager_id da tabela employees para os funcionários cujo employee_id é maior
que 200. Se o salário for superior a 10.000, inserir na tabela SAL_HISTORY usando
uma instrução INSERT multitabelas condicional. Se MANAGER_ID for maior que
200, inserir estes valores na tabela MGR_HISTORY usando um INSERT
multitabelas condicional:
INSERT ALL
WHEN sal > 10000 THEN
INTO sal_history VALUES (empid, hiredate, sal)
WHEN mgr > 200 THEN
INTO mgr_history VALUES (empid, mgr, sal)
SELECT employee_id empid, hire_date hiredate, salary sal, manager_id mgr
FROM employees
WHERE employee_id > 200;

FIRST INSERT CONDICIONAL

Exemplo: Selecione department_id, sum(salary) e max(hire_date) na


tabela employees. Se sum(salary) for superior a 25.000, insira esses
valores na tabela SPECIAL_SAL, usando uma instrução INSERT multi-
tabelas FIRST Condicional. Se a primeira cláusula WHEN for avaliada como
verdadeira, as cláusulas WHEN subseqüentes para essa linha serão
ignoradas. Inserir linhas que não atendem à primeira condição WHEN na
tabela HIREDATE_HISTORY_00, HIREDATE_HISTORY_99 ou
HIREDATE_HISTORY, com base no valor da coluna hire_date usando uma
instrução INSERT multi-tabelas condicional:
CREATE TABLE special_sal (depid, sal)
AS
SELECT department_id, salary FROM employees;

CREATE TABLE hiredate_history_00 (deptid, hiredate)


AS
SELECT department_id, hire_date FROM employees;

40
L A B O R A T O R I O D E B A N C O D E D A D O S

TRUNCATE TABLE special_sal;

TRUNCATE TABLE hiredate_history_00;

CREATE TABLE hiredate_history_99 (deptid, hiredate)


AS
SELECT * FROM hiredate_history_00;

CREATE TABLE hiredate_history(depid, hiredate)


AS
SELECT * FROM hiredate_history_00;

INSERT FIRST
WHEN sal > 25000 THEN
INTO special_sal VALUES (deptid, sal)
WHEN hiredate LIKE '%00%' THEN
INTO hiredate_history_00 VALUES (deptid, hiredate)
WHEN hiredate LIKE '%99%' THEN
INTO hiredate_history_99 VALUES (deptid, hiredate)
ELSE
INTO hiredate_history VALUES (deptid, hiredate)
SELECT department_id deptid, sum(salary) sal, max(hire_date) hiredate
FROM employees
GROUP BY department_id;

INSERT DE CRIAÇÃO DE PIVÔS


É uma operação na qual podemos precisar criar uma transformação de
maneira que cada registro de um fluxo de entrada, como uma tabela de banco de
dados não relacional, seja convertido em vários registros para um ambiente de
tabela de banco de dados mais relacional.
Exemplo:Suponha que recebemos um conjunto de registros de vendas de
uma tabela de banco de dados não relacional (SALES_SOURCE_DATA com os
campos: employee_id, week_id, sales_mon, sales_tue, sales_wed, sales_thur e
sales_fri). Usando a criação de pivôs, converta o conjunto de registros de vendas
da tabela de banco de dados não relacional no formato relacional:
CREATE TABLE sales_info
(employee_id number(6),
week number(2),
sales number(8,2));

CREATE TABLE Sales_source_data


(employee_id number(6),
week_id number(2),
sales_mon number(8,2),
sales_tue number(8,2),
sales_wed number(8,2),
sales_thur number(8,2),
sales_fri number(8,2));

41
L A B O R A T O R I O D E B A N C O D E D A D O S

INSERT INTO Sales_source_data


VALUES (176,6,2000,3000,4000,5000,6000);

INSERT ALL
INTO Sales_info VALUES (employee_id, week_id, Sales_MON)
INTO Sales_info VALUES (employee_id, week_id, Sales_TUE)
INTO Sales_info VALUES (employee_id, week_id, Sales_WED)
INTO Sales_info VALUES (employee_id, week_id, Sales_THUR)
INTO Sales_info VALUES (employee_id, week_id, Sales_FRI)
SELECT employee_id, week_id, sales_mon,
sales_tue, sales_wed, sales_thur, sales_fri
FROM sales_source_data;

42
L A B O R A T O R I O D E B A N C O D E D A D O S

SEQUÊNCIAS

Sequências são estruturas criadas no banco de dados que retornam um valor


diferente a cada acesso. Sintaxe:
CREATE SEQUENCE nome_sequência
[START WITH valor_inicial] (default 1)
[INCREMENT BY incremento] (default 1)
[MAXVALUE valor_maximo_sequencia/NOMAXVALUE]
[MINVALUE valor_minimo_sequencia/NOMINVALUE]
[CYCLE|NOCYCLE]
[CACHE numero_cache|NOCACHE]
[ORDER|NOORDER];

SEQUENCIA Nome da sequência que não pode ser o


mesmo de uma tabela ou view.
Específica de quanto será o incremento ou
INCREMENT BY n decremento da sequência. O default é 1.
Especifica o primeiro número a ser gerado. O
START WITH n default é 1.
Especifica o valor máximo que a sequência
MAXVALUE n pode assumir. O default é NOMAXVALUE, indo
até 1027
Especifica o valor mínimo para sequências que
MINVALUE n estejam sendo decrementadas. É
mutuamente exclusiva à anterior.
Indica que, quando atingir o valor máximo, a
CYCLE | NOCYCLE numeração continuará a partir do valor inicial.
O default é NOCYCLE.
CACHE|NOCACHE Número de valores inteiros a manter na
memória (padrão 20). O número mínimo pode
ser 2. NOCACHE significa sem memória cachê.
ORDER|NOORDER Garante que os números inteiros sejam
gerados na ordem da solicitação (ORDER). O
NOORDER não garante esta ordem (é o
padrão).

Exemplo:
CREATE SEQUENCE SEQ_ALUNO
INCREMENT BY 1
START WITH 20040001
MAXVALUE 20049999
NOCYRCLE;

43
L A B O R A T O R I O D E B A N C O D E D A D O S

Confirmando a existência de sequences:


SELECT * FROM user_sequences;

Eliminando uma sequence:


DROP SEQUENCE nome_sequencia;

OBSERVAÇÕES:
Se for executado um ROLLBACK, o número da sequência não voltará;
Duas pseudo-colunas são utilizadas nas sequências:
• NEXTVAL, que retorna o próximo número da sequência;
• CURRVAL, valor corrente da sequência.

Exemplo NEXTVAL: INSERT INTO ALUNO (matricula, aluno)


VALUES (seq_aluno.NEXTVAL, 'Simone Viana');

Exemplo CURRVAL: SELECT seq_aluno.CURRVAL


FROM dual;

SINÔNIMOS

Um banco de dados é utilizado por dezenas de usuários que têm vários


objetos. Acontece frequentemente que um usuário precisa de uma tabela, índice,
view ou sequence de outro e, para facilitar a manipulação desses objetos, cria
synonymns (sinônimos).

CRIANDO SINÔNIMOS
Sintaxe: CREATE [PUBLIC] SYNONYM sinônimo FOR objeto
Em que:
PUBLIC → específica que o sinônimo poderá ser usado por todos. O default
é que somente o criador possa utilizá-lo. Para criar este sinônimo devemos estar
conectados como usuário SYSTEM.
Exemplo: CREATE PUBLIC SYNONYM teste FOR all_sales;
OBJETO→ informa o nome do objeto sobre o qual se aplica o sinônimo. Pode
ser tabela, índice, view ou sequence.
Exemplo: CREATE PUBLIC SYNONYM cursos_dba FOR cursos;
Supondo que o usuário corrente se chamada TESTE1 e houvesse outro
usuário denominado PEDRO, este poderia fazer referência à tabela cursos TESTE1:
SELECT * FROM cursos_dba;
Em vez de:
SELECT * FROM teste1.cursos_dba.

44
L A B O R A T O R I O D E B A N C O D E D A D O S

CONFIRMANDO A CRIAÇÃO DE SINÔNIMOS


Os sinônimos públicos podem ser vistos em ALL_SYNONYMS e os privativos
em USER_SYNONYMS. Exemplo:
SELECT SYNONYM_NAME, TABLE_OWNER
FROM ALL_SYNONYMS
WHERE TABLE_NAME = 'CURSOS';

ELIMINANDO SINÔNIMOS
DROP PUBLIC SYNONYM nome_sinônimo;
Exemplo: DROP PUBLIC SYNONYM cursos_dba;

INDICES

Um índice é um objeto de um esquema que pode acelerar a recuperação de


linhas usando um ponteiro. Os índices podem ser criados de duas formas: De
maneira explícita ou implícita. Caso não exista um índice associado a uma coluna,
ocorrerá uma análise em toda a tabela.
Um índice fornece acesso direto e rápido às linhas em uma tabela. Seu
objetivo é reduzir a necessidade de I/O do disco usando um caminho indexado
para localizar dados de forma mais rápida. O índice é utilizado e mantido
automaticamente pelo Oracle Server. Após a criação de um índice, não é
necessária nenhuma atividade direta do usuário.
A desvantagem do índice é que, quando um registro novo é adicionado é
preciso gastar um tempo para atualizar o índice da nova linha. Geralmente
podemos criar um índice em uma coluna quando está recuperando um pequeno
de registros de uma tabela que contém muitos registros. Uma boa regra é:
• Crie um índice quando uma consulta recuperar no máximo 10% do
total de registros de uma tabela.
Estes tipos de índices são chamados de índices de ARVORE B (nome que
deriva de uma estrutura de dados utilizada em ciência da computação). Uma
coluna que pode ser usada para um índice deste tipo é quando há um valor
exclusivo – exemplo: CPF – e não é bom usar uma coluna contendo um pequeno
intervalo de valores – exemplo: sexo.
Os índices são lógica e fisicamente independentes da tabela que indexam.
Isso significa que eles podem ser criados e eliminados a qualquer momento e não
têm nenhum efeito sobre as tabelas-base ou outros índices.
É muito importante lembrar que ao eliminar uma tabela, os índices
correspondentes também são eliminados.
É possível criar dois tipos de índices. Um tipo é um índice exclusivo. O Oracle
Server cria esse índice automaticamente quando você define que uma coluna de
uma tabela tenha uma restrição PRIMARY KEY ou UNIQUE KEY. O nome do índice
é o nome dado à restrição.

45
L A B O R A T O R I O D E B A N C O D E D A D O S

O outro tipo de índice que um usuário pode criar é um índice não-exclusivo.


Por exemplo, você pode criar um índice da coluna FOREIGN KEY para uma junção
em uma consulta a fim de aumentar a velocidade de recuperação.

CRIANDO UM ÍNDICE ARVORE B

CREATE [UNIQUE] INDEX índice ON tabela (coluna[, coluna]...)


TABLESPACE nome_tablespace;
Onde:
• UNIQUE permitidos somente valores exclusivos na coluna indexada.
• índice é o nome do índice.
• tabela é o nome da tabela.
• coluna é o nome da coluna na tabela a ser indexada.
• Nome_tablespace4 , caso não seja informado será criado na tablespace
padrão do usuário.

CREATE INDEX idx_dept ON departments (department_name);

Possuir mais índices em uma tabela não significa que as consultas serão
aceleradas. Cada operação DML que seja submetida a COMMIT em uma tabela
com índices significa que os índices devem ser atualizados. Quanto mais índices
associados a uma tabela você tiver, maior será o esforço realizado pelo Oracle
Server para atualizar todos os índices após uma instrução DML.
Também podemos criar um índice composto em várias colunas, por
exemplo, um índice contendo o nome e o sobrenome do empregado:

CREATE INDEX idx_nome_completo ON employees(first_name,last_name);

Podemos criar um índice baseado em função. Exemplo:


CREATE INDEX idx_nome1 ON employees(UPPER(first_name));

SELECT * FROM employees


WHERE UPPER(first_name) = ‘GENOVEVA’;
QUANDO DEVEMOS CRIAR UM ÍNDICE

• Quando a coluna for usada frequentemente na cláusula WHERE ou em uma


condição de junção.
• Quando a coluna contiver uma ampla faixa de valores.
• Quando a coluna contiver um grande número de valores nulos.

4Área utilizada pelo bando de dados para armazenar objetos (tabelas). Por motivos de
desempenho armazenamos um índice em uma tablespace diferente da tablespace das tabelas.

46
L A B O R A T O R I O D E B A N C O D E D A D O S

• Quando duas ou mais colunas forem usadas juntas com frequência em uma
cláusula WHERE ou em uma condição de junção.
• Quando a tabela for grande e se esperar que a maioria das consultas recupere
menos que 2 a 4% das linhas.

QUANDO NÃO DEVEMOS CRIAR UM ÍNDICE


• Quando a tabela for pequena.
• Quando as colunas não forem utilizadas com frequência como uma condição na
consulta.
• Quando se esperar que a maioria das consultas recupere mais que 2 a 4% das
linhas.
• Quando a tabela for atualizada com frequência. Se você tiver um ou mais
índices em uma tabela, as instruções DML que acessarem a tabela serão mais
lentas.

CONFIRMAÇÃO DOS ÍNDICES

Podemos confirmar a existência de índices na view do dicionário de dados


USER_INDEXES (colunas: index_name, table_owner, table_name, uniqueness,
status). Também é possível checar as colunas envolvidas em um índice
consultando a view USER_IND_COLUMNS (index_name, table_name e
column_name). Ainda podemos utilizar a view ALL_IND_COLUMNS para saber
todos os índices que temos acesso.

REMOÇÃO DE UM ÍNDICE

Não podemos modificar índices. Para alterar um índice, você deve eliminá-lo
e, em seguida, recriá-lo. Remova uma definição de índice do dicionário de dados
emitindo a instrução DROP INDEX. Para eliminar um índice, você precisa ser o
proprietário do índice ou possuir o privilégio DROP ANY INDEX. Sintaxe:
DROP INDEX nome_indice;

ALTERAR UM ÍNDICE

Podemos modificar – por exemplo – o nome de um índice. Exemplo:


ALTER INDEX idx_teste RENAME TO idx_teste1

POSSUIR MAIS ÍNDICES EM UMA TABELA NÃO SIGNIFICA QUE AS


CONSULTAS SERÃO ACELERADAS. CADA OPERAÇÃO DML QUE SEJA
SUBMETIDA A COMMIT EM UMA TABELA

47
L A B O R A T O R I O D E B A N C O D E D A D O S

VIEWS

Também conhecido como visão, é uma tabela virtual na qual os dados não
estão fisicamente armazenados. Ela é apenas uma visão de um grupo de colunas
de uma ou mais tabelas do banco de dados. Utilizamos visões para:
• Restringir o acesso a dados;
• Facilitar as consultas complexas;
• Permitir a independência dos dados;
• Apresentar diferentes visualizações dos mesmos dados.
Pode ser:
• SIMPLES: somente uma tabela, não contém funções e nem grupos e faz
operação DML.
• COMPLEXA: uma ou mais tabelas, contém funções, grupos de dados e
nem sempre faz uma operação DML.
Sintaxe:
CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW nome_da_view
[apelido1, apelido2, …]
AS subconsulta
[WITH CHECK OPTION [CONSTRAINT restrição] ]
[WITH READ ONLY [CONSTRAINT restrição]];
Onde:
REPLACE Recria a view, se ela já existir.
FORCE Cria a view, mesmo que a tabela não exista.
NOFORCE Só cria a view se a tabela existir. (padrão)
CONSULTA Comando SELECT. Não se usa o ORDER BY.
WITH CHECK Somente linhas acessíveis pela view (cláusula
OPTION where na sua definição), podemos inserir e alterá-
las.
WITH READ ONLY Indica que não podem ser executados comandos
DML sobre a views.

• Eliminar uma views – DROP VIEW nome_view;


• Estrutura de uma view– DESC ou DESCRIBE nome_view
• Verificando dados de uma view – SELECT * FROM nome_view;

Exemplo:
CREATE OR REPLACE VIEW aluno_curso
AS
SELECT a.cdmatricula, a.nmaluno, c.nmcurso
FROM aluno a, curso c
WHERE a.cdcurso = c.cdcurso;

48
L A B O R A T O R I O D E B A N C O D E D A D O S

APAGAR A VISÃO: DROP VIEW


Exemplo: DROP VIEW aluno_curso;

VIEW COMPLEXA

Exemplo:
SELECT a.nmfuncionario, a.vlsalario, a.nmfuncao, b.maior
FROM funcionario a,
(SELECT nmfuncao, max(vlsalario) maior
FROM funcionario
GROUP BY nmfuncao) b
WHERE a.nmfuncao = b.nmfuncao
AND a.vlsalario < b.maior;

OPERAÇÕES DML
Podemos executar operações DML nos dados através de uma view se essas
operações não tiverem uma destas exceções:
• Funções de grupo;
• GROUP BY;
• DISTINCT;
• ROWNUM;
• Colunas definidas por expressões (exemplo: salário * 1.10);
• Colunas NOT NULL nas tabelas-base que não sejam selecionadas pela
view.

WITH CHECK OPTION

Podemos verificar a integridade referencial através das views. Podemos impor


restrições no nível de banco de dados. A view poderá ser usada para proteger a
integridade dos dados, mas o uso é muito restrito. Esta cláusula específica que as
operações INSERT e UPDATE executadas na view não podem criar linhas que não
possam ser selecionadas pela view e portanto, permite restrições de integridade e
verificações de validação dos dados sejam impostas aos dados que estiverem
sendo inseridos ou atualizados. Exemplo:
CREATE OR REPLACE VIEW empvu20 AS
SELECT * FROM employees
WHERE department_id = 20
WITH CHECK OPTION CONSTRAINT empvu20_vk;

49
L A B O R A T O R I O D E B A N C O D E D A D O S

WITH READ ONLY

Esta cláusula assegura que nenhum comando DML através da view. Qualquer
tentativa com relação a um comando DML ocasionará um erro. Exemplo:
CREATE OR REPLACE VIEW empvu10 (id, nome, cargo)
AS
SELECT employee_id, last_name, job_id
FROM employees
WHERE department_id = 10
WITH READ ONLY;

ANÁLISE TOP-N

As consultas Top-N são úteis onde existe a necessidade de exibir apenas os


n maiores ou os n menores registros de uma tabela com base em uma condição.
Esse conjunto de resultados pode ser usado para análise posterior. Como por
exemplo, os três maiores salários da empresa, os quatro mais novos contratados
da empresa, os dois representantes de vendas que mais vendem produtos, etc.
Sintaxe:
SELECT lista_colunas, ROWNUM FROM (subconsulta com ORDER BY)
WHERE ROWNUM <= N;

Exemplo: Exibir os nomes e os salários dos três funcionários mais bem


remunerados:
SELECT ROWNUM, last_name, salary
FROM (SELECT last_name, salary
FROM employees ORDER BY salary DESC)
WHERE ROWNUM <= 3;

VIEW MATERIALIZADA

Materialized views (anteriormente chamado de Snapshot) são objetos do


banco de dados Oracle utilizados para armazenar dados de consultas que precisem
ler uma grande quantidade de dados de diferentes tabelas/views. Elas funcionam
como uma tabela do banco, populada manualmente ou via job, que permite a
execução de queries complexas, lendo um único objeto de banco de dados. Além
de permitir a criação de índices exclusivos, que não impactam na performance das
tabelas usadas como origem de dados para as materialized views.
Além do uso para gerar uma tabela a partir de uma consulta, outro uso para
as materialized views é a criação local de uma tabela existente em outro banco de
dados, evitando tráfego de rede durante as consultas, podendo mover este tráfego
para períodos onde o banco de dados não esteja muito carregado (quando os
valores da tabela não precisam estar com a versão mais atual).

50
L A B O R A T O R I O D E B A N C O D E D A D O S

Em resumo, a view materializada difere da view pois não armazena a consulta


e sim o resultado desta consulta. Pode ocorrer a consulta em tempo de execução
quando há uma atualização da tabela, então, é realizada uma nova consulta e é
novamente armazenada.
Comandos:
• REFRESH - tipo de atualização que sofrerão os dados contidos na visão.
Existem três estados ou métodos:
• FAST: Atualiza somente as linhas da tabela original que sofreram
atualizações.
• COMPLETE: Recria toda a estrutura da view materializada mesmo que não
seja necessário.
• FORCE: Se não for especificado o método de atualização, o padrão é FORCE,
que tentará fazer uma atualização FAST se não for possível irá fazer a
COMPLETE.
• START WITH - Indica que quando o banco irá fazer a primeira replicação;
• NEXT - Determina o intervalo entre a próxima replicação.
• WIDTH PRIMARY KEY - É utilizado para criar a Chave-Primária, que é baseada na chave-
primária da tabela máster. Conclui-se com esses post-tutorial que view materializadas são
extremamente úteis no dia-a-dia de uma companhia que trabalha com centenas de
milhares de tuplas e, o acesso à elas acaba ficando custoso. Este tipo de objeto ajuda a
diminuir acesso as tabelas master de uma maneira segura e íntegra.

Exemplo:
CREATE MATERIALIZED VIEW vm_employees
REFRESH FAST
START WITH SYSDATE + 1
NEXT SYSDATE + 1/24
WIDTH PRIMARY KEY
AS
SELECT employee_id, last_name, job_id, salary
FROM employees;

51
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS

1. Crie uma visão EMP_VU com base no número, nome dos funcionários e
número dos departamentos da tabela EMPLOYEES. Altere o cabeçalho do
funcionário para EMPREGADO.
2. Exiba o conteúdo da visão EMP_VU.
3. Usando a visão EMP_VU, informe uma coluna para exibir os nomes de todos
os funcionários e números dos departamentos.
4. Crie uma visão chamada DEPT50 que contenha o número e o nome do
funcionário e o número do departamento dos funcionários do departamento
50. Coloque um label (OU APELIDO) nas colunas da visão. Não permita que
um funcionário seja atribuído a outro departamento através da visão.
5. Crie uma visão chamada SALARIO_VU com base no nome, salário do
funcionário, nome do departamento e classe de salário de todos os
funcionários.
6. Criar uma tabela chamada ESTOQUE tenha uma coluna chamada ID do tipo
inteiro com chave primária.
7. Crie uma sequência para ser usada como a coluna de chave primária da tabela
ESTOQUE. A sequência deve iniciar em 200 e ter um valor máximo de 1000.
O incremento da sequência deve ser de dez números. Nomeie a sequência
como ESTOQUE_ID_SEQ.
8. Crie um script para exibir as seguintes informações sobre as sequências:
nome, valor máximo, tamanho do incremento e o último número utilizado.
9. Crie um sinônimo para cada uma das tabelas: EMPLOYEES e DEPARTMENTS.

52
L A B O R A T O R I O D E B A N C O D E D A D O S

OBJETO-RELACIONAL

O Oracle incorporou ao banco de dados relacional a tecnologia orientada a


objetos tornando-se assim um SGBD objeto-relacional. Ele nem pode ser
considerado puramente orientada a objetos nem tampouco apenas relacional. Isso
implica que todas as características relacionais permanecem mais com alguns
recursos adicionais. Antes, as tabelas apenas podiam conter valores atômicos em
seus atributos, agora podemos definir novos tipos de dados e usá-los para receber
valores complexos. O Oracle permite criar outros tipos de objetos, tabelas,
referências para objetos entre outros. A partir da versão 8, foi implementado
alguns conceitos para definir um modelo objeto-relacional: OBJETO, TABELA DE
OBJETOS, etc.

TIPO OBJETO

Podemos criar tipos de dados adicionais, depois fazermos referência a esses


tipos de dados dentro de outros objetos. Essa capacidade de estender o banco de
dados com tipos adicionais é um recurso muito importante, pois ajuda a simplificar,
por exemplo, a complexidade do tratamento a tipos de dados complexos. Um outro
ponto importante a observar é que os tipos criados são gravados no esquema
armazenado no banco de dados. Então, outras declarações que acessam o banco
de dados podem fazer uso das definições desses tipos. As definições de tipo em
linguagens de programação (incluindo programação persistente) não são
armazenadas em um banco de dados e só podem ser vistas por programas que
incluem um arquivo texto contendo as definições. Exemplo:
CREATE TYPE t_endereco AS OBJECT
(rua VARCHAR2(40),
cidade VARCHAR2(30),
uf CHAR(2),
cep NUMBER(8));
Ainda é possível utilizar tipos aninhados, ou seja, um tipo pode ser um
atributo de outro tipo. Exemplo:
CREATE TYPE t_funcionario AS OBJECT
(matricula NUMBER(5),
nome VARCHAR2(30),
data_admissao DATE,
endereco t_endereco);

HERANÇA

A partir do Oracle 9i, um tipo pode ser estendido criado subtipos que
reutilizam a especificação e implementação (atributos e métodos) do tipo que ele
deriva. Assim, através dos objetos podemos criar uma hierarquia de tipos.

53
L A B O R A T O R I O D E B A N C O D E D A D O S

Por padrão, o tipo de objeto é FINAL. Por isso, para permitir subtipos, deve
ser obrigatoriamente adicionada à expressão NOT FINAL à declaração do tipo do
objeto. Exemplo: CREATE TYPE t_pessoa AS OBJECT
(codigo_pessoa NUMBER(5),
nome VARCHAR2(50),
endereco VARCHAR2(50)) NOT FINAL;
/

CREATE TYPE t_fisica UNDER t_pessoa


(cpf CHAR(11),
sexo CHAR);

CREATE TYPE t_juridica UNDER t_pessoa


(cnpj CHAR(14),
inscricao_estadual VARCHAR(30));

Agora vamos criar as duas tabelas (FISICA e JURÍDICA) de acordo com os


tipos:
CREATE TABLE PESSOA_FISICA of t_fisica;

CREATE TABLE PESSOA_JURIDICA of t_juridica;

TABELAS ANINHADAS (NESTED TABLE)

São tabelas com colunas cujo tipo de dado de domínio é outra tabela. Isto é,
as tabelas podem ser aninhadas dentro de outras tabelas como valores na coluna.
Permite que os relacionamentos N:N possam ser representados por tabelas
aninhadas.
Este tipo de dados contém elementos desordenados, todos do mesmo tipo, e
sem limite de elementos. Quando uma coluna de uma tabela é do tipo nested
table, seus dados são armazenados no mesmo lugar desta tabela, ou seja, os
dados são armazenamentos fisicamente na mesma área de disco. Assim a
substituição de um join por uma tabela aninhada, garante um desempenho
superior. Exemplo:
CREATE OR REPLACE TYPE t_end AS OBJECT
(rua VARCHAR2(60),
numero INTEGER,
bairro VARCHAR2(60),
cidade VARCHAR2(60),
uf CHAR(2),
cep CHAR(9));

54
L A B O R A T O R I O D E B A N C O D E D A D O S

CREATE TYPE lista_endereco AS TABLE t_end;

Obs. A partir da versão 9i é possível que uma tabela aninhada tenha outra
tabela aninhada.
-0p=Ao criarmos object tables de object types que contenham como atributo
uma ou mais nested tables devemos especificar para o Oracle o nome de uma
tabela chamada store table, que é usada para guardar a tabela aninhada
Por padrão, os tipos de objeto são FINAL. Por isso, para permitir subtipos,
deve ser obrigatoriamente adicionada à expressão NOT FINAL à declaração do tipo
do objeto. Exemplo:
CREATE TYPE t_livro AS OBJECT
(numero NUMBER(4),
titulo VARCHAR2(40));

CREATE TYPE lista_livro AS TABLE OF t_livro;

CREATE TABLE material_disciplina


(departamento CHAR(4),
curso NUMBER(3),
livro_requerido lista_livro)
NESTED TABLE livro_requerido STORE AS livro_requerido_tab;

Podemos inserir na tabela material_disciplina assim:

INSERT INTO material_disciplina


VALUES ('ccft', 10, lista_livro(t_livro(1,'Oracle 10G'),
t_livro(2,'Oracle 9i')));

Podemos consultar assim:


SELECT l.titulo
FROM material_disciplina m,
TABLE (m.lista_livro) l
WHERE m.departamento='ccft'
AND m.curso = 10;

SELECT m.departamento, m.livro_requerido


FROM material_disciplina m;

55
L A B O R A T O R I O D E B A N C O D E D A D O S

CRIAÇÃO DE TIPOS DE ARRAY

É criado uma lista ordenada de elementos do mesmo tipo. Cada elemento


tem um índice, que é um número da posição do elemento no vetor. O tipo vetor é
chamado VARRAY porque possui um tamanho variável. Quando criado é necessário
especificar o tamanho máximo. O banco de dados não aloca realmente o espaço e
sim define um novo tipo e o armazena no catálogo do sistema. Exemplo:
CREATE TYPE lista_telefone AS VARRAY(5) OF VARCHAR2(10);

Exemplo: CRIANDO UMA TABELA COM TIPOS DEFINIDOS:


CREATE TABLE cliente_loja
(cpf CHAR(11),
nome VARCHAR(50),
tel_cliente lista_telefone);

Exemplo: INSERINDO DADOS NA TABELA COM TIPOS DIFERENCIADOS:


INSERT INTO cliente_loja
VALUES('11122233340','Porsidonio',
lista_telefone('32996969','32037171'));

OPERADOR VALUE

Retorna o conteúdo de um objeto armazenado em um object table. É usado


quando for preciso referenciar uma linha de uma object table como um objeto em
vez de uma lista de colunas. Exemplo: Armazena ao objeto obtido pela consulta
dentro da variável v_funcionário:
DECLARE
V_funcionário t_funcionario;
BEGIN
SELECT VALUE(f) INTO v_funcionario
FROM funcionarios f
WHERE matricula = 1234;
DBMS_OUTPUT.PUT_LINE(v_funcionario.nome);
END;

Exemplo: Para exibr a rua:


DBMS_OUTPUT.PUT_LINE (v_funcionario.endereco.rua);

56
L A B O R A T O R I O D E B A N C O D E D A D O S

TIPOS REFERÊNCIA
O relacionamento entre duas entidades pode ser modelado nativamente
através de ponteiros que referenciam as entidades relacionadas. Expressamos tais
relacionamentos utilizando o identificador do objeto (OID 5 ) associado a cada
instância de um tipo de dado estruturado. Esse identificador é atribuído
automaticamente a objetos, permitindo que o objeto correspondente seja
referenciado a partir de outros objetos. Isto é feito através do tipo REF 6, que
encapsula uma referência para um objeto especificado. Ou seja, ao declaramos
um tipo, podemos declarar como seu atributo um ponteiro para outro tipo através
da expressão REF. Exemplo:
CREATE OR REPLACE TRIGGER departamento_d
AFTER DELETE ON departamentos
FOR EACH ROW
DECLARE
D_ref REF t_departamento;
BEGIN
SELECT REF(d) INTO d_ref FROM departamentos d
WHERE d.num_depto = :old.num_depto;
UPDATE funcionaros f SET f.depto = null
WHERE f.depto = d_ref;
END;
Exemplo: CREATE TYPE t_departamento AS OBJECT
(num_depto NUMBER,
nome VARCHAR2(30),
endereço t_endereco);

CREATE TABLE departamentos OF t_departamento;

CREATE TABLE funcionários


(matricula NUMBER,
nome VARCHAR2(30),
depto REF t_departamento);

EXERCÍCIO PRÁTICO
1. Fazer a implementação objeto-relacional em Oracle que demonstre a hierarquia de
tipos (herança). Primeiramente, deve-se criar um tipo chamado VEICULO e também os
tipos Moto, Carro, Caminhão, Ônibus que herdam de VEÍCULO. O tipo VEICULO deve
possuir Placa, Descrição e Ano_Fabricação. O tipo Carro deve possuir Moto e Portas. O
tipo Moto deve possuir o atributo Cilindradas. O tipo Caminhão deve possuir o atributo
Comprimento. O tipo Ônibus deve possuir Número de Lugares e Andar. Definir as
tabelas dos tipos criados e fazer a inserção de dados nessas tabelas.

5 Object Identifier – identificador único global de um objeto em todo o banco de dados.


Produzido quando o objeto é armazenado no banco como Object Table.
6 Ponteiro para um objeto. Não é um OID, mas a maneira pela qual nós os vemos. Faz a junção

do OBJECT TABLES usando navegação por ponto (dot navigation) também conhecida como
expressão de caminho. É um operador que retorna o ponteiro para um objeto, dado um sinônimo
de tabela.

57
L A B O R A T O R I O D E B A N C O D E D A D O S

ARQUITETURA ORACLE

COMPONENTES DE ARQUITETURA ORACLE


Vamos apresentar os componentes da arquitetura Oracle e descrever
a composição da instância e do banco de dados.
O servidor é composto por uma instância e por um banco de dados.
A instância é composta por: SGA – SYSTEM GLOBAL AREA (ÉREA) (área
de memória), processos de 2º plano e nos arquivos relacionados ao banco
de dados.
SGA – SYSTEM GLOBAL AREA (ÉREA)

Figura 16 - Composição SGA

Toda instância possui sua própria SGA. Quando uma instância é iniciada
o servidor aloca memória para SGA que será liberado quando a instância
for desativada.
A região da memória é compartilhada. O espaço de memória não pode
ter swapped e nem pode ser paginado. Tem a finalidade armazenar
memória dados para acesso rápido, a memória deve estar na memória
principal e se estiver no disco não terá acesso rápido.
A SGA consiste num grupo de estrutura de memória e o seu espaço é
alocado na inicialização da instância. Temos: POOL COMPARTILHADO,
CACHE DE BUFFER DE BANCO DE DADOS, BUFFER DE REDO LOG, também
tem o POOL GRANDE e o POOL JAVA.
Podemos exibir as alocações de memória utilizando o comando SHOW
SGA.

58
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 17 - Partes da Instância

• POOL COMPARTILHADO: Armazena as instruções SQL e as


informações do dicionário de dados mais recentemente utilizadas.
• CACHE DE BUFFER DE BANCO DE DADOS: armazena os dados do
usuário utilizados mais recentemente. Este cache contém a lista de
gravação (retém buffer sujos com dados modificados mais não
gravados no disco) e a lista LRU (retém buffers livres, sujos e retidos
que atualmente em uso).
• BUFFER DE REDO LOG: registra as alterações feitas no banco de
dados.
Podemos alterar o espaço de memória que foi calculado com base nos
parâmetros do arquivo init.ora. Podemos expandir ou compactar a SGA
enquanto a instância estiver em uso.
A SGA dinâmica permite que sejam alterados sem desativar a instância,
podemos definir o tamanho máximo que ela pode crescer utilizando o
parâmetro SGA_MAX_SIZE.

PROCESSOS DE SEGUNDO PLANO

Uma instância contém SGA e os processos de segundo plano e quando


ela é iniciada é criada os processos de segundo plano.
São processos do sistema operacional e toda instância pode utilizar
mais de um processo com base na configuração Oracle. Cinco processos são
necessários para cada instância. São eles:
• DBWn: grava os dados do cachê de buffer de banco de dados nos
arquivos de banco de dados. O servidor Oracle processa todos os
dados na memória antes deste processo gravar os dados nos
arquivos. Quando a transação modifica os dados a imagem original é
59
L A B O R A T O R I O D E B A N C O D E D A D O S

gravada no segmento de rollback (está presente no cachê de buffer


de banco de dados. As operações que foram comitadas são gravadas
nos arquivos de dados. Isto significa que os arquivos de dados
armazenam o dicionário de dados e o objeto do usuário que contém
as últimas alterações comitadas);
• LGWR: registra as alterações contidas no buffer de redo log nos
arquivos de redo log. Quando os dados são modificados no cachê de
buffer de dados, os dados modificados são gravados no buffer de redo
log depois de submetidas a commit.
Os buffers de redo log que contém os blocos de dados são gravados
nos arquivos de redo log (contém todas as alterações feitas nos
dados) por este processo. As entradas no buffer de redo log são
conhecidas como dados de redo log;
• SMON: executa uma recuperação de instância efetuando um rollback
das transações pendentes e recuperando dados registrados no buffer,
mas não registrados no banco de dados. Limpa os segmentos
temporários que não estão mais em uso. Armazena dados
temporariamente durante uma transação. Recupera as transações
inativas (estavam ativas quando houve a falha no sistema) que foram
ignoradas durante uma falha no sistema. Une o espaço livre
fragmentado no banco de dados;
• PMON: recupera o processo de usuário que falhou, limpando o cachê
e desbloqueia os recursos de sistema mantidos pelo usuário;
• CKPT: atualiza as informações sobre o status do banco de dados
como os cabeçalhos dos arquivos de banco de dados. A atualização
ocorre para um evento de checkpoint. Durante o checkpoint o
servidor, registra permanentemente as alterações feitas no cachê do
buffer de banco de dados nos arquivos banco de dados.

Estes são processos de segundo plano opcionais:

Figura 18 - Processo de Segundo Plano

60
L A B O R A T O R I O D E B A N C O D E D A D O S

• RECO - resolver transações distribuídas pendentes devido a uma


falha na rede ou no sistema de um banco de dados distribuído (onde
várias instâncias cliente utilizam o mesmo banco de dados);
• ARCn – copia os arquivos de redo log online para o armazenamento
de arquivos quando eles estão completos. Só é ativado quando o
banco de dados está no modo ARCHIVELOG.
• LCKn – utilizado para bloqueio em instâncias na arquitetura Cluster.
É necessário pois várias instâncias acessam o mesmo banco de dados.
Podemos configurar qualquer processo entre 1 a 9; isto significa que
podemos configurar 9 bloqueios de uma só vez.
• Dnnn – estão disponíveis quando usamos uma configuração MTS
(Multi-Thread Server), onde o servidor tem mais de um thread e um
job é alocado a cada thread de um servidor. É utilizado em ambiente
distribuído para aumentar a eficiência. Permitem que os processos de
usuários compartilhem processos de servidor limitados em um
ambiente MTS, podendo variar de D000 e DNNN.

ARQUIVO DE BANCO DE DADOS

Figura 19 - Arquivos Fisicos em Banco Oracle

Um banco de dados Oracle é um conjunto de dados. O servidor


armazena os dados no BD e recupera as informações relacionadas a partir
do BD. As informações são armazenadas em arquivos ou estruturas físicas
de armazenamento.
Uma das responsabilidades do DBA é gerenciar os arquivos de banco
de dados e para isso é necessário conhecer os tipos de arquivos e as
informações armazenadas nele:

• BANCO DE DADOS: Em um BD Oracle podem existir um ou mais


arquivos de dados. O arquivo de dados armazena o dicionário de dados
e os objetos do usuário. Também armazena as últimas alterações
submetidas à commit no banco de dados. O servidor lê os arquivos de
dados e os armazena no cachê de buffer de banco de dados. O servidor
não grava dados novos ou modificados imediatamente no banco de
61
L A B O R A T O R I O D E B A N C O D E D A D O S

dados. Os dados são armazenados no cachê de buffer de banco de


dados.

• REDO LOG: todo banco de dados Oracle tem no mínimo dois grupos
de redo log e cada um com pelo menos um arquivo de redo log. Estes
arquivos registram todas as alterações feitas nos dados e permite a
recuperação dos dados num caso de falha de instância. Para proteger
estes arquivos das falhas dos arquivos, o Oracle suporta arquivos
multiplexados, que significa que podemos ter duas ou mais cópias de
redo log em diferentes discos. As cópias mantidas em arquivos
diferentes são chamadas ARQUIVOS DE LOG ESPELHADOS, cada
membro de um grupo de arquivos de log tem um arquivo de log do
mesmo tamanho.

• CONTROLE: armazena as informações necessárias para manter e


verificar a integridade dos dados. Eles armazenam informações sobre
a estrutura do banco de dados, como o nome do banco de dados, o
time stamp do banco de dados, além dos nomes e locais de arquivos
de dados e de redo log. As informações armazenadas nos arquivos de
controle são usadas para identificar os arquivos de dados e de redo log.
Devem ser abertos quando abrir o banco de dados, se o DBA alterar a
estrutura do banco de dados o servidor altera automaticamente o
arquivo de controle para que reflita as alterações. Quando ocorrer uma
falha do sistema, ele trabalha junto com o arquivo de redo log. Cada
servidor de banco de dados precisa de pelo menos um arquivo de
controle.

ARQUIVOS NÃO RELACIONADOS A BANCO DE DADOS

Figura 20 - Tipos de Arquivos não-relacionados ao Banco de Dados

62
L A B O R A T O R I O D E B A N C O D E D A D O S

O servidor utiliza alguns arquivos que não são relacionados ao banco


de dados para executar operações como inicialização de instância e
autenticação de usuários. Além dos arquivos de banco de dados, estes
arquivos são estruturas físicas importantes de armazenamento da Oracle:

• ARQUIVO DE PARAMETRO – define as características de uma instância


oracle. Quando o servidor inicializa uma instância
este arquivo é utilizado para obter a configuração da instância e é
especificação pela configuração específica do arquivo de parâmetros.
Especifica o nome do banco de dados, a quantidade de memória a ser
alocada, os nomes dos arquivos de controle e outros parâmetros do
sistema.

• ARQUIVO DE SENHA – utilizado para autenticar ou validar os privilégios


dos usuários de banco de dados.

• ARQUIVO DE REDO LOG ARQUIVADOS – armazena cópias offline do


arquivo de redo log utilizadas durante a recuperação de uma falha de
mídia. O Oracle cria estes arquivos por meio de arquivamento de redo
log online totalmente preenchidas é possível reutilizar o arquivo de redo
log online após o arquivamento. Se o banco de dados estiver no modo
ARCHIVELOG será necessário arquivar os arquivos de redo log antes de
serem reutilizados em um cycle. Se o arquivamento automático for
ativado os arquivos serão arquivados no processo ARCO é possível
recuperar completamente o banco de dados por falha de instância ou de
mídia.

ESTRUTURA DE ARMAZENAMENTO LÓGICA

Podemos maximizar a velocidade na qual o servidor recupera os dados


no banco de dados por métodos eficientes de armazenamento de dados e
como o Oracle armazena dados.
Contém vários componentes como TABLESPACES, SEGMENTOS e
EXTENSÕES:
• BANCO DE DADOS - primeiro componente da hierarquia. Dividido
logicamente em tablespaces.
• TABLESPACE – segundo componente da hierarquia de armazenamento
é usado para agrupar estruturas lógicas e relacionadas e agrupam por
exemplo, todos os objetos de uma aplicação para facilitar as operações
administrativas.
• ARQUIVO DE DADOS – terceiros componentes. São as estruturas
físicas de um banco de dados. Cada tablespace pode ter um ou vários
arquivos de dados, mas estes pertencem somente a uma tablespace.

63
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 21 - Estrutura Lógica de Armazenamento Oracle

O tamanho combinado de todos os arquivos de dados em um tablespace


é a capacidade total da tablespace. A capacidade total do banco de dados
é formada pela capacidade total de todas as tablespaces deste banco de
dados.
Um único banco de dados pode conter até 65.535 arquivos de dados.
Um tablespace pode conter um ou mais SEGMENTOS (4º componente),
pertence a uma estrutura lógica e quando criado possui no mínimo uma
extensão. Alguns segmentos são de tabela e de índice.

• EXTENSÃO - conjunto de blocos para armazenar um


tipo específico de informação. Quando um segmento
precisa de mais espaço são acrescentadas extensões
a ele.

• BLOCO ORACLE ou BLOCO DE DADOS (último


componente) é a menor unidade de entrada/saída
executada pelo banco de dados Oracle. Seu tamanho
deve ser um múltiplo do bloco do sistema operacional.

64
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 22 - Representação de Bloco de Dados

Corresponde a um número específico de bytes no espaço físico


específico no disco. Ao criar o banco de dados Oracle especifique o tamanho
básico para ele. Quando o servidor Oracle solicitar um ou mais blocos
Oracle, os dados serão recuperados do disco dos blocos do sistema
operacional.

EXIBIR INFORMAÇÕES
Temos as seguintes tablespaces já definidas no banco de dados:
• SYSTEM: usada pelo servidor para gerenciar o banco de dados. Contém
o dicionário de dados e tabelas com informações administrativas usadas
pelo DBA;
• SYSAUX: auxilia a SYSTEM. Obrigatória a partir da versão 10G;
• TEMP: armazena índices e tabelas temporárias usadas no processamento
das instruções SQL, como por exemplo, ordenação dos dados;
• UNDOTBS1: armazena informações de undo;
• USERS: armazena dados e objetos criados pelos usuários;
• EXAMPLE: contém exemplos de esquemas que podem ser instalados no
momento da criação do banco de dados.

Podemos ainda, consultar as views de dicionário de dados:


• ARQUIVO DE DADOS: DBA_DATA_FILES, V$DATAFILE;
• ARQUIVOS TEMPORÁRIOS: DBA_TEMP_FILES, V$TEMPFILE;
• TABLESPACES: DBA_TABLESPACE, V$TABLESPACE

EXERCÍCIOS

1. Exibir todas as tablespaces do banco de dados e anotar o nome, tipo,


tamanho e percentual na tabela abaixo:
NOME DA TIPO TAMANHO % USADO
TABLESPACE

65
L A B O R A T O R I O D E B A N C O D E D A D O S

DICIONÁRIO DE DADOS

O Dicionário de Dados é uma das mais importantes partes do RDBMS


Oracle. Ele consiste em um conjunto de tabelas e views, que são um guia
de referência sobre a base de dados. O dicionário de dados contém
informações como:
• nome dos usuários Oracle;
• direitos e privilégios que eles têm;
• nome dos objetos do banco de dados;
• constraints das tabelas;
• etc.
O Dicionário de Dados é criado junto com a criação do banco de dados.
As alterações feitas na base de dados são feitas pelo RDBMS Oracle.
O Dicionário de dados é uma referência para todos os usuários do
banco de dados. É uma fonte valiosa de informações para os usuários finais,
desenvolvedores de aplicações, e DBA’s.
O acesso ao Dicionário de Dados Oracle é feito pelos usuários através
de selects nas tabelas e views do dicionário. A alteração destas tabelas e
views é feita através do RDBMS, que verifica os acessos e permite ou não
as operações no banco. Nenhuma tabela ou view do sistema deve ser
alterada manualmente sob o risco de se perder a integridade dos dados que
estão contidos na base.
As tabelas do dicionário de dados são criadas junto com a criação do
banco de dados e raramente são acessadas diretemante pelo usuário. Para
o acesso aos usuários são criadas, views com dados mais resumidos e de
forma mais simples (algumas tabelas chegam a ter dezenas de colunas e
nome pouco significativos).
Os nomes das views que são criadas refletem o tipo de uso a que elas
se destinam.
As principais views são:
• USER_xxxx: exibe informações sobre os objetos do usuário;

• ALL_xxxx: exibe objetos que o usuário tem acesso além dos objetos do
próprio usuário.
• DBA_xxxx: para usuários que tem o acesso de DBA, exibe objetos
pertencentes à base de dados e objetos que o usuário não DBA tem
acesso.

• DICTIONARY: contém todos os objetos do dicionário de dados acessíveis


pelo usuário.

66
L A B O R A T O R I O D E B A N C O D E D A D O S

A view Dictionary mostra todos os objetos do dicionário de dados que


são acessíveis pelo usuário com um pequeno comentário sobre o conteúdo
de alguns destes objetos.
Para verificar o conteúdo desta view entre com o comando:
SQL> select * from dictionary;

O Quadro a seguir mostra as views do dicionário de dados mais


utilizadas são as seguintes:

Quadro 5 - View de Dicionário de Dados

Nome da view Sinônimo Descrição

Dictionary dict todos os objetos do dicionário de dados acessíveis


pelo usuário com uma breve descrição.
user_objects obj objetos pertencentes ao usuário
user_tables tabs descrição das tabelas do usuário
user_sequences seq descrição das sequences do usuário
user_synonym syn sinônimos do usuário
user_views texto das views do usuário
user_indexes ind descrição dos índices do usuário
all_objects objetos acessíveis pelo usuário
tab Contém as tabelas dos usuários

CONSULTANDO NO DICIONÁRIO DE DADOS


Exemplo 1: Tabelas do usuário corrente
select table_name
from user_tables;

Exemplo 2: Colunas do tipo Date na tabela PERIODO_LETIVO:


select column_name
from user_tab_columns
where table_name = ‘PERIODO_LETIVO’
and data_type = ‘DATE’;

Exemplo 3: Informações dos objetos do usuário corrente:


select object_name, object_type, created, status
from user_objects;

67
L A B O R A T O R I O D E B A N C O D E D A D O S

Exemplo 4: Informações dos objetos visíveis pelo usuário corrente:


select object_name, object_type, created
from all_objects;

Exemplo 5: Todos os sinônimos visíveis pelo usuário:


select synonym_name, table_name
from all_synonyms;

Exemplo 6: A definição de uma certa view:


select text
from user_views
where view_name = ‘ALUNOS_NATAL’;

Exemplo 7: Consultar o nome da primary key da tabela MATRICULA:


select constraint_name
from user_constraints
where table_name = ‘MATRICULA’
and constraint_type = ‘P’;

Exemplo 8: Quais colunas compõem a primary key da tabela MATRICULA?


select column_name, position
from user_cons_columns
where constraint_name = ‘MATRICULA_PK’;

VISÕES DINÂMICAS DE DESEMPENHO

São views virtuais que existem na memória apenas quando o banco


de dados está em execução. Pertecem ao usuário SYS e o seu nome sempre
se inicia com V$.
Podemos visualizar todas as views através de:
SELECT * FROM V$FIXED_TABLE
Temos mais algumas views para ajudar na administração do banco
de dados
• V$DATAFILE - contém informações sobre o banco de dados.

• V$CONTROLFILE – contém informações sobre os arquivos de


controle.

• V$DATAFILE - contém informações sobre os arquivos de dados.

68
L A B O R A T O R I O D E B A N C O D E D A D O S

• V$INSTANCE - contém informações sobre a instância atual

• V$PARAMETER – lisa os parâmetros e os valores em efeito na


sessão.

• V$SPPARAMETER – lista o conteúdo do SPFILE.

• V$TABLESPACE – exibe informações sobre tablespaces contidas no


arquivo de controle.

• V$SESSION → exibe todas as sessões conectadas ao banco de


dados (ativa ou não). Encontramos informações de grande valia
na análise e na identificação de problemas como, por exemplo,
tempo de conexão, sessão ativa, identificador do comando SQL
executado, há quanto tempo a sessão está em um determinado
status, os eventos de espera da sessão, qual usuário do sistema
operacional pertence a conexão, qual a máquina origem da
conexão, a quantidade de memória da PGA alocada para a sessão,
etc.
SELECT SID, SERIAL#, USERNAME, COMMAND, LOGON_TIME,
LAST_CALL_ET, WAIT_CLASS, SQL_ADDRESS
FROM V$SESSION
WHERE STATUS = ‘ACTIVE’;

69
L A B O R A T O R I O D E B A N C O D E D A D O S

USUÁRIOS E PRIVILÉGIOS

A razão de ser de um banco de dados e seu DBA são os usuários. Tudo o que
o DBA faz, em última análise, tem por objetivo atender às necessidades do usuário.
O DBA deve conhecer os seguintes detalhes:
• O que o usuário quer?
• O que o usuário precisa?
• Exibe outro usuário que queira ou necessite do mesmo?
• Qual seria o nível mínimo de segurança aceitável?
• E o máximo?
• Exigem regras na empresa que restrinjam a utilização do banco pelo usuário?

CONCEITO EXPLICAÇÃO
USUARIO Individuo que se conecta ao banco de dados e utiliza
objetos nele. Também pode criar objetos e permitir que
outros usuários manipulem.
SCHEMA Conjuntos de objetos (tabelas, índices, visões, etc) de
um usuário. Pode ser listado com o comando:
SELECT * FROM cat;
PRIVILÉGIO Direito que um usuário recebe para fazer algo. Existem
duas categorias:
- sistema: realiza conexão até eliminar qualquer tabela
- objeto: desde ler até eliminar
PAPEL (role) Conjunto de privilégios agrupados e com um nome.
Facilita bastante a gerência de privilégios.

CRIANDO USUARIOS
Sintaxe: CREATE USER nome
IDENTIFIED BY senha
DEFAULT TABLESPACE users
QUOTA UNLIMITED7 ON users;

CONSULTAR USUÁRIOS EXISTENTES


SELECT * FROM ALL_USERS;

PARA ALTERAR A SENHA DE ACESSO


ALTER USER nome IDENTIFIED BY nova_senha;

7 O espaço (cota) pode ser ilimitado, 1M (Mbytes), ou 1K (Kbytes).

70
L A B O R A T O R I O D E B A N C O D E D A D O S

EXCLUINDO UM USUÁRIO
DROP USER nome CASCADE;

PRIVILÉGIOS DE SISTEMA
Ao criar um usuário ele não tem direito de se conectar. Para que possa ser
considerado um usuário, ele deve receber alguns privilégios de sistema: CREATE
SESSION; CREATE TABLE; CREATE SEQUENCE; CREATE VIEW; CREATE USER e
DROP USER.

PRIVILÉGIOS DE CONEXÃO 8 PARA USUARIO CRIADO


GRANT CREATE SESSION TO usuário;

PARA VISUALIZAR OS PRIVILÉGIOS DE SISTEMA ATUAIS


SELECT * FROM SESSION_PRIVS;

PARA VISUALIZAR OS PRIVILÉGIOS DE SISTEMA


SELECT * FROM USER_SYS_PRIVS;

PARA VISUALIZAR OS PRIVILÉGIOS DE OBJETO


SELECT * FROM USER_TAB_PRIVS_MADE;
SELECT * FROM USER_COL_PRIVS_MADE;
Onde:
• GRANTEE Usuário a quem o privilégio foi concedido;
• TABLE_NAME Nome do objeto no qual o privilégio foi concedido;
• COLUMN_NAME Nome da coluna no qual o privilégio foi concedido;
• GRANTOR Usuário que concedeu o privilégio;
• PRIVILEGE Privilégio de objeto;
• GRANTABLE Beneficiado pode conceder ou não o privilégio a outro
• HIERARCHY Privilégio faz parte de uma hierarquia.

PARA CONCEDER PRIVILÉGIOS


Exemplo: GRANT SELECT, INSERT on Cursos To Usuário
[WITH GRANT OPTION];
GRANT SELECT on CURSOS TO PUBLIC
Observação:
• WITH GRANT OPTION permite ao grantee conceder os privilégios de
objetos a outros usuários.
• PUBLIC o privilégio será dado a todos os usuários.

PARA RETIRAR ALGUM PRIVILÉGIO DE SISTEMA

8 Há uma atribuição chamada CONNECT que possui o privilégio de criar sessão.

71
L A B O R A T O R I O D E B A N C O D E D A D O S

REVOKE nome_privilégio FROM usuário

PRIVILÉGIOS DE OBJETO
Privilégios de objeto servem, basicamente para que outros usuários que não
o dono, ou aqueles que tenham privilégios de sistema do tipo ANY possam ler,
alterar ou até mesmo apagar linhas de tabelas.
Privilégio Tabela View Sequence Procedure
ALTER X X
DELETE X X
EXECUTE X
INDEX X
INSERT X X
REFERENCES X
SELECT X X X
UPDATE X X
ALL X X X X

ROLES
É um grupo de privilégios (sistema ou objeto), reunidos sob um único nome,
que pode ser concedido a um ou mais usuários.

CRIANDO ROLES (DESDE QUE POSSUA PRIVILÉGIO)


CREATE ROLE nome_role;
Uma vez criada, a role pode receber privilégios e ser concedida a um usuário:
GRANT privilégio TO nome_role;
GRANT nome_role TO usuário;

PARA VISUALIZAR ROLE S


SELECT * FROM user_role_privs;

CONSULTANDO PRIVILEGIOS CONCEDIDOS


Privilégio Observações
ROLE_SYS_PRIVS Privilégios de sistema concedidos a atribuições
ROLE_TAB_PRIVS Privilégios de tabela concedidos a atribuições
USER_ROLE_PRIVS Atribuições acessíveis ao usuário
USER_TAB_PRIVS_MADE Privilégios de objeto concedidos para os
objetos de usuário
USER_COL_PRIVS_RECD Privilégios concedidos ao usuário em colunas
específicas
USER_SYS_PRIVS Privilégios de sistema concedidos ao usuário

72
L A B O R A T O R I O D E B A N C O D E D A D O S

PRÁTICA DE LABORATÓRIO

1) Crie dois usuários cada um com o seu primeiro nome e a senha sendo as suas
iniciais. Solicitar a troca de senha na primeira conexão e com quota na
tablespace USERS de 10Mb.

2) Crie uma role com o nome de GRUPO e acrescente estes dois usuários.

3) Conceda a esta role os privilégios de conexão, criação de tabela, sequência,


sinônimo e view.

4) Escolha um dos usuários e conecte com ele.

5) Criar as tabelas abaixo:

- Criar a tabela CLIENTE, com codigo como chave primária, número com 5
dígitos, nome do cliente como string de 30 caracteres, telefone com string de
20 caracteres.
- Criar a tabela VEICULO, com placa como chave primaria e string com 10
caracteres, marca do veículo como string de 20 caracteres de preenchimento
obrigatório. Relacionar a tabela CLIENTE com a tabela VEICULO através da
coluna codigo.

6) Criar a sequência CLIENTE_SEQ inicie com 5 com incremento de 5.

7) Inserir 2 registros na tabela utilizando a sequência criada. Confirmar a


transação.

8) Criar um sinônimo chamado PROPRIETARIO para a tabela CLIENTE.

9) Criar uma view chamada vw_cliente_veiculo que exiba o nome do cliente e o


nome do veículo.

10) Revogar o privilégio de criar tabela da role GRUPO.

11) Conectar com o sendo usuário e criar a tabela TESTE com a coluna numero
do tipo INTEGER. O QUE ACONTECEU? POR QUE?

73
L A B O R A T O R I O D E B A N C O D E D A D O S

PL/SQL – VISÃO GERAL

CONCEITOS GERAIS

A linguagem PL/SQL é uma extensão da linguagem SQL. Podemos dizer que


é um dialeto da linguagem SQL especializado no banco de dados ORACLE. Ela
elimina muitas definições da linguagem SQL por ser uma linguagem procedural.
A linguagem PL/SQL combina a facilidade de manipulação de dados da
linguagem SQL9 com as facilidades de programação de uma linguagem procedural.

VANTAGENS:
• Capacidade de organizar comandos SQL em blocos;
• Diminuir o número de comunicações entre cliente e servidor;
• Produtividade;
• Interação com o gerenciador de banco;
• Portabilidade;
• Capacidade procedural (estruturas de controle);
• Tipos de objeto e métodos (a partir da versão 8).

Por meio da linguagem PL/SQL, podemos criar objetos de esquema, como:

• Stored Procedure – (procedimento armazenado). Pode ser uma procedure


ou uma Função. É um programa PL/SQL que pode ser acionado por uma
aplicação, por um trigger ou uma ferramenta ORACLE. A diferença básica
entre procedure e uma função está no fato de que a função executa comandos
e retorna um resultado, enquanto a procedure apenas executa os seus
comandos;
• Package - (pacote) é um arquivo que agrupa funções, cursores, stored
procedures e variáveis em um único lugar;
• Trigger - É um programa PL/SQL armazenado no banco de dados e que é
executado imediatamente antes ou após os comandos INSERT, UPDATE e
DELETE;
• Cursor - O Oracle utiliza áreas de trabalho destinadas a executar comandos
SQL. Por meio de um produto da linguagem PL/SQL chamado cursor, é
possível dar nome para uma dessas áreas de trabalho e acessar sua
informação (dados);
• Blocos PL/SQL – também chamados de anônimos, contém comandos que
não serão armazenados no servidor Oracle.

9Linguagem de quarta geração que descreve o que deve ser feito, mas não como fazê-lo
(detalhes de como o comando é processado fica oculto).

74
L A B O R A T O R I O D E B A N C O D E D A D O S

ESTRUTURA DO PL/SQL

A linguagem PL/SQL utiliza o conceito de bloco estruturado. Esses blocos são


compostos por procedures e funções. Um bloco tem a estrutura básica, como
descrito na imagem logo abaixo e ele é composto por três partes:

DECLARE
- Seção opcional, em que
todos os objetos são
declarados.
BEGIN
- Em que os comandos
PL/SQL são colocados. Pode
conter outros blocos.
EXCEPTION
- Seção opcional, onde os
erros são tratados. (pode
conter outros blocos)
END
- Finaliza o bloco

DECLARAÇÃO

Podemos declarar constantes, variáveis, cursores, estruturas e tabelas.


Para declarar CONSTANTES podemos:
• Especificar com a palavra reservada CONSTANT;
• Atribuir um valor através dos dois pontos e igual (:=);
• Definir um valor com a palavra reservada DEFAULT.
Obs. O valor NULL é atribuído a variáveis que não foram inicializadas.
Exemplo:
constantes
n_alunos CONSTANT NUMBER(4) := 15; ou
n_alunos CONSTANT NUMBER(4) DEFAULT 15;
...
variáveis
valor1 NUMBER(4) := 0; ou
valor1 NUMBER(4) DEFAULT 0;
...
exemplo1 NUMBER(4) NOT NULL := 1;
exemplo2 NUMBER(4);

75
L A B O R A T O R I O D E B A N C O D E D A D O S

Só para lembrar que cada variável ou constante deve ser especificada com
seu nome, tipo e, opcionalmente, valor inicial. Todas as linhas devem terminar
com ponto-e-vírgula. Exemplo:
DECLARE
nome VARCHAR2(20);
numero NUMBER(5,2) := 100;
casado BOOLEAN NOT NULL := TRUE;
data_adm DATE := SYSDATE + 30 ;
contador BINARY_INTEGER := 0;
IDENTIFICADORES

Identificadores são os nomes que damos aos elementos do PL/SQL, sejam


eles: tabelas, cursores ou variáveis. Eles podem ter até 30 caracteres de
comprimento, devem começar com uma letra, e podem ter qualquer combinação
de letras, números, $, #, _ .
Uma constante é um tipo especial de variável, ela tem um tipo de dado e seu
valor é ajustado na criação.
Quando escolhemos um nome de variável, devemos escolher algo que lembre
o melhor possível o propósito da variável e sempre devemos tentar usar um nome
legível.
O PL/SQL permite o uso do caractere underscore ‘_’ de forma que é muito
fácil criar nomes legíveis.

VARIÁVEIS DE SUBSTITUIÇÃO OU DE HOST (LIGAÇÃO).

No SQL * PLUS é representado por & (i comercial). Exemplo → ‘&nome’10,


&salário.
Obs.: os campos date, timestamp, varchar, varchar2 e char precisam vir
entre aspas simples na utilização da linha de comando (SQL * PLS).
Na Home Page ou no Database Control é representado pelos : (dois pontos).
Exemplo→ :nome, :salário.

TIPOS DE DADOS ESCALARES


Todas as constantes e variáveis definidas em nossos programas contém um
tipo de dado. É este tipo de dado que determina o formato de armazenagem, as
restrições em como a variável pode ser usada e quais valores as variáveis podem
ter. Um tipo de dado escalar é atômico, isto significa que ele não é formado por
outros tipos de dados. O PL/SQL tem dois tipos de dados compostos, eles são
registros e tabelas.
TIPOS DE DADOS DO PL/SQL

10 Somente há aspas simples nos campos do tipo VARCHAR, CHAR e DATE.

76
L A B O R A T O R I O D E B A N C O D E D A D O S

• VARCHAR2 ou VARCHAR - Conjunto de caractere de comprimento variável.


• CHAR - Conjunto de caractere de comprimento fixo.
• NUMBER [(precisão, escala)] - Números fixos ou de ponto flutuante.
• BINARY_INTEGER - Valores de inteiros.
• BINARY_FLOAT e BINARY_DOUBLE – valores com ponto flutuante (ocupa
menos espaço e é mais rápido que o tipo NUMBER (presente a partir da versão
10G)).
• PLS_INTEGER - Números para cálculos rápidos de inteiros.
• DATE – Datas;
• TIMESTAMP (precisão) – valor de 0 a 9 por default o valor é 6
• TIMESTAMP (precisão) WITH TIME ZONE;
• TIMESTAMP (precisão) WITH LOCAL TIME ZONE;
• INTERVAL YEAR (precisão) TO MONTH;
• INTERVAL DAY (precisão) TO SECOND;
• BOOLEAN - Valores True / False.
• NVARCHAR2 - Conjunto de caractere de comprimento variável que usam o
conjunto nacional de caracteres.
• NCHAR - Conjunto de comprimento fixo que usam o conjunto nacional de
caractere.
• ROWID - Usado para armazenar rowids físicos (Endereço físico do registro no
Banco de Dados).
• UROWID - Usado para armazenar rowids físicos e lógicos.
• LONG - Usado para armazenar conjuntos longos de caractere.
• LONG RAW - Usado para armazenar grandes quantidades de dados binários e
figuras.
• RAW - Usado para armazenar dados binários.
O QUE É NULL?
Esta é uma pergunta que é feita todo o tempo, mesmo assim muitas pessoas
realmente não sabem qual é a resposta!
NULL é desconhecido. Tenha sempre essas duas coisas em mente:
• Um Null nunca é igual a nada;
• Um Null nunca é igual a algo.
A próxima questão deve ser: ‘Como comparar coisas com valores nulos?’
É onde verificamos se o valor IS NULL ou se IS NOT NULL.
Nossas declarações podem ser limitadas ou não-limitadas. Isto significa que
podemos especificar o valor que pode ser atribuído à variável. Nossa variável
NUMBER suporta até 38 dígitos, se não for limitada.

77
L A B O R A T O R I O D E B A N C O D E D A D O S

O PL/SQL alocará toda a memória que é necessária para armazenar 38


dígitos. Se limitarmos a variável usando NUMBER (2), então o PL/SQL alocará
apenas a memória para armazenar os dois dígitos.
DECLARE
idade NUMBER (3);
nome VARCHAR2(80) := ‘Genoveva Porsidius’;
cidade VARCHAR2(50) DEFAULT ‘Marília’;
pi CONSTANT NUMBER (3,2) := 3.14;
aux NUMBER (5); -- fica com NULL
BEGIN
DECLARE
data DATE DEFAULT SYSDATE;
data_devolucao DATE := data + 30;
BEGIN
princ.cidade := ‘São Paulo’; -- ou cidade := ‘São Paulo’
...
cidade := ‘MARÍLIA’;

ATRIBUTO %TYPE

Variáveis ancoradas referem-se ao uso deste atributo. O PL/SQL ancora o tipo


de dado de uma variável a uma estrutura de dados, geralmente de uma coluna de
uma tabela. Sintaxe: VARIAVEL TABELA.COLUNA_TABELA%TYPE;
DECLARAÇÃO POR REFERÊNCIA
DECLARE
preco NUMBER(12,2);
pvp preco%TYPE := 2000;

BASEADO NUMA COLUNA DE UMA TABELA


DECLARE
nome aluno.nome_aluno%TYPE;

O benefício de tipos de dados de variáveis ancoradas em programas PL/SQL


com colunas de bancos de dados é que quando as declarações base mudam e o
código PL/SQL não precisa ser alterado, facilitando a manutenção do sistema.
Exemplo: v_name employees.first_name%TYPE;
v_balance NUMBER(7,2);
v_min_balance v_balance%TYPE :=10;

78
L A B O R A T O R I O D E B A N C O D E D A D O S

DICAS SOBRE USO DE VARIÁVEIS


• Sempre use nomes claros e tente estabelecer uma convenção de nomes para
seus diferentes tipos de variáveis.
• Evite variáveis recicláveis. Leia esta instrução como NUNCA recicle variáveis.
• Reusar nomes de variáveis com o mesmo programa pode causar mais
problemas do que poderia imaginar. Tente depurar algum assim qualquer dia!
• Utilizar constantes nomeadas sempre que possível e evite o uso de valores
numéricos.
• Remover as variáveis não usadas de seus programas PL/SQL. Muitos
programas PL/SQL desenvolvem-se, em muitos casos, através de muitos anos
e muitas versões.
• Quando as variáveis não estiverem mais sendo usadas, remova-as do
programa. Isto tornará o código muito mais fácil de entender.
• Se a variável representa uma coluna de banco de dados, então ancore a
variável à coluna do banco usando a declaração %TYPE.
• Seguindo essas dicas, você terá uma abordagem consistente para o uso de
variáveis no PL/SQL e não pegará maus hábitos.

DBMS_OUTPUT.PUT_LINE

Um procedimento de pacote fornecido pela Oracle. Uma alternativa para


exibir dados a partir de um bloco PL/SQL. Precisa ser ativado em através do
comando: SET SERVEROUTPUT ON antes de utilizar o pacote DBMS.Exemplo:
DECLARE
v_sal NUMBER(9,2) := &p_anual;
BEGIN
v_sal := v_sal/12;
DBMS_OUTPUT.PUT_LINE(‘O salário mensal é ‘ || TO_CHAR(v_sal));
END;

COMENTÁRIOS

Podemos comentar o código para documentar cada fase e para auxiliar a


depuração, utilizamos dois hífens (--) se o comentário estiver em uma única linha
ou coloque o comentário entre os símbolos /*espaço em branco E espaço em
branco */ se o comentário englobar várias linhas.

OPERADORES EM PL/SQL

As operações na expressão são executadas em uma determinada ordem,


dependendo da precedência (prioridade):

79
L A B O R A T O R I O D E B A N C O D E D A D O S

Quadro 6 - Descrição dos Operadores

OPERADOR DESCRIÇÃO
**, ^, NOT Exponenciação
NOT Negação
:= Atribuição
+,-,*,/ Adição, subtração, multiplicação e divisão
|| Concatenação
=, !=,<,>,>=,<=, IS NULL, Comparação
LIKE, BETWEEN, IN
AND Conjunção
OR Inclusão
@ Acesso remoto
; Finalizar instrução
/ Executar bloco

Obs.: não há necessidade de se utilizar parênteses nas expressões booleanas,


mas, isso facilita a leitura do texto.
Exemplos: v_conta := v_conta + 1; v_equacao := (v_n1 + v_n2);

DIRETRIZES E SINTAXE DE BLOCO

Os identificadores são usados para nomear itens do programa PL/SQL


(constantes, variáveis, extensões, cursores, subprogramas e pacotes). Podem
conter até 30 caracteres, mas deverão ser iniciados com uma letra. Também não
escolha o mesmo nome de uma coluna de tabela de banco de dados.
Os literais são valores booleanos, um valor numérico explícito, um caractere
ou uma string não representada pelo identificador.
Para finalizar um bloco, é usada uma barra (/) em uma linha sozinha (sem
comando).

VARIÁVEIS DE TIPO DE DADOS LOB

O tipo LOB (large object – objeto grande) podemos armazenar blocos de


dados não estruturados (textos, imagens gráficas, videoclipes e formatos de
arquivo para armazenar sons) de até 4 gigabytes em tamanho. Os tipos de dados
LOB fornecem acesso eficiente, aleatório e em intervalos aos dados, podendo ser
atributos de um tipo de objeto. Os LOBs também suportes acesso aleatório a
dados. Podem ser:

80
L A B O R A T O R I O D E B A N C O D E D A D O S

• CLOB (character large objetct – objeto grande caracteres) é usado para


armazenar blocos grandes de dados com caracteres de um único byte no banco
de dados;
• BLOB (binary large object – objeto grande binário) é usado para armazenar
objeto binários grandes no banco de dados em linha (dentro linha de tabela)
ou fora de linha (fora de linha de tabela);
• BFILE (binary file – arquivo binário) é usado para armazenar objetos grandes
binários em arquivos do sistema operacional fora do banco de dados;
• NCLOB (objeto grande de caractere do idioma nacional) é usado para
armazenar blocos grandes de dados NCHAR de byte único ou de bytes múltiplos
de largura fixa no banco de dados dentro e fora da linha.

FUNÇÕES SQL EM PL/SQL

A maior parte das funções SQL, estão disponíveis no PL/SQL, com exceção
das seguintes:
• DECODE;
• Funções de grupo: MIN, AVG, MAX, COUNT e SUM. Estas funções de
aplicam a grupos de linhas em uma tabela e por isso estão disponíveis
apenas em instruções SQL em bloco PL/SQL. Exemplo: v_total :=
SUM(numero_tabela);
Obs.: Também podemos utilizar o TO_CHAR, TO_DATE e TO_NUMBER para
converter tipos de dados.

BLOCOS ANINHADOS E ESCOPO DE VARIÁVEL

Uma das vantagens do PL/SQL é aninhar instruções. Podemos aninhar blocos


onde quer que uma instrução executável seja permitida, transformando o bloco
aninhado em uma instrução. Podemos dividir a parte executável de um bloco em
blocos menores. A seção de exceção poderá conter blocos aninhados.
ESCOPO é a região do programa que pode referenciar outro objeto. É sempre
um identificador daquela região de uma unidade de programa. Exemplo:

...
X BINARY_INTEGER;
BEGIN Escopo
...
DECLARE Escopo
Y NUMBER;
BEGIN
...
END;
...
END;

81
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS
1. Criar um bloco anônimo que entre com dois valores e exiba a somatória entre
eles;

2. Criar um bloco anônimo que forneça o nome e a data de nascimento de uma


pessoa e exiba o seu nome e a sua idade atual;

3. Criar um bloco anônimo que entre com o nome, o cargo e o salário e exiba o valor
a ser descontado de vale transporte (6%);

4. Criar um bloco anônimo que entre com três notas e exiba a média aritmética das
mesmas;

5. Criar um bloco anônimo que entre com o nome de uma mercadoria, o valor desta
mercadoria e o percentual de aumento. Exibir o novo valor desta mercadoria.

6. Elabore um bloco PL/SQL que compute a remuneração total por um ano. O salário
anual e a porcentagem do bônus anual são repassados ao bloco PL/SQL pelas
variáveis de substituição e os benefícios precisam ser convertidos de um número
inteiro para um decimal (exemplo 15 para 0.15). Se o salário for nulo, defina-o
para zero antes de computar a remuneração total. Execute o bloco PL/SQL. Obs.:
utilizar a função NVL. Obs.: Utilizar as tabelas do usuário HR: EMPLOYEES,
DEPARTMENTS.

82
L A B O R A T O R I O D E B A N C O D E D A D O S

INSTRUÇÕES PL/SQL

Apenas um único conjunto de valores pode ser retornado e controla


transações: COMMIT ou ROLLBACK. É possível determinar o resultado com
cursores implícitos quando houver uma ou mais linhas no resultado.

SELECT INTO
Recupera dados do banco de dados com SELECT, atribuindo colunas que
DEVEM ser especificadas para cada variável declarada. Retornando somente uma
linha, se retornar mais de uma linha ou nenhuma ocorre um erro. Sintaxe:
SELECT coluna, coluna2,.., colunan
INTO {nome_variavel | nome_registro, variavel2,..,variaveln11}
FROM tabela WHERE condição;
Exemplo:
DECLARE
v_deptno NUMBER(2);
v_loc NUMBER (15);
BEGIN
SELECT departament_id, location_id
INTO v_deptno, v_loc
FROM departments
WHERE department_name = ‘Sales’;
END;

INSERT, UPDATE E DELETE


Os comandos de manipulação de dados são iguais aos que já vimos
anteriormente:
• INSERT (insere dados);
• UPDATE (atualiza dados);
• DELETE (apaga dados).

11 Estas variáveis utilizadas na cláusula INTO deverão estar declaradas.

83
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS

1. Crie um bloco PL/SQL que selecione o número máximo de departamento na


tabela DEPARTMENTS e exiba resultado.
2. Modifique o bloco anterior para inserir uma nova linha na tabela
DEPARTMENTS:
a) Em vez de imprimir o número do departamento recuperado, adicione 10 a
esse número e use-o como o número do novo departamento.
b) Use um parâmetro de substituição para o nome do departamento.
c) Deixe um valor nulo no id da localização e do gerente.

3. Crie um bloco PL/SQL que delete o departamento criado no exercício anterior.

4. Criar um bloco que entre com o id de um departamento e exiba a soma salarial


de seus empregados.

5. Criar um bloco anônimo que entre com o id de um empregado (EMPLOYEE_ID)


e exiba o seu nome (FIRST_NAME), o título do cargo (JOB_TITLE) e o nome do
departamento (DEPARTMENT_NAME). DICA: Deverá ser usado join.

6. Criar as seguintes tabelas abaixo:


CREATE TABLE produto
(cdproduto NUMBER(10) PRIMARY KEY,
nmproduto VARCHAR2(100) NOT NULL,
qtproduto NUMBER(10),
vlproduto NUMBER(14,2));

CREATE TABLE cliente


(cdcliente NUMBER(5) PRIMARY KEY,
nmcliente VARCHAR2(50),
iccliente CHAR(1),
CONSTRAINT ck_cliente CHECK (iccliente IN (‘J’,’F’)));

CREATE TABLE nota_fiscal


(cdnota NUMBER(10) PRIMARY KEY,
dtemissao DATE,
cdcliente NUMBER(5),
CONSTRAINT fk_nota FOREIGN KEY (cdcliente)
REFERENCES cliente (cdcliente));

84
L A B O R A T O R I O D E B A N C O D E D A D O S

CREATE TABLE item_nota_fiscal


(cdnota NUMBER(10),
cditem NUMBER(10),
qtitem NUMBER(10),
vlunitario NUMBER(14,2),
vltotalitem NUMBER(14,2),
vltotalgeral NUMBER(14,2),
vldesconto NUMBER(14,2),
vltotaldesconto NUMBER(14,2),
CONSTRAINT pk_item PRIMARY KEY (cdnota, cditem),
CONSTRAINT fk_item FOREIGN KEY (cdnota)
REFERENCES nota_fiscal (cdnota));

7. Utilizando um bloco anônimo inserir um registro em uma das tabelas.

8. Utilizando um bloco anônimo deletar um registro de uma das tabelas.

9. Criar um bloco anônimo que caso o cliente seja pessoa física dar um desconto
de 10% no total da nota emitida.
Obs.: deverá ser inserido os dados da NOTA_FISCAL.

10.Criar um bloco que entre com um valor em real a cotação do dólar do dia e
exiba o valor convertido em dólar. Teste: cotação do dia 15/01/2019: R$
3,72.

85
L A B O R A T O R I O D E B A N C O D E D A D O S

ESTRUTURAS DE CONTROLE

Podemos alterar o fluxo lógico de instruções dentro do bloco PL/SQL com


diversas estruturas para controle. Temos dois tipos:
• Construções Condicionais com a instrução IF.
• Estruturas para controle LOOP.

INSTRUÇÃO IF

Figura 23 - Estrutura de Controle

Há três tipos de instrução IF:


• IF-THEN-END IF;
• IF-THEN-ELSE-END IF;
• IF-THEN-ELSIF-END IF.

Sintaxe:
IF condição THEN
Instrução;
[ELSIF condição THE
instrução;]
[ELSE
instrução;]
END IF;

86
L A B O R A T O R I O D E B A N C O D E D A D O S

Observações:
Usamos o ELSE quando a condição for falsa ou nula.
O END-IF finaliza a estrutura condicional.
Podemos em uma instrução ter vários ELSIF’s, porém somente um ELSE.
Exemplo:
DECLARE
v_valor NUMBER(14,2) := :VALOR;
v_forma VARCHAR2(15) := :FORMA;
BEGIN
IF v_forma = ‘DINHEIRO’ THEN
v_valor := v_valor – (v_valor*0.2);
ELSIF v_forma = ‘CHEQUE’ THEN
v_valor := v_valor – (v_valor*0.15);
ELSE
DBMS_OUTPUT.PUT_LINE12(´Não há desconto!’);
END IF;
DBMS_OUTPUT.PUT_LINE (‘Valor a pagar é de ‘ || v_valor);
END;
/

LOOPS (LAÇOS)
Obs.: Para este tópico criar a tabela abaixo:
CREATE TABLE loop
(numero NUMBER(3),
Tipo VARCHAR(20));

Os loops repetem uma instrução ou sequência de instruções várias vezes.


Existem três tipos de loop: Básico, FOR e WHILE, onde:
• Básico ou Simples → fornece ações repetitivas sem condições gerais;
• For → fornece controle iterativo para ações com base em uma contagem;
• While → fornece controle iterativo para ações com base em uma condição.

LOOP
É o formato mais simples. Delimita uma sequência de instruções entre as
palavras-chaves LOOP e END-LOOP. Sempre que o fluxo de execução atinge a
instrução END LOOP, o controle retorna à instrução LOOP correspondente acima.
Um loop básico permite a execução de sua instrução pelo menos uma vez, mesmo
que a condição já esteja atendida no momento em que o loop foi informado. Sem
a instrução EXIT WHEN13, o loop seria infinito. Sintaxe:
LOOP
Comandos;
EXIT WHEN condição;
END LOOP;

12
Para este comando ser realizado é necessário ser habilitado com SET SERVEROUTPUT ON.
13 Na versão 11G podemos ter o comando CONTINUE WHEN além do comando EXIT WHEN.

87
L A B O R A T O R I O D E B A N C O D E D A D O S

Obs.: a instrução EXIT WHEN finaliza um loop.


Exemplo: Criar um loop que insira na tabela LOOP, números até 10:
DECLARE
v_num NUMBER(3) := 1;
BEGIN
LOOP
INSERT INTO loop VALUES (v_num. ‘LOOP’);
COMMIT;
v_num := v_num + 1;
EXIT WHEN v_num > 10;
END LOOP;
END;

FOR
Possui a mesma estrutura de um loop básico. Além disso, ele tem uma
instrução para controle no início da palavra chave LOOP para determinar o numero
de iterações que o PL/SQL executa. Sintaxe:
FOR contador IN [REVERSE] início.. fim LOOP
comandos;
END LOOP;

Obs.: REVERSE faz o contador decrescer a cada iteração a partir do limite


superior até o limite inferior.

Exemplo: Criar um loop que insira na tabela LOOP os números de 11 a 20:


DECLARE
v_inicio NUMBER(2) := 11;
v_fim NUMBER(2) := 20;
BEGIN
FOR I IN v_inicio..v_fim LOOP
INSERT INTO loop
VALUES (I, ‘FOR’);
COMMIT;
END LOOP;
END;

WHILE
Usado para repetir uma seqüência de instruções até a condição para
controle. Não ser mais verdadeira. A condição é avaliada ao início de cada iteração.
O loop terminará quando a condição for falsa. Se a condição for falsa no início do
loop, nenhuma iteração futura será executada. Sintaxe:
LOOP
Comandos;

88
L A B O R A T O R I O D E B A N C O D E D A D O S

EXIT WHEN condição;


END LOOP;
Exemplo: Criar um loop que insira na tabela LOOP os números até 21 até
um limite informado:
DECLARE
v_inicio NUMBER(2):= 1;
v_fim NUMBER(2):= :LIMITE;
BEGIN
WHILE v_inicio < v_fim LOOP
INSERT INTO loop
VALUES (v_num. ‘WHILE’);
COMMIT;
v_num := v_num + 1;
END LOOP;
END;

EXERCÍCIOS PRÁTICOS

1. Criar um bloco PL/SQL que apresente todos os anos bissextos entre 2000 e
2100. Um ano será bissexto quando for possível dividir este ano por 4, mas não
por 100 ou quando puder ser dividido por 400.

2. Criar um bloco que de acordo com o salário informado, exiba o valor de INSS
conforme a tabela abaixo:

Obs. O valor de contribuição acima de R$ 5.645,80 é de R$ 570,82.

89
L A B O R A T O R I O D E B A N C O D E D A D O S

3. Crie um bloco anônimo que altere o bloco anônimo para que informe se o
número é par ou ímpar.

4. Crie uma tabela chamada mensagem com campo resultado VARCHAR2(60).


Criar um bloco que insira números na tabela mensagem.
a) inserir os números de 1 a 10, excluindo 6 e 8;
b) faça um COMMIT antes do final do bloco;
c) faça seleção na tabela MENSAGEM

5. Criar um bloco anônimo que informe um número de 1 a 10 e exiba a tabuada.


Obs. Deverá ter uma restrição para aceitar somente números de 1 a 10.

6. Alterar o exercício 5 para exibir todas as tabuadas de 1 a 10.

7. Adicione uma coluna chamada STATUS de tipo de dado VARCHAR2 e o


comprimento 40 à tabela EMPLOYEES para armazenar asteriscos (*).

8. Crie um bloco PL/SQL que premie um funcionário, anexando um asterisco à


coluna STATUS para cada 1000,00 do salário do funcionário. Salve o bloco
PL/SQL em um arquivo nomeado:
a) Aceitar o ID do funcionário como entrada do usuário com uma variável de
substituição do SQL * Plus;
b) Inicialize uma variável que conterá uma string de asteriscos;
c) Anexe um asterisco à string para cada 1000,00 do salário. Por exemplo, se
o funcionário recebe um salário de 8000,00 a string deverá conter oito
asteriscos.
d) Atualize a coluna STATUS do funcionário com a string de asteriscos;
e) Efetue um commit;
f) Teste o bloco dos funcionários que não têm salário de um funcionário que
tem um salário.

90
L A B O R A T O R I O D E B A N C O D E D A D O S

CURSORES EXPLÍCITOS

O Oracle usa áreas de trabalho chamadas de AREAS SQL PARTICULARES


para executar instruções SQL e para armazenar informações de
processamento. Podemos usar cursores do PL/SQL para nomear uma área SQL
particular e acessar suas informações armazenadas.
O cursor orienta todas as fases do processamento. Os cursores podem ser
de dois tipos:
• IMPLÍCITO: declarados implicitamente pelo PL/SQL para todas as instruções
DML e PL/SQL Select, incluindo consultas que retornam somente uma linha;
• EXPLÍCITO: consultas que retornam mais de uma linha. Os cursores
explícitos são declarados e nomeados pelo programador e manipulados
através de instruções específicas nas ações executáveis do bloco.

CURSORES IMPLÍCITOS

O Oracle abre implicitamente um cursor para processar cada instrução


SQL que não associada a um cursor declarado explicitamente. O PL/SQL
permite que consulte o cursor implícito mais recente como o cursor PL/SQL.
Não é possível usar as instruções OPEN, FETCH e CLOSE para controlar o
cursor SQL, mas pode usar atributos de cursor para obter informações sobre a
instrução SQL executada mais recentemente.

CURSORES EXPLÍCITOS

Usado para processar individualmente cada linha retorna por uma


instrução SQL de várias linhas.
O conjunto de linhas retornado por uma consulta de várias linhas é
chamado de CONJUNTO ATIVO. Seu tamanho é o número de linhas que atende
aos critérios da pesquisa. Um cursor aponta para a linha atual do conjunto
ativo.
Isso permite que o programa processe as linhas uma de cada vez.
Um programa PL/SQL abre um cursor, processa linhas por uma consulta
e, em seguida, fecha o cursor. O cursor marca a posição atual no conjunto
ativo.
FUNÇÕES DO CURSOR EXPLÍCITO:
• Pode processar além da primeira linha retornada pela consulta, linha por
linha;
• Controla que linha está sendo processada no momento;
• Permite que o programador controle as linhas manualmente no bloco
PL/SQL.
91
L A B O R A T O R I O D E B A N C O D E D A D O S

CONTROLANDO CURSORES EXPLÍCITOS

Para controlar os cursos explícitos utilizamos quatro comandos:


o
Si
DECLARE OPEN FETCH ID m CLOSE
?

Cria uma Identifica o Carrega a Testa para


Libera o
Área SQL conjunto ativo linha atual linhas
conjunto
Figura 24 - Estrutura do Cursor Explícito

1. Declare o cursor nomeando-o e definindo a estrutura da consulta a ser


executada dentro dele (DECLARE);
2. Abra o cursor. A instrução OPEN executa a consulta e vincula as variáveis
que estiverem referenciadas. As linhas identificadas pela consulta são
chamadas de CONJUNTO ATIVO e estão agora disponíveis para extração;
3. Extraia dados do cursor, comando FETH, que busca as linhas do cursor.
Após cada extração, testamos o cursor para qualquer linha existente. Se
não existirem mais linhas para serem processadas, precisamos fechar o
cursor.
4. Feche o cursor. A instrução CLOSE libera o conjunto ativo de linhas. É
possível reabrir o cursor e estabelecer um novo conjunto ativo.
Usamos as instruções OPEN, FETCH e CLOSE para controlar um cursor. A
instrução OPEN executa a consulta associada ao cursor, identifica o conjunto
ativo e posiciona o cursor (indicador) antes da primeira linha. A instrução
FETCH recupera a linha atual e avança o cursor para a próxima linha. Após o
processamento da última linha, a instrução CLOSE desativa o cursor.

DECLARANDO O CURSOR

Utilize a instrução CURSOR para declarar um cursor explícito. Pode-se


fazer referência a variáveis dentro da consulta, mas devemos declará-las antes
da instrução CURSOR. Sintaxe: CURSOR nome_cursor IS consulta (sem INTO)
Exemplo: Recupere os funcionários um a um.
DECLARE
v_id employees.employee_id%TYPE;
v_nome employees.first_name%TYPE;
CURSOR emp_cursor IS

92
L A B O R A T O R I O D E B A N C O D E D A D O S

SELECT employee_id, first_name


FROM employees;
BEGIN

END;
/

ABRINDO O CURSOR
Abre o cursor para executar uma consulta e identificar o conjunto ativo que
consiste em todas as linhas que atendem aos critérios de pesquisa da consulta. O
cursor aponta agora para a primeira linha do conjunto ativo.
Sintaxe: OPEN nome_cursor;
Exemplo: OPEN emp_cursor;

EXTRAINDO DADOS DO CURSOR

A instrução FETCH recupera as linhas no conjunto ativo uma de cada vez.


Após a extração, o cursor avança para a próxima linha no conjunto ativo.
Sintaxe: FETCH nome_cursor INTO [variável1, variável2,...|nome_registro];
Observações:
• Inclua o mesmo número de variáveis na cláusula INTO da instrução FETCH
do que as colunas na instrução SELECT e certifique-se de que os tipos de
dados são compatíveis;
• Faça a correspondência de cada variável para coincidir com a posição das
colunas;
• Como alternativa, defina um registro para o cursor e faça referência do
registro na cláusula FETCH INTO;
• Teste para verificar se o cursor possui linhas. Se uma extração não obtiver
valores, não existem linhas remanescentes para serem processadas no
conjunto ativo e nenhum erro será registro.
Exemplo: FETCH emp_cursor INTO v_id, v_nome;
Exemplo: Recuperar os primeiros 10 funcionários um a um.
DECLARE
v_id employees.employee_id%TYPE;
v_nome employees.first_name%TYPE;
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
BEGIN
OPEN emp_cursor;
FOR i IN 1..10 LOOP
FETCH emp_cursor INTO v_id, v_nome;

93
L A B O R A T O R I O D E B A N C O D E D A D O S


END LOOP;
END;

FECHANDO O CURSOR
A instrução CLOSE desativa o cursor e o conjunto ativo se torna indefinido.
Feche o cursor após completar o processamento da instrução SELECT. Essa
etapa permite que o cursor seja reaberto se necessário, assim, podemos
estabelecer um conjunto ativo, várias vezes. Sintaxe: CLOSE nome_cursor;
Observações:
• Caso queira extrair dados de um cursor que esteja fechado será criada uma
exceção INVALID_CURSOR;
• Podem terminar um bloco sem fechar o cursor, porém existe um limite
máximo de cursores abertos por usuário que é determinado pelo parâmetro
OPEN_CURSORS no campo de parâmetros do banco de dados. (Por default
é 50).
Exemplo: ….
FOR i IN 1..10 LOOP
FETCH emp_cursor INTO v_id, v_nome;

END LOOP;
CLOSE emp_cursor;
END;

ATRIBUTOS DO CURSOR EXPLÍCITO


Existem quatro atributos para obter informações de status sobre um
cursor. Quando anexado ao nome da variável do cursor, esses atributos
retornam informações úteis sobre a execução de uma instrução de
manipulação de dados:
Quadro 7 – Principais Atributos do cursor explícito (feito pelo Autor)

Atributo Tipo Descrição


%ISOPEN Booleano Validado para TRUE se o cursor estiver aberto
%NOTFOUND Booleano Validado para TRUE se a extração mais recebendo não
retornar uma linha
%FOUND Booleano Validado para TRUE se a extração mais recente não
retornar uma linha (complemento de %NOTFOUND)
%ROWCOUNT Número Validado para o número total de linhas retornadas até
o momento.

CONTROLANDO VÁRIAS EXTRAÇÕES

Para processar várias linhas de um cursor explícito, normalmente define um loop


para realizar uma extração em cada iteração. Finalmente todas as linhas no conjunto

94
L A B O R A T O R I O D E B A N C O D E D A D O S

ativo serão processadas e uma extração malsucedida define o atributo %NOTFOUND


para TRUE. Usado para testar o êxito de cada extração antes que sejam feitas
referências futuras para o cursor. Se omitir o um critério de saída o resultado é um
loop infinito.

ATRIBUTO %ISOPEN

Podemos extrair linhas somente quando o cursor está aberto. Use o atributo de
cursor %ISOPEN para determinar se o cursor está aberto, se necessário. Extrai as
linhas através de um loop. Use os atributos de cursor para determinar o momento
para sair do loop. Use o atributo de cursor %ROWCOUNT para recuperar um número
exato de linhas, extrair as linhas em um loop FOR numérico ou extrair as linhas em
um loop simples e determinar o momento para sair do loop. Exemplo:
IF NOT emp_cursor%ISOPEN THEN
OPEN emp_cursor;
END IF;
LOOP
FETCH emp_cursor…

ATRIBUTOS %NOTFOUND E %ROWCOUNT

Use o atributo de cursor %ROWCOUNT para recuperar um número exato de


linhas. E o atributo %NOTFOUND para determinar quando sair do loop.
Exemplo: Recupere os primeiros 10 funcionários um por um:
DECLARE
v_id employees.employee_id%TYPE;
v_nome employees.first_name%TYPE;
CURSOR emp_cursor IS
SELECT employee_id, first_name
FROM employees;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_id, v_nome;
EXIT WHEN emp_cursor%ROWCOUNT > 10 OR
Emp_cursor%NOTFOUND;

END LOOP;
CLOSE emp_cursor;
END;
/

95
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS

1. Criar um bloco que entre com o id do departamento e exiba o nome, o título


do cargo e o salário de todos os funcionários deste departamento.

2. Criar a tabela a seguir:


CREATE TABLE FUNCIONARIO
(id INTEGER PRIMARY KEY,
Salbruto NUMBER(10,2),
Valetransp NUMBER(10,2).
Salliq NUMBER(10,2),
CONSTRAINT func_fk FOREIGN KEY (id)
REFERENCES employees (employee_id));

3. Criar um bloco que insira na tabela FUNCIONARIO a matrícula dos funcionários


e o salário.

4. Criar um bloco que calcule 6% sobre o salário e atualize as colunas valetransp


e o salliq (salbruto – valtransp) da tabela FUNCIONARIO.

5. Criar a tabela abaixo para armazenar os funcionários e seus salários:


CREATE TABLE top
(nome VARCHAR2(50),
salario NUMBER(14,2))

6. Crie um bloco PL/SQL que determine os funcionários com os maiores salários:


a) Aceite o número n como entrada de usuário com um parâmetro de
substituição;
b) Em um loop, obtenha os sobrenomes e salários das n pessoas com maiores
salários da tabela EMPLOYEES;
c) Armazene os nomes e salários na tabela TOP;
d) Pressuponha que não existam dois funcionários com salários iguais;
e) Teste diversos casos especiais, como n=0 ou onde n seja maior do que o
número de funcionários na tabela EMPLOYEES. Esvazie a tabela TOP depois
de cada teste.

7. Considere o caso em que vários funcionários recebem o mesmo salário. Se


uma pessoa estiver listada, todos que tiverem o mesmo salário também
deverão ser exibidos:
a) Por exemplo se o funcionário informar um valor 2 para n, King, Ford e
Scott deverão ser exibidos (serão reunidos pelo segundo maior salário);
b) Se o usuário informar um valor 3, King, Ford, Scott e Jones deverão ser
exibidos;
c) Apague todas as linhas de TOP e teste o exercício.

96
L A B O R A T O R I O D E B A N C O D E D A D O S

EXCEÇÕES

Exceção é um identificador em PL/SQL, criado durante a execução de um


bloco que termina seu corpo principal de ações. Um bloco sempre termina quando
o código PL/SQL cria uma exceção, mas especifica um handler de exceções para
executar ações finais.
Podemos criar uma exceção utilizando dois métodos:
• Ocorre um erro do Oracle e a exceção associada é criada
automaticamente;
• Crie uma exceção explicitamente emitindo a instrução RAISE dentro do
bloco.
CAPTURANDO UMA EXCEÇÃO

Quando a exceção é criada na seção executável do bloco, o processamento é


desviado para o handler de exceção correspondente na seção de exceção do bloco.
Se o código PL/SQL tratar a exceção com êxito, à exceção não propagará para o
ambiente ou bloco delimitado. O bloco PL/SQL é concluído com êxito.
Podemos capturar qualquer erro incluindo uma rotina correspondente dentro
da seção de tratamento do bloco PL/SQL. Cada handler consiste em uma cláusula
WHEN que especifica uma exceção, seguida por uma seqüência de instruções a
serem executadas quando essa exceção for criada.
Sintaxe: EXCEPTION
WHEN exceção1 [OR exceção2..] THEN
Instrução1;
Instrução2;

WHEN OTHER14 THEN
Instrução1;
Instrução2;
….
Obs.: OTHERS é uma cláusula de manipulação de exceção opcional que
captura exceções não especificadas.

• WHEN OTHERS → a seção tratamento de exceção captura somente as exceções


especificadas; quaisquer outras exceções não serão capturadas exceto se
estivermos usando o handler de exceção OTHERS. Esse handler captura
qualquer exceção que ainda não esteja tratada. Por essa razão, OTHERS é o
último handler de exceção a ser definido. Este handler captura todas as
exceções ainda não capturadas. Exemplo:
DECLARE

14Clausula de manipulação de exceção opcional que captura exceções não especificadas (não
tratadas). É sempre o último handler de exceção.

97
L A B O R A T O R I O D E B A N C O D E D A D O S

v_largura INTEGER;
v_altura INTEGER := 2;
v_area INTEGER := 6;
BEGIN
-- configura a largura igual a área dividida pela altura
v_largura := v_area / v_altura;
DBMS_OUTPUT.PUT_LINE(‘v_largura: ‘ || v_largura);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE(‘Divisão por zero...’);
END;

Agora, inicializar a altura com o valor zero.

• DIRETRIZES PARA CAPTURA DE EXCEÇÕES:


o Inicie a seção de tratamento de exceções do bloco com a palavra-chave
EXCEPTION;
o Defina vários handles de exceção do bloco com a palavra-chave
EXCEPTION;
o Quando ocorre uma exceção, código PL/SQL processa somente um handler
antes de sair do bloco;
o Coloque a cláusula OTHERS após todas as outras cláusulas de tratamento
de exceção.

PROPAGANDO UMA EXCEÇÃO


Se a exceção for criada na seção executável do bloco e não houver handler
de exceção correspondente, o bloco PL/SQL terminará com falha e a exceção será
propagada para o ambiente de chamada.
TIPOS DE EXCEÇÃO
Podemos programar exceções a fim de evitar transtornos no tempo d
execução. Há três tipos de exceções:

Quadro 8 - Tipos de Exceptions

EXCEÇÃO DESCRIÇÃO ORIENTAÇÃO PARA


TRATAMENTO
Erro predefinido pelo Um dos cerca de 20 erros Não declare e permita que
Oracle Server que ocorrem com mais o Oracle Server crie as
frequência no código exceções implicitamente.
PL/SQL.
Qualquer outro erro Declare dentro da seção
Erro não predefinido pelo padrão do Oracle Server. declarativa e permita que
Oracle Server. o Oracle Server crie as

98
L A B O R A T O R I O D E B A N C O D E D A D O S

exceções de forma
implícita.
Uma condição que o Declare dentro da seção
Erro definido pelo desenvolvedor determina declarativa e crie
usuário. seja anormal. exceções de forma
explícita.

CAPTURANDO ERROS PREDEFINIDOS


Capture um erro predefinido do Oracle fazendo referência ao seu nome
padrão dentro da rotina de tratamento de exceção correspondente.

Quadro 9 - Principais Exceções (feito pelo Autor)

NOME DA EXCEÇÃO ERRO DESCRIÇÃO


Tentativa de atribuir valores
ACCESS_INTO_NULL ORA-06530 aos atributos de um objeto não
inicializado.
Nenhuma das cláusulas WHEN
de uma instrução CASE foi
CASE_NOT_FOUND ORA-06592 selecionada e não há nenhuma
cláusula ELSE padrão.
Tentativa de aplicação de
métodos de conjunto diferentes
COLLECTION_IS_NULL ORA-06531 de EXISTS para um varray ou
tabela aninhada não
inicializada.
CURSOR_ALREADY_OPEN ORA-06511 Tentativa de abertura de um
cursor já aberto.
DUP_VAL_ON_INDEX ORA-00001 Tentativa de inserção de um
valor duplicado.
INVALID_CURSOR ORA-01001 Ocorreu operação ilegal de
cursor.
INVALID_NUMBER ORA-01722 Falha de conversão de string de
caracteres para número
Estabelecendo login com o
LOGIN_DENIED ORA-01017 Oracle com um nome de
usuário ou senha inválida.
NO_DATA_FOUND ORA-01403 SELECT de linha única não
retornou dados.
O programa PL/SQL emite uma
NOT_LOGGED_ON ORA-01012 chamada de banco de dados
sem estar conectado ao Oracle
PROGRAM_ERROR ORA-06501 O código PL/SQL tem um
problema interno.
Variável de cursor de host e
variável de cursor PL/SQL
ROWTYPE_MISMATCH ORA-06504 envolvida em um atributo têm
tipos de retorno incompatíveis.
Tentativa de chamar um
método MEMBER em um objeto

99
L A B O R A T O R I O D E B A N C O D E D A D O S

SELF_IS_NULL ORA-30625 nulo. Isto é, o parâmetro


interno SELF (sempre primeiro
membro passado para o
MEMBER) é nulo.
O PL/SQL esgotou a memória
STORAGE_ERROR ORA-06500 ou a memória está corrompida.
Feita referência a um elemento
de varray ou tabela aninhada
SUBSCRIPT_BEYOND_COUNT ORA-06533 usando um número de índice
fora da faixa legal (-1, por
exemplo)
Tentativa de referenciar um
elemento de tabela aninhada ou
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 varray usando um número de
índice que está fora do intervalo
válido (exemplo:-1)
Conversão de uma string de
caracteres em um rowid
SYS_INVALID_ROWID ORA-01410 universal falhou porque a string
não representa um rowid
válido.
Ocorreu um timeout enquanto o
TIMEOUT_ON_RESOURCE ORA-00051 Oracle está aguardando por um
recurso.
TOO_MANY_ROWS ORA-01422 SELECT de uma única linha
retornou mais de uma linha.
Ocorreu erro aritmético, de
VALUE_ERROR ORA-06502 conversão, truncamento ou
restrição de tamanho. Quando
ocorre em uma instrução SQL
(ao invés de PL/SQL) a
mensagem é
INVALID_NUMBER.
ZERO_DIVIDE ORA-01476 Tentativa de divisão por zero.

EXCEÇÃO PREDEFINIDA
Somente uma exceção é criada e tratada a qualquer momento.
Sintaxe: BEGIN
EXCEPTION
WHEN NO_DATA_FOUND THEN
Instruções;
WHEN TOO_MANY_ROWS THEN
Instruções;
WHEN OTHERS THEN
Instruções;
END;

100
L A B O R A T O R I O D E B A N C O D E D A D O S

EXCEÇÃO ZERO_DIVIDE

Ocorre quando há uma tentativa de dividir um número por zero. O


exemplo a seguir tenta dividir 1 por 0 no bloco BEGIN.
Exemplo: BEGIN
DBMS_OUTPUT.PUT_LINE(1/0);
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE(‘Divisão por zero...’);
END;

Retire as linhas de EXCEPTION e WHEN e verifique a mensagem de


erro sem estar tratada:

Figura 25 - Mensagem de erro de uma exceção não tratada (feito pelo autor).

EXCEÇÃO DUP_VAL_ON_INDEX
Tentativa de armazenar valores duplicados em uma coluna com índice
exclusivo. Exemplo:
BEGIN
INSERT INTO customers(customer_id, first_name,last_name)
VALUES (1, ‘Greg’, ‘Green’);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE(‘Valor Duplicado’);
END;

EXCEÇÃO INVALID_NUMBER
Tentativa de converter uma string de caractere inválida em um número.
Exemplo: Converte a string 123X em um número
BEGIN
INSERT INTO customers(customer_id, first_name,last_name)

101
L A B O R A T O R I O D E B A N C O D E D A D O S

VALUES (‘123X’, ‘Greg’, ‘Green’);


EXCEPTION
WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE(‘Falha na conversão de numero da string’);
END;

EXCEÇÃO OTHERS
Usada para tratar todas as exceções. Exemplo:
BEGIN
DBMS_OUTPUT.PUT_LINE(1/0);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Ocorreu uma exceção...’);
END;
Como OTHERS significa todas exceções, se tivermos o tratamento de mais
um tipo, ela deverá ser a última exceção a ser tratada. Exemplo:
BEGIN
DBMS_OUTPUT.PUT_LINE(1/0);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Ocorreu uma exceção...’);
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE(‘Divisão por zero...’);
END;

CAPTURANDO ERROS NÃO PREDEFINIDOS


Capturamos um erro não predefinido do Oracle Server declarando-o primeiro
ou usando o handler OTHERS. A exceção declarada é criada implicitamente. Em
PL/SQL, o PRAGMA 15 EXCEPTION_INIT informa o compilador para associar um
nome de exceção a um número de erro do Oracle, permitindo que seja consultado
qualquer exceção interna por nome e crie um handler específico para ela.

Figura 26 – Funcionamento do PRAGMA EXCEPTION_INIT (feito pelo Autor)

Também chamado de pseudo-instruções é uma palavra-chave que significa que a instrução é


15

um diretiva de compilador que não é processada ao executar o bloco PL/SQL.

102
L A B O R A T O R I O D E B A N C O D E D A D O S

ERROS NÃO PREDEFINIDOS

Passos para capturar uma exceção não predefinida:


1. Declare o nome para a exceção na seção declarativa;
2. Associe a exceção declarada ao número de erro padrão do Oracle Server
usando a instrução PRAGMA EXCEPTION_INIT;
3. Faça referência à exceção declarada dentro da rotina de tratamento de
exceção correspondente.
Exemplo: Capturar por número de erro do Oracle Server -2292, uma violação
de restrição de integridade:
DECLARE
E_emp EXCEPTION;
PRAGMA EXCEPTION_INIT (E_emp, -2292);
v_dept departments.department_id%TYPE := :p_dept;
BEGIN
DELETE FROM departments WHERE department_id = v_dept;
COMMIT;
EXCEPTION
WHEN E_emp THEN
DBMS_OUTPUT.PUT_LINE(‘ Não é possível ser removido, há empregados
neste departamento ‘);
END;

FUNÇÕES DE CAPTURA DE EXCEÇÕES


Quando ocorre uma exceção podemos identificar o código a mensagem de
erro associado usando duas funções. Com base nos valores de código ou
mensagem, podemos decidir qual ação subseqüente tomar com base no erro:

Quadro 10 - Descrição Funções de Erro

FUNÇÃO DESCRIÇÃO
SQLCODE Retornar um valor numérico do código de erro, podemos atribuir a
uma variável NUMBER
SQLERRM Retorna os dados de caracteres que contém a mensagem
associada ao número do erro.
Exemplo de Valores do SQLCODE
• 0 → Nenhuma exceção encontrada;
• 1 → Exceção definida pelo usuário;
• +100 → Exceção NO_DATA_FOUND
• Número negativo→ Outro número de erro do Oracle.
DECLARE
v_error_codigo NUMBER.

103
L A B O R A T O R I O D E B A N C O D E D A D O S

V_error_mensagem VARCHAR(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
v_error_codigo := SQLCODE;
v_error_mensagem := SQLERRM;
INSERT INTO errors
VALUES (v_error_codigo, v_error_mensagem);
END;

Exemplo: Criar um bloco que atualiza a descrição de um produto. Criar uma


exceção e imprimir uma mensagem para o usuário alertando-os de que foi incluído
um número de produto inválido:
DECLARE
E_invalido EXCEPTION;
BEGIN
UPDATE produto
SET descrição = :produto
WHERE id_produto = :id;
IF SQL%NOTFOUND THEN
RAISE E_invalido;
END IF;
COMMIT;
EXCEPTION WHEN E_invalido THEN
DBMS_OUTPUT.PUT_LINE (‘Número Inválido’);
END;

CAPTURANDO EXCEÇÕES DEFINIDAS PELO USUÁRIO


Podemos definir suas próprias exceções que são definidas pelo usuário:
• Declaradas na seção de declaração de um bloco;
• Criadas explicitamente com instrução RAISE.

Figura 27 – Funcionamento da exceção definida pelo usuário (feito pelo autor)

104
L A B O R A T O R I O D E B A N C O D E D A D O S

PROCEDIMENTO RAISE_APPLICATION_ERROR

Use o procedimento RAISE_APPLICATION_ERROR para comunicar uma


exceção predefinida interativamente retornando um código ou uma mensagem de
erro não padronizada. Com RAISE_APPLICATION_ERROR podemos relatar erros
para a aplicação e evitar o retorno de exceções não tratáveis. OBSERVAÇÕES:
Numero de erro: número especificado pelo usuário para a exceção entre -20000 e
-20999. Exempl:
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20201, ‘Numero de gerente inválido’);
END;

EXERCÍCIOS PRÁTICOS
1. Crie um bloco PL/SQL que imprima o número de funcionários que recebem mais
ou menos que R$ 500,00 de salário.
a) Se não houver funcionário nessa faixa de salário, imprima uma mensagem
para o usuário indicado que é esse o caso. Use uma exceção para esse caso.
b) Se houver um ou mais funcionários dentro dessa faixa, a mensagem deverá
indicar quantos funcionários estão naquela faixa salarial.
c) Trate quaisquer outras exceções com um handler de exceção apropriado. A
mensagem deve indicar que ocorreu algum outro erro.

2. Criar a tabela MENSAGEM com a coluna texto VARCHAR(100) e crie um bloco


PL/SQL para selecionar o nome do funcionário com um determinado salário.
a. Se o salário informado retornar mais de uma linha, trate a exceção com
um handler de exceção apropriado e insira, na tabela MESSAGEM, a
mensagem "Há mais de um empregado com o salário <salário>".
b. Se o salário informado não retornar qualquer linha, trate a exceção com
um handler de exceção apropriado e insira, na tabela MESSAGEM, a
mensagem "Não há empregado com este salário <salário>”.
c. Se o salário informado retornar apenas uma linha, insira, na tabela
MESSAGEM, o nome do funcionário e o valor do salário.
d. Trate qualquer outra exceção com um handler de exceção apropriado e
insira, na tabela MESSAGEM, a mensagem "Ocorreu um outro erro".
e. Teste o bloco para vários casos.

105
L A B O R A T O R I O D E B A N C O D E D A D O S

PROCEDURES
Um procedimento é um bloco PL/SQL nomeado que pode obter parâmetros16 e
que pode ser chamado. Ou seja, um procedimento é usado para executar uma ação e
possui cabeçalho, seção para declaração, seção para execução e uma seção para
tratamento de exceção.
Os procedimentos promovem a reutilização e a manutenção. Uma vez validados,
podem ser usados em qualquer número de aplicações. Se a definição for alterada,
somente o procedimento será afetado, simplificando assim a manutenção. Sintaxe:
CREATE [OR REPLACE] PROCEDURE nome_do_procedimento
(parâmetro1 [modo1] tipo_de_dados1,
Parâmetro2 [modo2] tipo_de_dados2, ...)
IS
Bloco;

MODOS DE PARÂMETRO

Podemos transferir valores para o ambiente de chamada ou a partir dele através


de parâmetros. Selecione um dos três modos para cada parâmetro: IN, OUT, IN OUT:

Quadro 11 -Modos de Parâmetro

TIPO DESCRIÇÃO
Especifica um valor constante do ambiente de chamada
IN para o procedimento.
Especifica um valor de procedimento para o ambiente de
OUT chamada.
Especifica um valor de ambiente de chamada para o
procedimento e um valor possivelmente diferente do
IN OUT procedimento de volta para o ambiente de chamada
usando o mesmo parâmetro.
PARÂMETRO IN
É o parâmetro DEFAULT.
Seu valor é especificado para um subprograma e este parâmetro age como uma
constante e pode ser variável inicializada, constante, expressão ou literal.
Exemplo: Criar um procedimento que atualize o salário em 10% do funcionário
informado (owner: HR):
CREATE OR REPLACE PROCEDURE aumento
(v_id IN employees.employee_id%TYPE) IS
BEGIN
UPDATE employees
SET salary := salary * 1.10
WHERE employee_id = v_id;
COMMIT;
END;

16 Também chamado de argumento

106
L A B O R A T O R I O D E B A N C O D E D A D O S

EXECUÇÃO DA PROCEDURE

Para executar o procedimento utilizamos o comando EXECUTE:


EXECUTE aumento(100);

Para executar o procedimento também podemos usar o comando CALL:


CALL update_product_price(1,1.517);

SHOW ERRORS
Obs.: podemos utilizar o comando SHOW ERRORS para consultar os erros
de compilação no ambiente SQL * PLUS. Exemplo (owner: LOJA):
CREATE PROCEDURE update_product_price(
p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER)
AS
v_product_count INTEGER;
BEGIN
-- conta o número de produtos com o valor de product_id fornecido
-- sera 1 se o produto existir
SELECT COUNT(*)
INTO v_product_count
FROM products
WHERE product_id = p_product_id;
-- se o produto existir (v_product_count = 1) então
-- atualiza seu preço
IF v_product_count = 1 THEN
UPDATE products
SET price = price * p_factor
WHERE product_id = p_product_id;
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product_price;

17 Na versão 11G podemos passar parâmetros da seguinte maneira: CALL


update_product_price(p_fator => 1.3, p_produto=>2);

107
L A B O R A T O R I O D E B A N C O D E D A D O S

PARÂMETRO OUT

Deve ser especificado e retorna ao ambiente de chamada.


Deve ser sempre uma variável e não ser inicializada.
Exemplo: Exibe as informações do funcionário informado:
CREATE OR REPLACE PROCEDURE dado_func
(v_id IN employees.employee_id%TYPE,
v_nome OUT employees.first_name%TYPE,
v_salario OUT employees.salary%TYPE)
IS
BEGIN
SELECT first_name, salary
INTO v_nome, v_salario
FROM employees
WHERE employee_id = v_id;
END;

Criar variáveis de ambiente:


VARIABLE g_nome VARCHAR2(200
VARIABLE g_salario NUMBER

Executar o procedimento:
EXECUTE dado_func(7369, :g_nome, :g_salario)

Visualizar o conteúdo:
PRINT g_nome

PARÂMETRO IN OUT

Deve ser especificado para o subprograma e retornado para o ambiente de


chamada. Deve ser uma variável inicializada.
Exemplo: Criar um procedimento que aceita uma string de caracteres contendo
10 dígitos e retorna o número de telefone formatado:
CREATE OR REPLACE PROCEDURE formato_telefone
(v_telefone IN OUT VARCHAR2) IS
BEGIN
v_telefone := ‘(‘ || SUBSTR(v_telefone,1,3) ||
‘(‘ || SUBSTR(v_telefone,4,3) ||
‘-’ || SUBSTR(v_telefone,7);
END;

VARIABLE g_telefone VARCHAR2(15)


BEGIN
:g_telefone := ‘8007533589’;
END;
EXECUTE formato_telefone(:g_telefone)

PRINT g_telefone

108
L A B O R A T O R I O D E B A N C O D E D A D O S

PARÂMETRO DEFAULT

Exemplo:
CREATE OR REPLACE PROCECURE adiciona_depto
(v_nome IN departments.department_name%TYPE DEFAULT ‘CPD’,
v_loc IN departments.location_id DEFAULT 100) IS
BEGIN
INSERT INTO departments
(department_id, department_name, location_id)
VALUES (seq_dept.NEXTVAL, v_nome, v_loc);
END;
/

ESPECIFICAR PARÂMETROS

Exemplo:
BEGIN
adiciona_depto(‘CPD’, 150);
adiciona_depto(v_nome => ‘DP’, v_loc => 200);
adiciona_depto(120);
END;

DECLARANDO SUBPROGRAMAS

É possível declarar os subprogramas em qualquer bloco. Na seção DECLARE deve


ser o último item. Exemplo:
CREATE OR REPLACE PROCEDURE insere_empregado
(v_id IN employees.employee_id%TYPE) IS
PROCEDURE log
IS
BEGIN
INSERT INTO tabela_log18 (user_id, data, obs)
VALUES (user, sysdate, ‘Exclusão’);
END log;
BEGIN
DELETE FROM employees
WHERE employee_id = v_id;
log; --chamada do procedimento
END;

Esta tabela deverá ser criada contendo as colunas usuário VARCHAR(20), data DATE e obs
18

VARCHAR(50)

109
L A B O R A T O R I O D E B A N C O D E D A D O S

Exemplo: Exibir os dados dos empregados:


CREATE OR REPLACE PROCEDURE exibe_empregados IS
CURSOR emp_cursor IS
SELECT first_name
FROM employees;
BEGIN
FOR emp_rec IN emp_cursor
LOOP
exibe_empregados(emp_rec.first_name);
END LOOP;
COMMIT;
END;

REMOVENDO PROCEDIMENTOS

Podemos remover um procedimento armazenado no servidor utilizando: DROP


PROCEDURE nome_procedimento. Exemplo: DROP PROCEDURE exibe_empregados;
INFORMAÇÕES SOBRE PROCEDURES

Para obter informações sobre procedures utilizamos a view


USER_PROCEDURES19, que possui as seguintes colunas:
COLUNA DESCRIÇÃO
OBJECT_NAME Nome do objeto pode ser um nome de procedure, função ou
pacote.
PROCEDURE_NAME Nome da procedure.
AGGREGATE Se a procedure é uma função agregada – sim ou não.
IMPLTYPEOWNER Proprietário do tipo (se houver).
IMPLTYPENAME Nome do tipo (se houver).
PARALLEL Se a procedure é ativada para consultas paralelas – sim/não.

INFORMAÇÕES SOBRE FUNÇÕES AS FUNCTONS CRIADAS NESTE


USUARIO

SELECT object_name FROM user_objects WHERE object_type=’FUNCTION’;

CÓDIGO DA FUNCAO CRIADA NESTE USUARIO

SELECT text FROM user_source WHERE name=’NOME_DA_FUNCAO’;

19Podemos ter informações de todas as procedures mudando de USER para


ALL_PROCEDURES.

110
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS

1. Criar a procedure PRC_EMP que entre com o id de um empregado, exiba o


nome do empregado, o nome do departamento e a cidade em que ele
trabalha.

2. Criar uma procedure PRC_DEPT que entre com o id do departamento e exiba


o nome do empregado e o titulo do cargo. Caso o id não exista, exibir a frase:
DEPARTAMENTO INEXISTENTE.

3. Criar a tabela FOLHA com a estrutura abaixo:


CREATE TABLE folha
(employee_id INTEGER,
data DATE,
salario NUMBER(8,2),
vale_transporte NUMBER(8,2),
salliq NUMBER(8,2),
CONSTRAINT folha_pk PRIMARY KEY (employee_id, data),
CONSTRAINT folha_fk FOREIGN KEY (employee_id)
REFERENCES employees (employee_id));

4. Criar a procedure PRC_FOLHA que entre com a data e insira na tabela FOLHA
o id do empregado, o salario, o vale transporte calculado (6%) sobre o salário
e o salário líquido (salário – vale transporte).

5. Crie um procedimento chamado CONSULTA_EMPREGADO que consulta na


tabela EMPLOYEES, recuperando o salário e o cargo de um funcionário quando
fornecido o número de matrícula:
a. Crie um procedimento que retorne um valor das colunas SALARY e
JOB_TITLE (tabela JOBS) para um determinado funcionário (coluna
EMPLOYEE_ID); Obs: utilize variáveis de host para os parâmetros OUT.
b. Chame o procedimento e exiba o salário e o cargo do funcionário de número
102.
c. Chame novamente especificando o id 9898, o que acontece?

6. Criar um procedimento chamado EXIBE_CARGO que de acordo com o id de um


cargo informado, exiba o nome dos funcionários, o salario e o nome do
departamento que possuem este cargo.

7. Consultar no dicionário de dados as procedures existentes.

8. Exibir o código da procedure EXIBE_CARGO.

9. Executar a procedure colocando como parâmetro de entrada o id do cargo


ST_CLERK.

111
L A B O R A T O R I O D E B A N C O D E D A D O S

FUNCTIONS

Função é um bloco PL/SQL nomeado que pode obter parâmetros e ser chamado.
Em resumo, um procedimento é usado para calcular um valor. Funções e
procedimentos são estruturados da mesma forma, com a diferença que uma função
deve retornar um valor ao ambiente de chamada. Como um procedimento, uma
função também possui cabeçalho, parte declarativa, parte executável e uma parte
para tratamento de exceções opcional. Uma função deve ter uma cláusula RETURN no
cabeçalho e pelo menos uma instrução RETURN na seção executável. As funções
promovem a reutilização e a manutenção. Uma vez validadas, podem ser usadas em
qualquer número de aplicações. Se a definição for alterada, somente a função será
afetada, o que simplifica bastante a manutenção.
As funções podem ser chamadas como parte de uma expressão SQL ou parte de
uma expressão PL/SQL. Em expressão SQL, uma função deve obedecer a
determinadas regras para controlar os efeitos colaterais. Em uma expressão PL/SQL,
o identificador da função age como uma variável cujo valor depende dos parâmetros
especificados para ela. Sintaxe:
CREATE [OR REPLACE] FUNCTION nome_função
(parametro1 [modo1] tipodedados1,
(parametro2 [modo2] tipodedados2...)
RETURN tipodedados
IS
Bloco PL/SQL;

Exemplo: Calcular a área do círculo:


CREATE FUNCTION area_circulo
(p_raio IN NUMBER)
RETURN NUMBER
AS
v_pi NUMBER:= 3.1415926;
v_area NUMBER;
BEGIN
-- area do circulo é pi multiplicado pelo raio do quadrado
v_area := v_pi * POWER(p_raio, 2);
RETURN v_area;
END;

Uma função é um bloco PL/SQL que retorna um valor. Crie novas funções com a
instrução CREATE FUNCTION, que podem declarar uma lista de parâmetros, devem
retornar um valor e definir as ações a serem executadas pelo bloco PL/SQL padrão.
Utilize SHOW ERRORS para consultar os erros de compilação.

PARAMETRO DESCRIÇÃO
REPLACE Caso a função exista, ela será substituída pela nova versão
RETURN Não deve incluir um tamanho no seu tipo de dados.

112
L A B O R A T O R I O D E B A N C O D E D A D O S

Exemplo: Criar uma função chamada get_sal:

CREATE OR REPLACE FUNCTION get_sal


(v_id IN employees.employee_id%TYPE)
RETURN NUMBER
IS
v_salario employees.salary%TYPE := 0;
BEGIN
SELECT salary
INTO v_salario
FROM employees
WHERE employee_id = v_id;
RETURN (v_salario);
END;
Para executar no SQL * PLUS:

SELECT get_sal(130) FROM DUAL;

Exemplo: Criar uma função que retorne o imposto de um valor:

CREATE OR REPLACE FUNCTION taxa


(v_valor IN NUMBER)
RETURN NUMBER
IS
BEGIN
RETURN (v_valor *.08;
END;
/

Utilizando a função criada:


SELECT employee_id, salary, taxa(salary)
FROM employees;

Mais um exemplo: (owner loja)


CREATE FUNCTION average_product_price
( p_product_type_id IN INTEGER)
RETURN NUMBER
AS
v_average_product_price NUMBER;
BEGIN
SELECT AVG(price)
INTO v_average_product_price
FROM products
WHERE product_type_id = p_product_type_id;
RETURN v_average_product_price;
END average_product_price;

113
L A B O R A T O R I O D E B A N C O D E D A D O S

LOCAIS PARA CHAMAR FUNÇÕES DEFINIDAS


• Lista de seleção de um comando SELECT.
• Condição das cláusulas WHERE e HAVING.
• Cláusulas CONNECT BY, START WITH, ORDER BY e GROUP BY.
• Cláusulas VALUES do comando INSERT.
• Cláusula SET do comando UPDATE.

CHAMANDO FUNÇÕES A PARTIR DE EXPRESSÕES


Para poder ser chamada de expressão SQL, uma função é definida pelo usuário
para preencher determinados requisitos:

• Somente funções armazenadas podem ser chamadas de instruções SQL.


Procedimentos armazenados não podem ser chamados;

• Os parâmetros para uma função PL/SQL chamada a partir de uma instrução SQL
devem usar notação posicional. A notação nomeada não é suportada;

• Funções PL/SQL armazenadas não podem ser chamadas de cláusula de restrição


CHECK de um comando CREATE ou ALTER TABLE ou ser usadas para especificar
um valor default para uma consulta;

• Podemos possuir o privilégio EXECUTE da função para chamá-la de uma


instrução SQL.

REMOVENDO FUNÇÕES

Quando uma função não é mais utilizada podemos removê-la do servidor através
do comando: DROP FUNCTION nome_função.
Exemplo: DROP FUNCTION reajuste_salario.

INFORMAÇÕES SOBRE FUNÇÕES AS FUNCTONS CRIADAS NESTE


USUARIO

SELECT object_name FROM user_objects WHERE object_type=’FUNCTION’;

CÓDIGO DA FUNCAO CRIADA NESTE USUARIO

SELECT text FROM user_source WHERE name=’NOME_DA_FUNCAO’;

114
L A B O R A T O R I O D E B A N C O D E D A D O S

PROCEDIMENTO OU FUNÇÃO
Um procedimento é criado para armazenar uma série de ações para execução
futura. Um procedimento pode conter zero ou mais parâmetros que podem ser
transferidos do ambiente de chamada e para ele, mas não tem que retornar um valor.
Crie uma função quando quiser calcular um valor, que pode ser retornado ao
ambiente de chamada. Ela pode conter zero ou mais argumentos que são transferidos
para o ambiente que a chamou e deve sempre retornar um único valor.
Possui os seguintes benefícios:
• Desempenho melhorado;
• Manutenção melhorada;
• Segurança de dados e integridade melhorada.

Quadro 12 - Diferença entre Procedure e Function

PROCEDURE FUNCTION
Executa como instrução PL/SQL. Chamar como parte de uma expressão.
Tipo de dados sem RETURN Deve possuir um tipo de dados RETURN.
Pode retornar nenhum ou muitos Deve retornar um único valor.
valores.

Procedure Function
Parâmetro IN Parâmetro IN
Parâmetro OUT
Parâmetro IN OUT Is
Ambiente
de
Begin
Is Exception
Chamada
Begin End;
Exception
End;

Figura 28 - Diferença entre Procedure e Function (feito pelo Autor)

EXEMPLO DE FUNÇÃO
CREATE OR REPLACE FUNCTION soma_numeros(telefone IN VARCHAR2)
RETURN NUMBER IS
s NUMBER(4) := 0;
soma NUMBER(4):= 0;
BEGIN
FOR x IN 1..15 LOOP
IF Substr(telefone, x, 1) IN ('0', '1', '2', '3','4', '5','6', '7','8', '9')
THEN s := To_Number(Substr(telefone, x, 1));
soma := soma + s;
END IF;
END LOOP;
RETURN soma;
END soma_numeros;

115
L A B O R A T O R I O D E B A N C O D E D A D O S

EXERCÍCIOS PRÁTICOS
1. Criar uma função chamada FUNCAO_CARGO que retorna o título do cargo
informado.

2. Criar uma função chamada PRIMO que recebe um número inteiro e retorna a
informação se este número é primo ou não. Obs. Números primos são diviseis
somente por eles mesmos e por um.

3. Criar uma função chamada ANUAL_COMP para retornar o salário anual quando
especificado um salário mensal e comissão de um empregado. Obs. A função
deve tratar valores nulos.

4. Criar uma função chamada FNC_PIS que calcule o valor de pis a receber:
Para calcular PIS o trabalhador deve informar a remuneração mensal e a
quantidade de meses trabalhados, é importante salientar que para ter direito
o trabalhador deve ter recebido em média até 2 salários mínimos de
remuneração mensal no ano-base considerado. Por exemplo: Para calcular PIS
2019 o ano-base é 2018, portanto o valor do salário mínimo para efeito do
cálculo é de R$ 954,00, portanto o trabalhador deve ter recebido até R$
1.908,00, equivalente a 2 salários mínimos. Para calcular PIS é multiplicada a
remuneração mensal pela quantidade de meses trabalhados, depois dividido
pelos meses trabalhados, a remuneração média deve ser inferior a 2 salários
mínimos, sendo assim o trabalhador terá direito ao abono salarial do PIS.

5. Criar uma função chamada FNC_INSS que de acordo com um salário informado
retorna o valor a ser descontado do INSS:

Obs. O valor de contribuição acima de R$ 5.645,80 é de R$ 570,82.


6. Executar a função acima passando como parâmetro da coluna SALAY da tabela
EMPLOYEES.

7. Consultar o código da function criada.

8. Criar uma função chamada FNC_EXIBE_COMISSAO que de acordo com o salario


e o percentual de comissão informado, exiba o valor de receber de comissão
(salary * percentual).

116
L A B O R A T O R I O D E B A N C O D E D A D O S

9. Alterar a tabela FOLHA as colunas comissão e inss:


ALTER TABLE folha ADD comissao NUMBER(10,2);

ALTER TABLE folha ADD inss NUMBER(10,2);

10. Alterar a procedure PRC_FOLHA para que chame as functions FNC_INSS e


FNC_EXIBE_COMISSAO para que seja recalculado a folha de pagamento
acrescentando ao salário líquido o valor de comissao e subtraia o valor do
INSS.

117
L A B O R A T O R I O D E B A N C O D E D A D O S

PACKAGES

Agrupar tipos, itens e subprogramas PL/SQL relacionados em um container,


ou seja, encapsula funcionalidades relacionadas em uma unidade independente.
Por exemplo, um pacote de RH (Recursos Humanos) pode conter procedimentos
de admissão e demissão. Bem como funções de bônus e variação de impostos.
Vantagens:
• Modularidade (encapsulamento);
• Projeto de aplicações mais simples;
• Informações ocultas;
• Funcionalidade ampliada;
• Desempenho melhorado;
• Sobrecarregando (vários subprogramas com o mesmo nome).
O pacote possui uma especificação e um corpo de pacote armazenado
separadamente no banco de dados. Onde:
• ESPECIFICAÇÃO: interface de suas aplicações. Declara tipos, variáveis,
constantes, exceções, cursores e subprogramas disponíveis para uso. Ela
deve ser definida antes do corpo do pacote.
• CORPO: define completamente os cursores e subprogramas
implementando a especificação.

Uma especificação existe sem um corpo, mas um corpo não vive sem uma
especificação. Se tiver incorporado um procedimento independente a um pacote,
deverá eliminá-lo.

Figura 29– Estrutura do Comando PACKAGE (feito pelo Autor)

O pacote em si não pode ser chamado, aninhado ou receber parâmetros. Seu


formato é semelhante à de um subprograma e uma vez escrito e compilado pode
ser utilizado por várias aplicações. A primeira vez que é chamado, o pacote inteiro
é carregado na memória. Assim, nas próximas chamadas não requerem I/O.

118
L A B O R A T O R I O D E B A N C O D E D A D O S

CRIANDO O PACOTE

ESPECIFICAÇÃO
Sintaxe:
CREATE [OR REPLACE] PACKAGE nome_pacote IS
Tipo de dados especificação de um subprograma
END nome_pacote;

Exemplo:
CREATE OR REPLACE PACKAGE comissao_pacote IS
PROCEDURE calcula_comissao (v_percentual IN NUMBER);
END comissao_pk;

CORPO

Sintaxe:
CREATE [OR REPLACE] PACKAGE BODY nome_pacote IS
Tipo de dados especificação de um subprograma e corpo.
END nome_pacote;

Exemplo:
CREATE OR REPLACE PACKAGE BODY comissao_pacote IS
FUNCTION valida_comissao
(v_percentual IN NUMBER)
RETURN BOOLEAN
IS
v_maior_comissao NUMBER;
BEGIN
SELECT MAX(commission_pct)
INTO v_maior_comissao
FROM employees;
IF v_percentual > v_maior_comissao THEN
RETURN(FALSE);
ELSE
RETURN(TRUE).
END IF;
END valida_comissao;
PROCEDURE calcula_comissao(v_percentual IN NUMBER)
IS
p_comissao NUMBER:= 0.10;

119
L A B O R A T O R I O D E B A N C O D E D A D O S

BEGIN
IF valida_comissao(v_percentual) THEN
P_comissao := v_percentual;
ELSE
RAISE_APPLICATION_ERROR(-20210, ‘ Comissão Inválida’);
END IF;
END calcula_comissao;
END comissao_pacote;

Exemplo (owner: loja):


CREATE PACKAGE product_package
AS
TYPE t_ref_cursor IS REF CURSOR;
FUNCTION get_products_ref_cursor RETURN t_ref_cursor;
PROCEDURE update_product_price
(p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER);
END product_package;
/

CREATE PACKAGE BODY product_package


AS
FUNCTION get_products_ref_cursor
RETURN t_ref_cursor IS
v_products_ref_cursor t_ref_cursor;
BEGIN
-- obtém o REF CURSOR20
OPEN v_products_ref_cursor FOR
SELECT product_id, name, price
FROM products;
-- retorna o REF CURSOR
RETURN v_products_ref_cursor;
END get_products_ref_cursor;
PROCEDURE update_product_price
( p_product_id IN products.product_id%TYPE,
p_factor IN NUMBER)
AS

20 Semelhante a um ponteiro na linguagem de programação C++ e aponta para um cursor.

120
L A B O R A T O R I O D E B A N C O D E D A D O S

v_product_count INTEGER;
BEGIN
-- conta o número de produtos com o valor de
-- product_id fornecido (sera 1 se o produto existir)
SELECT COUNT(*)
INTO v_product_count
FROM products
WHERE product_id = p_product_id;
-- se o produto existir (v_product_count = 1) então
-- atualiza o produto
IF v_product_count = 1 THEN
UPDATE products
SET price = price * p_factor
WHERE product_id = p_product_id;
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product_price;
END product_package;
/

EXECUTANDO UM PROCEDIMENTO DO PACOTE

Como este procedimento é público, podemos chamá-lo da seguinte


maneira:EXECUTE nome_pacote.nome_procedimento(parâmetros). Exemplo:
EXECUTE comissao_pacote.calcula_comissao(0.15);
SELECT product_package.get_products_ref_cursor FROM dual;
CALL product_package.update_product_price(3, 1.25);

REMOVENDO PACOTES
• ESPECIFICAÇÃO: DROP PACKAGE nome_pacote;
• CORPO: DROP PACKAGE BODY nome_pacote;

INFORMAÇÕES DE FUNÇÕES E PROCEDURES EM PACOTES


SELECT object_name, procedure_name FROM user_procedures;

121
L A B O R A T O R I O D E B A N C O D E D A D O S

PACOTES FORNECIDOS PELO SERVIDOR ORACLE

Já conhecemos o pacote DBMS_OUTPUT.PUT_LINE que exibe uma


mensagem. Dentre vários pacotes, vamos dar uma ênfase ao DBMS_JOB.
Este pacote, permite programar tarefas, executar procedimentos e alterar
jobs que foram programados anteriormente. Podemos usar a view do
dicionário de dados, USER_JOBS para visualizar os jobs programados.
• SUBMETER JOB À FILA: DBMS_JOB.SUBMIT(id_job, o_que, data). nde:
id_job → parâmetro OUT que irá conter o número alocado para o job.
O_que → instrução a ser executada.
Data → data de execução, por padrão SYSDATE.
• Forçar um job na fila a ser executado agora, se fornecer o número do job:
DBMS_JOB.RUN(id_job)
Exemplo: VARIABLE id_job NUMBER
EXECUTE DBMS_JOB.SUBMIT(:id_job, ‘ OVER_PACK.ADD_DEPT(‘
‘EDUCATION ‘ ‘, ‘ ‘ZURICH ‘ ‘);’, SYSDATE)
COMMIT;
PRINT id_job
EXERCÍCIOS PRÁTICOS
Obs.: Executar o script PRODUCT.SQL
01. Crie uma especificação e um corpo do pacote chamado PRODUTO_PACOTE
que possua os procedimentos: ADICIONA PRODUTO, ATUALIZADA_PRODUTO
e APAGA_PRODUTO e a função QUANTIDADE_PRODUTO.
02. Crie um pacote chamado CHECAR_PACOTE que contenha os procedimentos
CHECAR_ADMISSAO e CHECAR_DEPARTAMENTO:
• CHECAR_ADMISSAO: Deve verificar se a data de admissão de um funcionário
está dentro do seguinte intervalo: sysdate – 50 anos, sysdate + 50 anos. Se a
data for inválida, devemos criar um erro de aplicação com uma mensagem
apropriada indicando por que o valor de data não é aceitável. Um valor nulo na
data de admissão deve ser tratado como data inválida. Use uma constante para
referenciar o limite de 50 anos;
• CHECAR_DEPARTAMENTO: verifica a combinação de departamento e gerente
para um funcionário determinado. Aceita um número de funcionário e um
número de gerente. O procedimento verifica se o gerente e o funcionário
trabalham no mesmo departamento. O procedimento também verifica se o
cargo do número do gerente fornecido é AC_MGR ou FI_MGR.

03. Com base nas procedures e functions criadas nas tarefas 08 e 09, criar uma
package chamada PK_TAREFA11 contendo na especificação o cabeçalho das
procedures e no corpo contendo o código das procedures e das functions.

122
L A B O R A T O R I O D E B A N C O D E D A D O S

TRIGGERS

Figura 30 – Esquema de Disparo de uma TRIGGER (extraído da WEB)

Os gatilhos (triggers) são executados implicitamente quando uma instrução


de acionamento DML (INSERT, UPDATE ou DELETE) é emitida junto da tabela
associada, independente do usuário, conectado ou da aplicação usada. Os gatilhos
de banco de dados também são executados implicitamente quando ocorrem
algumas ações de usuários ou de sistema de banco de dados, como por exemplo,
quando um usuário estabelece logon ou DBA desativa o banco de dados. Os
gatilhos de aplicação são executados implicitamente sempre que ocorre um
determinado evento em uma aplicação. Estes gatilhos podem ser definidos em
tabelas e visões.
São úteis para fazer a auditoria avençada das alterações feitas em valores de
coluna. Vamos utilizar para este assunto o usuário loja e a tabela
product_price_audit.
COMPONENTES
Quadro 13- Componentes da Trigger

COMPONENTE DESCRIÇÃO VALORES


Quando o gatilho dispara em relação BEFORE
Tempo de gatilho ao evento de acionamento AFTER
INSTEAD OF
Que operações de manipulação de INSERT
Evento de dados na tabela ou view disparam o UPDATE21
Acionamento gatilho DELETE
Quantas vezes é executado o corpo Instrução
Tipo de Gatilho do gatilho. Linha
Corpo do Gatilho Que ação o gatilho executa Completa o bloco
PL/SQL

21 Podemos informar qual a coluna terá o evento. Exemplo: UPDATE OF salary

123
L A B O R A T O R I O D E B A N C O D E D A D O S

TEMPO DE GATILHO

• BEFORE → executa o corpo do gatilho antes do evento DML de acionamento


em uma tabela;
• AFTER → executa o corpo do gatilho após um evento DML de acionamento de
uma tabela;
• INSTEAD OF → executa o corpo do gatilho no lugar da instrução de
acionamento. Utilizado para views que não são modificáveis de outra forma.

TIPOS DE GATILHO

• INSTRUÇÃO → (padrão) o corpo do gatilho é executado uma vez para cada


evento de acionamento;
• LINHA → o corpo do gatilho é executado uma vez para cada linha afetada pelo
evento de acionamento.

Sintaxe:
CREATE [OR REPLACE] TRIGGER nome_gatilho
Tempo
evento1 OR evento2
ON nome_tabela
Corpo do Gatilho;

Onde:
• Tempo – indica o tempo de disparo (BEFORE ou AFTER);
• Evento – indica a operação DML (INSERT, UPDATE, DELETE)

Exemplo: Criar uma trigger para restringir a inserção na tabela EMP a


determinado horário comercial de segunda à sexta-feira. Se o usuário tentar inserir
na tabela EMP no sábado, receberá uma mensagem de alerta e o procedimento
será descartado:
CREATE OR REPLACE TRIGGER segurança_emp
BEFORE INSERT ON emp
BEGIN
IF (TO_CHAR(sysdate, ‘DY’) IN (‘SAT’, ‘SUN’)) OR
(TO_CHAR(sysdate, ‘HH24’) NOT BETWEEN ‘08’ AND ‘18’)
THEN RAISE_APPLICATION_ERROR
(-20500, ‘Somente poderá inserir em horário comercial.’);
END IF;
END;

124
L A B O R A T O R I O D E B A N C O D E D A D O S

CRIANDO UMA TRIGGER DE LINHA

Sintaxe: CREATE [OR REPLACE] TRIGGER nome_trigger


tempo
evento1 [OR evento2 OR evento3]
ON nome_tabela
[REFERECING OLD AS antigo | NEW AS novo
FOR EACH ROW
[WHEN condição]
corpo do gatilho;
Onde:
• REFERECING – especifica os nomes da correlação para os valores antigos
e novos da linha atual (padrão OLD e NEW);
• FOR EACH ROW – informa que será uma trigger de linha;
• WHEN – restrição de gatilho (predicado condicional válido para cada linha
até o final do corpo da trigger).

Exemplo: Criar uma trigger que permita que somente determinados


funcionários possam receber salários acima de 5000.
CREATE OR REPLACE TRIGGER restricao_sal
BEFORE INSERT OR UPDATE OF salary ON employees
FOR EACH ROW
BEGIN
IF NOT (:NEW.JOB_ID IN (‘AC_MGR’, ‘FI_MGR’))
AND :NEW.SALARY > 5000
THEN RAISE_APPLICATION_ERROR
(-20202, ‘Empregado não pode receber este salário. ‘);
END IF;
END;

Exemplo: Reduzir o preço em 25%


CREATE TRIGGER before_product_price_update
BEFORE UPDATE OF price
ON products
FOR EACH ROW WHEN (new.price < old.price * 0.75)
BEGIN
dbms_output.put_line(‘product_id = ‘ || :old.product_id);
dbms_output.put_line(‘Old price = ‘ || :old.price);
dbms_output.put_line(‘New price = ‘ || :new.price);
dbms_output.put_line(‘The price reduction is more than 25%’);
-- insert linha na tabela product_price_audit

125
L A B O R A T O R I O D E B A N C O D E D A D O S

INSERT INTO product_price_audit


(product_id, old_price, new_price)
VALUES (:old.product_id, :old.price, :new.price);
END before_product_price_update;

QUALIFICADORES: OLD(ANTIGO) E NEW(NOVO)

Exemplo: Criar uma trigger na tabela EMP para adicionar linhas a uma tabela
do usuário, AUDIT_EMP, fazendo log das atividades com a tabela EMPLOYEES:
Primeiro, vamos criar a tabela AUDIT_EMP_TABLE:
CREATE TABLE audit_EMP_TABLE
(user_name VARCHAR2(30),
timestamp DATE,
id NUMBER,
old_last_name VARCHAR2 (30),
new_last_name VARCHAR2(30),
old_title VARCHAR2(30),
new_title VARCHAR2(30),
old_salary NUMBER(14,2),
new_salary NUMBER(14,2));

Segundo vamos criar a trigger:


CREATE OR REPLACE TRIGGER audit_emp
AFTER DELETE OR INSERT OR UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO audit_emp_table
(user_name, timestamp, id, old_last_name,
new_last_name, old_title, new_title, old_salary, new_salary)
VALUES (USER, SYSDATE, :OLD.employee_id, :OLD.first_name,
:NEW.first_name,:OLD.job_id, :NEW.job_id, :OLD.salary,
:NEW.salary);
END;

Terceiro teste a trigger, criando um comando de INSERT, UPDATE ou DELETE


na tabela EMPLOYEES.

O gatilho registra os valores de diversas colunas antes e depois das alterações


dos dados. Usando os qualificadores OLD e NEW (somente na trigger de linha)
junto com a coluna da tabela, precedidos por dois pontos (:).

126
L A B O R A T O R I O D E B A N C O D E D A D O S

RESULTADO DO QUALIFICADOR: ANTES E DEPOIS


INSERT – antes: NULO e depois: VALOR INSERIDO;

UPDATE - antes: VALOR ANTIGO e depois: NOVO VALOR;

DELETE- antes: VALOR ANTIGO e depois: NULO.

RESTRIÇÃO NA TRIGGER DE LINHA


Somente que satisfaça uma determinada condição, usamos a cláusula WHEN
Obs.: Na cláusula WHEN o OLD ou NEW não necessita dos dois pontos(:).
Exemplo: Crie uma trigger na tabela EMP para calcular a comissão de um
funcionário quando uma linha for adicionada na tabela EMP ou o salário for
alterado:
CREATE OR REPLACE TRIGGER verifica_salario
BEFORE INSERT OR UPDATE OF sal ON employees
FOR EACH ROW
WHEN (NEW.JOB_ID = ‘SA_MAN’) --vendedor
BEGIN
IF INSERTING
THEN :NEW.commission_pct := 0;
ELSIF :OLD.commission_pct IS NULL
THEN :NEW.commission_pct := 0;
ELSE
:NEW.commission_pct := :OLD.commission_pct *
(:NEW.salary/:OLD.salary);
END IF;
END;

TRIGGER INSTEAD OF
São assim chamados por ser usado para modificar dados nos quais a
instrução DML foi emitida em uma view não-atualizada automaticamente. A trigger
é disparada ao invés de executar a instrução DML.
VANTAGEM: Quando a view é formada por mais de uma tabela.
Sintaxe:
CREATE [OR REPLACE] TRIGGER nome_trigger
INSTEAD OF
Evento1 [OR evento2 OR evento3]
ON nome_tabela
[REFERECING OLD AS antigo | NEW AS novo]
[FOR EACH ROW]
corpo_trigger;

127
L A B O R A T O R I O D E B A N C O D E D A D O S

ALTERANDO TRIGGERS
• ATIVAR/REATIVAR:
ALTER TRIGGER nome_trigger DISABLE / ENABLE

• ATIVAR/REATIVAR TRIGGERS DA TABELA:


ALTER TABLE nome_tabela DISABLE / ENAME ALL TRIGGERS

• RECOMPILAR UMA TRIGGER


ALTER TRIGGER nome_trigger COMPILE;

APAGANDO TRIGGERS

Sintaxe: DROP TRIGGER nome_trigger;


Exemplo: DROP TRIGGER verifica_salario;

TRIGGER DE BANCO DE DADOS

As triggers podem ser definidas no nível de banco de dados ou esquema.


Exemplo: uma trigger para desativar um banco de dados.
Eventos que podem disparar a trigger:
• Uma instrução de definição de dados em um objeto de banco de dados
ou esquema;
• Um login ou logoff específico ou qualquer de usuário;
• Uma desativação ou inicialização de um banco de dados;
• Ocorre um erro qualquer específico.

CRIANDO TRIGGER NAS INSTRUÇÕES DDL
Sintaxe: CREATE [OR REPLACE] nome_gatilho
tempo
[evento1 OR evento2 OR...]
ON {banco_dados | esquema}
Corpo_gatilho

EVENTOS DDL
CREATE
ALTER
DROP
TRIGGER BODY – completa o bloco PL/SQL
Os gatilhos DDL só serão disparados se o objeto a ser criado for: function,
índice, package, procedure, sequence, sinonym, table, trigger, view ou user.

128
L A B O R A T O R I O D E B A N C O D E D A D O S

A seguir temos uma lista de eventos DDL que podem disparar uma trigger:

Quadro 14 - Eventos DDL que disparam Triggers

EVENTOS DE DDL DISPARA A TRIGGER QUANDO...


ALTER Qualquer objeto é alterado;
ANALYZE Qualquer objeto é analisado;
ASSOCIATE STATISTICS Estatísticas são associadas ao objeto;
AUDIT Auditoria é ligada;
COMMENT Comentário adicionado ao objeto;
CREATE Qualquer objeto criado;
DDL Qualquer um dos comandos desta tabela;
DISASSOCIATE STATISTICS Estatísticas são desassociadas de um objeto;
DROP Qualquer objeto é excluído;
GRANT Privilégio concedido;
NOAUDIT Auditoria desligada;
RENAME Objeto renomeado;
REVOKE Privilégio revogado;
TRUNCATE Tabela é truncada.
TRIGGER QUE ARMAZENA INFORMACOES DA DDL

Criar a tabela AUDITA_DDL:


CREATE TABLE audita_ddl
(evento VARCHAR(100),
username VARCHAR(100),
objeto VARCHAR(100),
objtype VARCHAR(100),
objowner VARCHAR(100),
sql VARCHAR(4000));

CRIAR A TRIGGER TG_AUDITA_DDL:


CREATE OR REPLACE TRIGGER tg_audita_ddl
AFTER DDL ON SCHEMA
DECLARE
SQL_TEXT ORA_NAME_LIST_T;
STMT VARCHAR(4000);
N NUMBER;
BEGIN
N := ORA_SQL_TXT(SQL_TEXT);
FOR i IN 1..n LOOP
STMT := STMT || SQL_TEXT(i);
END LOOP;
INSERT INTO audita_ddl VALUES
(ORA_SYSEVENT, ORA_LOGIN_USER,ORA_DICT_OBJ_NAME,
ORA_DICT_OBJ_TYPE,ORA_DICT_OBJ_OWNER,STMT); END;

129
L A B O R A T O R I O D E B A N C O D E D A D O S

TRIGGER QUE ARMAZENA LOG

• SYS_CONTENT: captura as informações de nome de usuário do banco de dados,


usuário do sistema operacional e a estação de trabalho. Esta função retorna o
valor de um parâmetro associado a um namespace (USERENV retorna
informações sobre a sessão corrente. Muito útil para auditoria).

• PRAGMA AUTONOMOUS_TRANSACTION: altera a maneira com que os sub-


programas trabalham com transações, tornando-as independentes. Um
subprograma com este pragma permite executar operações SQL, COMMIT e
ROLLBACK. Com isto, evita-se o problema de TABELA MUTANTE22.

• ORA_SQL_TXT: função que armazena o texto do comando até 64 caracteres.


A trigger chamada TG_LOG a seguir captura informações, como o nome do
usuário do banco de dados, o nome do usuário do sistema operacional, a estação
de trabalho, o comando que foi executado e foi efetuado com SUCESSO ou com
FALHA. Em seguida, armazena na tabela de LOG, onde a chave primária possui
uma sequência que gera os números automaticamente chamada SEQ_LOG que
inicia em 1:
Criar a tabela LOG_DML:
CREATE TABLE LOG_DML
(seq NUMBER(35) PRIMARY KEY,
Data DATE,
Tabela VARCHAR2(20),
Usuario VARCHAR2(15),
UsuarioOS VARCHAR2(25),
Estacao VARCHAR2(35),
Acao VARCHAR2(6),
Status VARCHAR2(7));

CREATE SEQUENCE seq_log


START WITH 1
INCREMENT BY 1;

CREATE OR REPLACE TRIGGER tg_log


BEFORE INSERT OR UPDATE OR DELETE ON employees
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_usuario log_dml.usuario%TYPE;
v_os log_dml.usuarioos%TYPE;

22Mutante significa algo que está sendo modificado ou alterado. O erro de uma tabela mutante
é o ORA-04091 que ocorre quando uma trigger tenta verificar ou alterar uma tabela que está
sofrendo uma alteração.

130
L A B O R A T O R I O D E B A N C O D E D A D O S

v_host log_dml.estacao%TYPE;
BEGIN
SELECT SYS_CONTEXT(‘userenv’, ‘session_user’),
SYS_CONTEXT(‘userenv’, ‘os_user’),
SYS_CONTEXT(‘userenv’, ‘host’)
INTO v_usuario, v_os, v_host
FROM dual;
IF INSERTING THEN
INSERT INTO log_dml
VALUES (seq_log.NEXTVAL, sysdate, ‘EMPLOYEES’, v_usuario,
v_os, v_host, ‘INSERT’, ‘FALHA’);
END IF;
IF UPDATING THEN
INSERT INTO log_dml
VALUES (seq_log.NEXTVAL, sysdate, ‘EMPLOYEES’, v_usuario,
v_os, v_host, ‘UPDATE’, ‘FALHA’);
END IF;
IF DELETING THEN
INSERT INTO log_dml
VALUES (seq_log.NEXTVAL, sysdate, ‘EMPLOYEES’, v_usuario,
v_os, v_host, ‘DELETE’, ‘FALHA’);
END IF;
COMMIT;
END;
/

CREATE OR REPLACE TRIGGER tg_log1


AFTER INSERT OR UPDATE OR DELETE ON employees
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_usuario log_dml.usuario%TYPE;
v_os log_dml.usuarioos%TYPE;
v_host log_dml.estacao%TYPE;
v_seq NUMBER(35);
BEGIN
SELECT SYS_CONTEXT(‘userenv’, ‘session_user’),
SYS_CONTEXT(‘userenv’, ‘os_user’),
SYS_CONTEXT(‘userenv’, ‘host’)
INTO v_usuario, v_os, v_host
FROM dual;
SELECT MAX(seq) INTO v_seq FROM log_dml
WHERE tabela = ‘EMPLOYEES’
AND usuario = v_usuario
AND usuarioos = v_os
AND estacao = v_host;
UPDATE log_dml
SET status = ‘SUCESSO’
WHERE seq = v_seq;
COMMIT;
END;

131
L A B O R A T O R I O D E B A N C O D E D A D O S

Podemos ainda melhorar esta trigger para que seja utilizada em qualquer
tipo de objeto.
Para isto, altere o nome da coluna tabela para objeto:
ALTER TABLE log_dml
RENAME COLUMN tabela TO objeto;

Depois adicione mais duas colunas: TIPO_OBJETO e TEXTO_SQL:


ALTER TABLE log_dml
ADD (tipo_objeto VARCHAR2(20),
texto_sql VARCHAR2(2000));

A trigger a seguir possui um laço que captura todas as instruções SQL


presentes no comando e concatena-as:
CREATE OR REPLACE TRIGGER tg_ddl
AFTER DDL ON SCHEMA
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
SQL_TEXT ORA_NAME_LIST_T;
V_SQL VARCHAR2(2000);
N NUMBER;
BEGIN
N := ORA_SQL_TXT(SQL_TEXT);
FOR i IN 1..N LOOP
V_SQL := V_SQL || SQL_TEXT(I);
END LOOP;
INSERT INTO log_dml
VALUES (seq_log.NEXTVAL, SYSDATE, ORA_DICT_OBJ_NAME,
ORA_LOGIN_USER,SYS_CONTEXT(‘USERENV’, ‘OS_USER’),
SYS_CONTEXT(‘USERENV’, ‘HOST’), ORA_SYSEVENT,
‘SUCESSO’, ORA_DICT_OBJ_TYPE, V_SQL);
COMMIT;
END;

EXERCÍCIOS PRÁTICOS
Obs.: Executar o script PRODUCT.SQL

1. Somente serão permitidas alterações nos dados das tabelas durante o horário
comercial, das 7:30 as 12:30, de segunda à sexta-feira.
a) Crie um procedimento armazenado chamado SECURE_DML que não funcione
fora desse horário, devolvendo a mensagem: “Fora do horário comercial”.

132
L A B O R A T O R I O D E B A N C O D E D A D O S

UTL_FILE

O pacote UTL_FILE é um conjunto de componentes que tem como função permitir


o acesso ou geração de arquivos externos ao banco de dados. Um exemplo seria
importarmos scripts em SQL ou PL/SQL para o nosso sistema. O pacote é constituído
de 18 componentes, nos quais são distribuídos da seguinte maneira: 7 Exception, 2
Function, 8 Procedure e 1 Type.
Para utilizarmos o pacote, teremos que interromper os serviços do banco de
dados e modificar o arquivo INIT.ORA ( No Oracle 10G XE – chama-se initXE.ora),
onde iremos acrescentar o parâmetro UTL_FILE_DIR, a fim de determinar quais os
diretórios do sistema está livre para o acesso.
Primeiramente, vamos informar ao banco de dados que podemos gravar e
recuperar dados do sistema operacional, através dos seguintes passos:

Figura 31 – Passos do UTL_FILE (feito pelo Autor)

Agora vamos finalizar e inicializar novamente o banco de dados para assumir


os novos parâmetros:
SHUTDOWN
STARTUP
SHOW PARAMETER UTL_FILE_DIR

Ainda conectado com o usuário SYS (CONNECT / AS SYSDBA) dê privilégio


de EXECUTE no pacote UTL_FILE para o usuário LOJA:
GRANT EXECUTE ON UTL_FILE TO LOJA;

Podemos deixar para que todos os usuários tenham o privilégio:


GRANT EXECUTE ON UTL_FILE TO PUBLIC;
Podemos consultar todos os componentes do pacote: DESC UTL_FILE.

133
L A B O R A T O R I O D E B A N C O D E D A D O S

COMANDOS UTL_FILE

Quadro 15 - Procedimentos Package UTL_FILE

Procedimentos
da package Funcionalidade
UTL_FILE
abre um arquivo para entrada ou saída, criando um arquivo
FOPEN
de saída caso o arquivo especificado não exista
IS_OPEN indica se determinado arquivo está ou não aberto
FCLOSE fecha um arquivo
FCLOSE_ALL fecha todos os arquivos abertos
GET_LINE lê uma linha de um arquivo aberto
escreve uma linha no arquivo. Não acrescenta
PUT
automaticamente o caractere de fim de linha
escreve uma linha no arquivo, acrescentando
PUT_LINE
automaticamente o caractere de fim de linha
inclui o caractere de fim de linha no arquivo, o que irá gerar
NEW_LINE
uma nova linha em branco
FFLUSH escreve, fisicamente, todas as pendências para um arquivo

Quadro 16 – Comandos do Pacote UTL_FILE (feito pelo Autor)

Exceções package
Controle
UTL_FILE
INVALID_PATH diretório ou nome de arquivo inválido
INVALID_MODE o parâmetro de modo de abertura é inválido
INVALID_FILEHANDLE especificador de arquivo inválido
o arquivo não pode ser aberto ou a operação é
INVALID_OPERATION
inválida
ocorreu um erro do sistema operacional durante a
READ_ERROR
leitura de um arquivo
ocorreu um erro do sistema operacional durante a
WRITE_ERROR
gravação de um arquivo
INTERNAL_ERROR erro não especificado no PL/SQL

Exemplo: Roteiro para geração de arquivo texto:


DECLARE
arquivo_saida UTL_File.File_Type;
Cursor Cur_Linha is
--Definição do select que traz a linha completa concatenada a ser gravada
BEGIN
arquivo_saida := UTL_File.Fopen(‘caminho completo’,’nm arquivo’, ‘w’);

134
L A B O R A T O R I O D E B A N C O D E D A D O S

For Reg_Linha in Cur_linha Loop


UTL_File.Put_Line(arquivo_saida, Reg_linha.linha);
End Loop;
UTL_File.Fclose(arquivo_saida);
Dbms_Output.Put_Line(‘Arquivo gerado com sucesso.’);
EXCEPTION
WHEN UTL_FILE.INVALID_OPERATION THEN
Dbms_Output.Put_Line(‘Operação inválida no arquivo.’);
UTL_File.Fclose(arquivo_saida);
WHEN UTL_FILE.WRITE_ERROR THEN
Dbms_Output.Put_Line(‘Erro de gravação no arquivo.’);
UTL_File.Fclose(arquivo_saida);
WHEN UTL_FILE.INVALID_PATH THEN
Dbms_Output.Put_Line(‘Diretório inválido.’);
UTL_File.Fclose(arquivo_saida);
WHEN UTL_FILE.INVALID_MODE THEN
Dbms_Output.Put_Line(‘Modo de acesso inválido.’);
UTL_File.Fclose(arquivo_saida);
WHEN Others THEN
Dbms_Output.Put_Line(‘Problemas na geração do arquivo.’);
UTL_File.Fclose(arquivo_saida);
END;

Exemplo: Roteiro para leitura de arquivo texto:


DECLARE
arquivo_ler UTL_File.File_Type;
Linha Varchar2(100);
BEGIN
arquivo_ler := UTL_File.Fopen(‘caminho completo’,’nm arquivo’, ‘r’);
Loop
UTL_File.Get_Line(arquivo_ler, Linha);
-- Manipulação da linha lida
End Loop;
UTL_File.Fclose(arquivo_ler);
Dbms_Output.Put_Line(‘Arquivo processado com sucesso.’);
EXCEPTION
WHEN No_data_found THEN
UTL_File.Fclose(arquivo_ler);
Commit;
WHEN UTL_FILE.INVALID_PATH THEN
Dbms_Output.Put_Line(‘Diretório inválido.’);
UTL_File.Fclose(arquivo_ler);
WHEN Others THEN
Dbms_Output.Put_Line (‘Problemas na leitura do arquivo.’);
UTL_File.Fclose(arquivo_ler);
END;

135
L A B O R A T O R I O D E B A N C O D E D A D O S

EXEMPLO PRÁTICO DE UTL_FILE

PASSOS:
1. Conectar com o usuário SYSTEM: CONNECT SYSTEM/SENHA;
2. Criar diretório: CREATE DIRECTORY DIRETORIO AS ‘C:\DIRETORIO’;
3. Ir no Windows Explorer e criar uma pasta chamada DIRETÓRIO na unidade
C;
4. Conceder privilégio de leitura e gravação no diretório criado:
GRANT READ, WRITE ON DIRECTORY DIRETORIO TO HR;
5. Conectar com o usuário HR: CONNECT HR/HR;
6. Criar o procedimento abaixo:
DECLARE
V_LINHA VARCHAR2(2000) := ‘‘;
V_ARQUIVO UTL_FILE.FILE_TYPE;
BEGIN
V_ARQUIVO := UTL_FILE.FOPEN(‘DIRETORIO’, ‘ARQUIVO.TXT’, ‘W’);
FOR i in 1..5 LOOP
V_LINHA := ‘LINHA ‘ || i || ‘!!’;
UTL_FILE.PUT_LINE(V_ARQUIVO, V_LINHA);
END LOOP;
UTL_FILE.FCLOSE(V_ARQUIVO);
END;
7. Vá a unidade C:\DIRETÓRIO e visualize o conteúdo do arquivo.

136
L A B O R A T O R I O D E B A N C O D E D A D O S

XML COM PL/SQL

Vamos gravar nomes dos clientes em um arquivo XML. Para isto vamos
conectar como SYSTEM e conceder o privilégio de CREATE ANY DIRECTORY para
o usuário LOJA:

Figura 32 – Concessão de Privilégio para Diretório (feito pelo Autor)

Agora, conectar com o usuário loja (senha loja) e criar um objeto de diretório
c:\TEMP_FILES:

Figura 33 – Criação de um Objeto Diretório (feito pelo Autor)

Para exibir os diretórios existentes:


SELECT * FROM ALL_DIRECTORIES ;

Obs.: não esquecer de criar a pasta TEMP_FILES na unidade C:

137
L A B O R A T O R I O D E B A N C O D E D A D O S

Figura 34 – Diretório criado no Windows Explorer (feito pelo Autor)

É necessário dar privilégio de gravação no diretório para a conta de usuário


Oracle que usamos para instalar o software de banco de dados.
Os privilégios:
• READ – pode ler o conteúdo de um diretório do sistema operacional
utilizando uma definição DIRECTORY;
• WRITE – pode gravar informações em um diretório do sistema
operacional utilizando uma definição DIRECTORY do Oracle.

Figura 35 – Concessão de privilégio para o SYSDBA (feito pelo Autor)

Vamos criar a procedure a seguir que se chama write_xml_data_to_file() que


recupera o nome dos clientes e os grava num arquivo XML:
CREATE OR REPLACE PROCEDURE write_xml_data_to_file
( p_directory VARCHAR2,
p_file_name VARCHAR2) AS
v_file UTL_FILE.FILE_TYPE;
v_amount INTEGER := 32767;
v_xml_data XMLType;
v_char_buffer VARCHAR2(32767);
BEGIN
-- abre o arquivo para gravar o texto (até v_amount caracteres por vez)
v_file:=UTL_FILE.FOPEN(p_directory, p_file_name, ‘w’, v_amount);
138
L A B O R A T O R I O D E B A N C O D E D A D O S

-- grava a linha inicial em v_file


UTL_FILE.PUT_LINE(v_file, ‘<?xml version="1.0"?>‘);
-- recupera os clientes e o armazena em v_xml_data
SELECT
EXTRACT(
XMLELEMENT("customer_list",
XMLAGG(XMLELEMENT("customer", first_name || ‘ ‘ || last_name)
ORDER BY last_name )), ‘/customer_list’ )
AS xml_customers
INTO v_xml_data
FROM customers;
-- obtém o valor da string de v_xml_data e o armazena em v_char_buffer
v_char_buffer := v_xml_data.GETSTRINGVAL();
-- copia os caracteres de v_char_buffer no arquivo
UTL_FILE.PUT(v_file, v_char_buffer);
-- descarrega os dados restantes no arquivo
UTL_FILE.FFLUSH(v_file);
-- fecha o arquivo
UTL_FILE.FCLOSE(v_file);
END write_xml_data_to_file;

Para executar o procedimento acima digite:


CALL write_xml_data_to_file(‘TEMP_FILES_DIR’,’customers.xml’);
Após a execução vá no diretório C:/TEMP_FILES onde deverá existir um arquivo
chamado customers.xm:

Figura 36 - Resultado em XML (feito pelo Autor)

O procedimento acima poderá ser modificado para recuperar qualquer


informação do banco de dados para gerar um XML.

XMLQUERY()
Usada para construir ou consultar códigos XML, passando uma expressão
XQueryXML, que é uma linguagem de consulta que permite construir e consultar
código XML, retornando o resultado da avaliação da expressão. Exemplo: Criar strings
XML para produtos e tipos de produto.

139
L A B O R A T O R I O D E B A N C O D E D A D O S

Obs.: Utiliza métodos do pacote PL/SQL DBMS_XDB para excluir e criar arquivos
de recursos XML no XML DB Repository do Oracle – é uma área de armazenamento
para dados XML dentro do banco de dados:
CREATE OR REPLACE PROCEDURE create_xml_resources AS
v_result BOOLEAN;
-- cria string contendo código XML para produtos
v_products VARCHAR2(300):=
‘<?xml version="1.0"?>‘ ||
‘<products>‘ ||
‘<product product_id="1" product_type_id="1" name="Modern Science"‘ ||
‘ price="19.95"/>‘ ||
‘<product product_id="2" product_type_id="1" name="Chemistry"‘ || ‘
price="30"/>‘ ||
‘<product product_id="3" product_type_id="2" name="Supernova"‘ || ‘
price="25.99"/>‘ ||
‘</products>‘;
-- cria string contendo código XML para tipos de produtos
v_product_types VARCHAR2(300):=
‘<?xml version="1.0"?>‘ ||
‘<product_types>‘ ||
‘<product_type product_type_id="1" name="Book"/>‘ ||
‘<product_type product_type_id="2" name="Video"/>‘ ||
‘</product_types>‘;
BEGIN
-- exclui o recurso existente para produtos
DBMS_XDB.DELETERESOURCE(‘/public/products.xml’,
DBMS_XDB.DELETE_RECURSIVE_FORCE);
-- cria um recurso para produtos
v_result := DBMS_XDB.CREATERESOURCE(‘/public/products.xml’,
v_products);
-- exclui o recurso existente para tipos de produtos
DBMS_XDB.DELETERESOURCE(‘/public/product_types.xml’,
DBMS_XDB.DELETE_RECURSIVE_FORCE);
-- cria um recurso pra tipos de produtos
v_result :=DBMS_XDB.CREATERESOURCE(‘/public/product_types.xml’,
v_product_types);
END create_xml_resources;
/

EXERCÍCIOS PRÁTICOS
Crie um procedimento chamado XML_EMPREGADO que consulta na tabela
EMPLOYEES recuperando o nome, salário e o cargo dos funcionários.
23 Necessário ter cadastro no site da Oracle, porém é gratuito.
24 Necessário ter cadastro no site da Oracle, porém é gratuito.

140