Download Oracle9i Fundamental_final.pdf...
ORACLE 9I FUNDAMENTAL SQL, PL/SQL E ADMINISTRAÇÃO
Oracle 9i Fundamental
1
EDUARDO TERRA MORELLI
[email protected]
ORACLE 9I FUNDAMENTAL SQL, PL/SQL E ADMINISTRAÇÃO
Morelli, Eduardo M. Terra, 19661. Banco de dados - Gerência 2. Oracle 3. PL/SQL (Linguagem de programação para computadores) 4. SQL (Linguagem de programação para computadores) I. Título. Índices para Catálogo Sistemático: 1. Oracle: Banco de dados : Sistemas de gerência 005.75 “Algumas imagens utilizadas neste livro foram obtidas a partir do CorelDRAW 7, 8 e 9 e da Coleção do MasterClips/ MasterPhotos© da IMSI, 1985 Francisco Blvd. East, San Rafael, CA 94901-5506, USA.”
Oracle 9i Fundamental
2
FABRICANTE Produto: Oracle 9i Oracle do Brasil Rua José Guerra, 127 - Chácara Santo Antônio CEP: 04719-030 - São Paulo - SP Tel: (11) 5189-1000 Site: www.oracle.com.br
REQUISITOS DE HARDWARE E DE SOFTWARE Para que os assuntos aqui tratados possam ser postos em prática, deve-se atender a um conjunto mínimo de requisitos, tanto de hardware quanto de software. Tomou-se por base a plataforma Windows, utilizada ao longo do livro. Seguem os requisitos mínimos de hardware para utilização do Oracle Server 9i na plataforma Windows: Servidor:
PC baseado em processador Pentium 166 MHz (recomendado: Pentium 233 MHz).
RAM: mínimo de 128 MB; recomenda-se 512 MB. Espaço em disco configurado como NTFS: 2,8 GB (não incluído espaço de bases de dados) mais 275 MB no disco de sistema. Para discos configurados como FAT: 4,5 GB mais 140 MB no disco de sistema. Disco contendo diretório apontado pela variável de ambiente TEMP deve possuir 400 MB livres, no mínimo. Área de paginação (swap) deve partir de 200 MB. Placa de vídeo SuperVGA com 2 MB de memória. Máquinas clientes devem partir de Pentium 166 MHz, possuir 64 MB de RAM e 800 MB de espaço livre em disco. Software mínimo: Servidor: Windows 2000 com último Service Pack instalado; Microsoft Internet Explorer 5.5; Oracle Server. Cliente: Windows 98; Microsoft Internet Explorer 5.5; Oracle Client. O ambiente necessário para praticar os ensinamentos do livro consiste no Windows 2000 com último Service Pack; Oracle Server versão 9.2; SQL Navigator da Quest, para os capítulos de programação; Uma planilha compatível com Microsoft Excel para abrir o arquivo Livros_Oracle9i.xls. Para realizar instalações em outras plataformas, deve-se consultar documentação específica do Sistema Operacional em questão. Inicie a busca por: http://technet.oracle.com/docs/products/oracle9i/content.html. Mais detalhes no Apêndice G.
Oracle 9i Fundamental
3
DEDICATÓRIA Ao Thiago, ainda alguns Bytes; Ao Leonardo, já com alguns Kilobytes; À Monick, todo Exabyte que houver.
Oracle 9i Fundamental
4
AGRADECIMENTOS Nenhum livro pode ser escrito apenas pelo seu autor. Todos aqueles que contribuam para incrementar os conhecimentos teóricos e dêem oportunidades para aplicá-los também são um pouco autores. Sendo assim, gostaria de agradecer às contribuições da GINFO da Companhia Libra de Navegação representada por Marcelo, Fernando, Eduardo, Marcia, Luís Eduardo, Leme, Mariana, Marcos, Pedro, Cristina, Bruno, Ricardo, Américo, Hamilton, Fátima e, principalmente, Luís Paulo Soares Dutra, o Lupa (as dicas sobre LOBs foram cruciais). Mas, apenas oportunidade de estudo e prática não são o bastante para produzir um livro. Palavras de incentivo, quando emitidas no momento certo e da forma adequada, representam um estímulo sem igual. E não existiram palavras tão instigantes como as de Patrícia de Andrade Bueno Garcia, da UFPR (Curitiba-PR). Incentivo é pouco diante da persistência de Rosana Arruda. Graças à sua infinita paciência com prazos expirados, este trabalho pôde ser concluído. Obrigado a Pieter Reckman da Starsoft pela confiança depositada nestes três anos de convivência. A Luiz Paulo Maia pelo excelente artigo do Capítulo 17. Deveriam inventar uma palavra que expressasse uma imensa gratidão, pois ela seria destinada aos meus pais, Enrique e Guillermina, pelo apoio em todos estes anos. Um agradecimento especial às minhas irmãs, Mariana, Victoria, Maria José e Maria Pia, pelo exemplo de persistência e integridade. Já que inventarão uma palavra para imensa gratidão, deveriam fazê-lo também para expressar um sentimento que revelasse extrema felicidade por compartilhar a vida de outra pessoa especial, pois essa palavra representaria uma ínfima parcela do que significa viver com Monick. Aos meus segundos pais, Sergio e Elizabeth pelo apoio nestes meses de trabalho árduo. Ao Leonardo sou grato pelo brilho em seus olhos a cada capítulo concluído. Ao Thiago, pela paz que emana de seu ser. Oracle 9i Fundamental
5
SOBRE O AUTOR Eduardo Terra Morelli, autor dos livros Oracle 8: SQL, PL/SQL e Administração (2000) e de SQL Server 2000 Fundamental (2001), trabalha com treinamento e confecção de material didático desde 1986. Neste período, foram mais de 6.300 horas de sala de aula, com cerca de 2.600 alunos, sem contar com oito anos como professor universitário na PUC-RJ (350 alunos) e ainda outro na Faculdade Carioca (100 alunos). Atualmente trabalha como DBA Oracle e SQL Server em diversas empresas, além de, claro, ministrar cursos sobre estes assuntos. Já escreveu mais de trinta apostilas, além de diversas contribuições para revistas do ramo, tais como MicroSistemas.
Oracle 9i Fundamental
6
SOBRE O MATERIAL DISPONÍVEL NA INTERNET O material disponível na Internet contém arquivos de exercícios e exemplos utilizados ao longo do livro. Em cada capítulo (seção Arquivos Necessários) aparece uma lista com os arquivos a serem utilizados no capítulo em questão. Após a descompactação, os arquivos estarão distribuídos por quatro diretórios: C:\ParteI, C:\ParteII, C:\ParteIII e C:\Hots. Para utilizar esses arquivos, é imprescindível que o leitor possua o Oracle 9i Server (servidor) e Client (cliente) instalados sua máquina, Servidora e Cliente, respectiva-mente. Para acompanhar os exemplos descritos na Parte II, também recomendam-se as presenças do SQL Navigator da Quest e de algum editor de textos compatível com Microsoft Word no Cliente. Vale ressaltar que todos os trabalhos podem ser efetuados apenas na máquina servidora, caso exista uma para fins de testes. Arquivo ORACLE_9I.EXE EXERCICIO.EXE
Tamanho 96 KB 734 KB
Procedimento para Download Acesse o site do Autor: www.tmorelli.com.br. Na página principal do site, selecione Livros e clique no item “Download”. Dê um clique sobre o arquivo executável e este será transferido. Procedimento para Descompactação Primeiro passo: após ter transferido o arquivo, verifique o diretório em que se encontra e dê um duplo-clique sobre ele. Será exibida uma tela do programa WINZIP SELF-EXTRACTOR que conduzirá você ao processo de descompactação. Abaixo do Unzip To Folder, existe um campo que indica o destino dos arquivos que serão copiados para o disco rígido do seu computador. Segundo passo: prossiga com a instalação, clicando no botão Unzip, o qual se encarrega de descompactar os arquivos. Logo abaixo dessa tela, aparece a barra de status a qual monitora o processo para que você acompanhe. Após o término, outra tela de informação surgirá, indicando que os arquivos foram des-compactados com sucesso e estão no diretório criado. Para sair dessa tela, clique no botão OK. Para finalizar o programa WINZIP SELF-EXTRACTOR, clique no botão Close.
Oracle 9i Fundamental
7
PREFÁCIO Recente estudo conduzido na Universidade da Califórnia, em Berkeley, concluiu que o mundo produz entre um e dois exabytes (EB) por ano. Já Richard Niemiec afirma que se estima em 12 EB o total de informações no mundo1. Só para que se tenha uma noção do que isso significa, analise a seguinte tabela: Potência de 10
Nome
Armazena
0
Byte (B)
Um caractere representa um byte.
3
Kilobyte (KB)
Uma página de um livro típico ocupa 25 linhas e 80 colunas, resultando em pouco menos de 2 KB.
6
Megabyte (MB)
Supondo que uma página ocupe 2000 bytes, um livro com 500 páginas gastaria 1 MB; um arquivo MP3 contendo uma mú-sica típica gasta cerca de 4 MB.
9
Gigabyte (GB)
Uma sinfonia completa em alta fidelidade ocuparia 1 GB; típicos Bancos de Dados comerciais possuem entre 5 e 200 GB.
12
Terabyte (TB)
Papel equivalente a 50.000 árvores.
15
Petabyte (PB)
Estima-se em 8 PB o volume de toda a informação disponível na Internet.
18
Exabyte (EB)
Todas as palavras já ditas por todos os seres humanos ocupariam 5 EB.
21
Zettabyte (ZB)
?
24
Yottabyte (YB)
?
Desde 1979, quando foi lançado o primeiro SGBDR comercial, a Oracle notabilizou-se por nortear os rumos do mercado de Bancos de Dados Corporativos. Em junho de 2001, a Oracle lançou a versão 9i de seu SGBDR2, o primeiro a permitir acesso a dados em barramento de 64 bits. Se memória física não for empecilho, com esta característica é possível endereçar 264, o que equivale a 16 exabytes! Só para se ter uma idéia do que representa este vanguardismo, a Microsoft ainda não possui um Sistema Operacional com este poder de endereçamento. 1
2
Leia a íntegra da pesquisa em http://www.sims.berkeley.edu/research /projects/how-much-info/summary.html. A afirmação de Richard Niemiec consta na edição de setembro/outubro de 2001 da Oracle Magazine (página 29). Em maio de 2002 foi lançada a versão 9.2, também conhecida por Release II
Oracle 9i Fundamental
8
Este livro destina-se ao profissional que percebeu a importância dos bancos de dados Oracle em plena Era da Informação. A meta principal consiste em, objetivamente, abrir as portas do Mundo Oracle. O leitor não pode se conformar em “parar” aqui. Há muitos pontos que podem e devem ser explorados mais a fundo. Composição do Livro O livro divide-se em quatro partes. A primeira trata de SQL (capítulos 1 a 7), na qual são ensinados os fundamentos desta importantíssima linguagem de manipulação de bancos de dados relacionais. A partir de um estudo de caso, que, aliás, continua sendo usado ao longo do livro, apresentam-se a terminologia básica, como se conectar as bases Oracle e os comandos SQL mais importantes. Leitores com pouca ou nenhuma experiência em SQL devem estudar a fundo estes capítulos. A segunda parte (capítulos 8 a 17) destina-se aos programadores que desejam desenvolver código na linguagem PL/SQL. Diferente de outras linguagens, tais como: Pascal, C ou VBA, os “programas” escritos em PL/SQL são executados no Servidor em que estão os dados. Há muitos tópicos interessantes nesses capítulos: Cursores, Packages, Triggers e Objetos, em que há um texto primoroso sobre as bases conceituais do Paradigma da Orientação por Objetos escrito por Luiz Paulo Maia. O melhor do livro está na terceira parte (capítulos 18 a 26) que explica como um banco de dados Oracle deve ser administrado, ou melhor, como trabalha um DBA. Há que se comentar quase todos os capítulos: o 19 apresenta a arquitetura de um BD Oracle; o 20 trata sobre Tablespaces; do 21 ao 23, explica-se Segmento e as suas variações: Undo (21), Tabela (22) e Índice (23); o 24 discute aspectos de segurança e o 25 sobre como implementar uma Política de Backup consistente. Finalmente, há breves comentários sobre a utilização do Database Configuration Assistant sob Windows 2000. A última parte reúne os sete apêndices do livro. Destaque para o C no qual se comentam diversos livros de Oracle que complementam os assuntos aqui tratados. Seguindo o princípio do aprendizado contínuo, este apêndice apresenta os próximos desafios. O arquivo fornecido Livros_Oracle9i traz uma relação mais completa com editora, páginas e ISBN.
Oracle 9i Fundamental
9
Devo enfatizar o apêndice D apresentando um exemplo de relatório produzidos em um típico dia de trabalho de um DBA. Vale a pena conferir o E, no qual se detalha um roteiro que permite implementar um Banco Standby, isto é, uma fiel cópia do original por motivos de performance (abriga pesadas consultas) e disponibilidade (caindo a produção, rapidamente se mudam as conexões para o novo Banco). Finalmente, o apêndice F oferece uma lista de endereços na Internet (mais de 30) coletada por horas a fio. Lembre-se que a Internet é muito dinâmica, assim, quando chegar nele, outros endereços podem existir. Por falar em Internet, há no site do Autor (www.tmorelli.com.br) uma lista de scripts que podem e devem ser carregados. Os quase cem arquivos estão distribuídos em quatro diretórios: ParteI, ParteII, ParteIII e ParteIV. Este último, abriga o HOTS, contendo um conjunto de scripts que devem ser utilizados regularmente. O ambiente necessário para praticar os ensinamentos do livro consiste no Windows 2000 com último Service Pack; Oracle Server versão 9.2; SQL Navigator da Quest, para os capítulos de programação.
Oracle 9i Fundamental
10
Composição dos Capítulos A organização interna dos capítulos segue o estilo dos outros livros do autor, sendo resultado da experiência adquirida em escrever materiais didáticos ao longo dos últimos 16 anos. Todo capítulo divide-se em: Objetivos: Novidades Arquivos Necessários: Prérequisitos: Motivação: Teoria: Exercícios/ dicas:
Referência Rápida:
determina-se o que o leitor deve aprender com o capítulo corrente. Deve-se voltar a esta seção freqüentemente para que o foco não seja perdido. presente a partir do capítulo 19, revela os novos recursos in-troduzidos na versão 9i. scripts utilizados como exemplo ou exercício. Há mais de cem arquivos fornecidos. destinado ao leitor que não prefira uma leitura seqüencial, para que avalie se possui os conhecimentos necessários para estudar o capítulo. nem sempre presente, exibe uma situação problema que in-troduz os tópicos a serem aprendidos. apresenta conceitos, exemplifica, fornece sintaxe de coman-dos. complementa a teoria a partir de instigantes exercícios. Existem alguns, inclusive, que levam o leitor a conhecer novos recursos (por exemplo, trigger em startup no capítulo 19). Há quase 270 exercícios, cujas soluções comentadas estão disponíveis no site do Autor (maiores informações na página “Sobre o Material Disponível na Internet”). célere fonte de acesso à teoria. Também possui caráter complementar e às vezes apresenta recursos inéditos (por exemplo, comando CREATE PFILE no capítulo 19).
Por que vale a pena ler este livro Quem adquiriu o primeiro livro, ORACLE8: SQL, PL/SQL e ADMINISTRAÇÃO pode pensar que comprar este seria um desperdício de tempo e dinheiro, entretanto, há muitas razões para não pensar desta forma:
Oracle 9i Fundamental
11
Já se passaram mais de dois anos desde o lançamento do primeiro livro. Neste tempo, o autor aumentou seus conhecimentos dramaticamente, já que vivenciou Bancos de Dados Oracle diariamente;
Aquele livro tratava da versão 8. Depois dela, já foram lançadas a 8i, 9i e 9i Release II, estas duas últimas com grande destaque neste trabalho;
Há muito mais páginas, exercícios (todos corrigidos!), dicas, notas de rodapé, exemplos e scripts;
A maioria dos capítulos foram quase totalmente reescritos, como por exemplo o 15–Packages (há grande ênfase em LOBs); 21-Segmentos de Undo/Rollback (aborda SMU e DBMS_FLASHBACK), 22Segmentos de Tabelas (IOTs, Materialized Views), 23-Segmentos de Índice (Bitmaps), 24-Segurança (mais recursos de gerência de usuários) e, principalmente, o 25-Backup & Recover tratando de assuntos inéditos como LogMiner, Tablespaces Transportáveis e Recovery Manager.
Oracle 9i Fundamental
12
ÍNDICE ANALÍTICO Capítulo 1 – Bancos de Dados ............................ 21 1.1 - O Problema ........................................... 22 1.1.1 - A Situação Ideal ................................... 23 1.2 - A Solução............................................. 23 1.2.1 - Projeto Conceitual.................................. 24 1.2.2 - Projeto Lógico ..................................... 25 1.3 - SQL ................................................. 25 Capítulo 2 – TABELAS .................................... 28 2.1 - Conexão.............................................. 28 2.2 - Criação de Tabelas ..................................... 29 2.2.1 - Tipos de Dados .................................... 30 2.2.2 - Constraints ....................................... 32 2.3 - Alteração de Tabelas .................................... 35 2.4 - Exclusão de Tabelas .................................... 37 2.5 - Inserção de Dados...................................... 38 Capítulo 3 – SELEÇÃO DE DADOS ........................... 42 3.1 - Seleções Simples ....................................... 42 3.2 - Ordenações e Filtros .................................... 45 3.3 - Visualizando Dados em Tabelas Diferentes .................. 48 3.3.1 3.3.2 3.3.3 3.3.4
-
Relacionamento Relacionamento Relacionamento Relacionamento
EquiJoin............................ OuterJoin........................... NonEquiJoin ........................ SelfJoin ............................
48 52 52 53
3.4 - Expressões Calculadas .................................. 53 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5
-
Funções Funções Funções Funções Funções
de Caracteres .............................. de Datas .................................. Numéricas ................................ de Conversão de Dados ...................... de Grupo .................................
54 55 57 57 60
3.5 - Operadores de Conjunto ................................. 62 3.6 - Dicionário de Dados .................................... 64 Capítulo 4 – ATUALIZAÇÃO DE DADOS ....................... 70 Oracle 9i Fundamental
13
4.1 - Fundamentos ......................................... 70 4.2 - Alteração de Linhas..................................... 71 4.3 - Eliminação de Linhas ................................... 71 4.4 - Transações ........................................... 72 Capítulo 5 – RELATÓRIOS ................................. 79 5.1 - Fundamentos ......................................... 79 5.2 - Variáveis de Ambiente................................... 80 5.3 - Comandos SQL*Plus Worksheet de Formatação ............... 81 5.3.1 - Column .......................................... 81 5.3.2 - Ttitle e Btitle ...................................... 83 5.3.3 - Break e Compute .................................. 83 5.4 - Bind Variables......................................... 84 5.5 - Geração de SQL........................................ 86 Capítulo 6 – OUTRAS ESTRUTURAS DE DADOS ................. 89 6.1 - Fundamentos ......................................... 90 6.2 - Índices ............................................... 90 6.3 - Views ................................................ 92 6.4 - Sequences ............................................ 95 6.5 - Synonyms ............................................ 97 Capítulo 7 – SUBQUERIES ................................ 101 7.1 - Fundamentos ........................................ 101 7.2 - Subqueries de Uma Linha .............................. 102 7.3 - Subqueries de Múltiplas Linhas .......................... 104 7.4 - Subqueries de Múltiplas Colunas......................... 106 7.5 - Subqueries Correlatas ................................. 106 Capítulo 8 – PROGRAMAÇÃO CLIENTE/ SERVIDOR ............. 110 Criando Programas sob Enfoque Cliente-Servidor ............. 110 8.1 - PL/SQL ............................................. 112 8.2 - PL/SQL ou Java? ..................................... 113 8.3 - Unidades de Programa ................................. 114 8.4 - Procedures........................................... 115 8.5 - Functions ........................................... 116 Capítulo 9 – SQL NAVIGATOR ............................. 120 9.1 - Fundamentos ........................................ 120 Oracle 9i Fundamental
14
9.2 - Elementos do Ambiente ................................ 121 9.2.1 - DB Navigator..................................... 9.2.2 - Stored Program Editor ............................. 9.2.3 - SQL Editor ...................................... 9.2.4 - Trigger Editor .................................... Capítulo 10 – VARIÁVEIS ................................
121 122 123 123 126
10.1 - Fundamentos ....................................... 126 10.2 - Tipos Escalares ...................................... 127 10.3 - Tipos Compostos ..................................... 129 10.3.1 - Vetores (Tables).................................. 129 10.3.2 - Registros (Records) ............................... 130 10.4 - Escopo ............................................. 131 Capítulo 11 – PL/SQL: SQL .............................. 134 11.1 - Seleção (Select/Into) .................................. 134 11.2 - Inserção (Insert) ..................................... 136 11.3 - Alteração (Update).................................... 137 11.4 - Exclusão (Delete)..................................... 138 11.5 - SQL Dinâmica ....................................... 139 Capítulo 12 – pl/sql:pl ................................ 142 12.1 - Processamento Condicional ............................ 142 12.2 - Processamento Repetitivo .............................. 145 12.2.1 12.2.2 12.2.3 12.2.4
-
FOR ........................................... WHILE ......................................... LOOP .......................................... FORALL........................................
145 146 147 148
12.3 - Depuração .......................................... 149 Capítulo 13 – CURSORES ................................. 153 Exemplo de processamento precisando Cursores .............. 153 13.1 - Fundamentos ....................................... 154 13.2 - Cursores Explícitos ................................... 156 13.3 - Cursores de Atualização ............................... 159 Capítulo 14 – EXCEÇÕES ................................. 163 14.1 - Fundamentos ....................................... 163 14.2 - Exceções Predefinidas................................. 164 14.3 - Exceções não Predefinidas ............................. 166 14.4 - Exceções Definidas pelo Usuário ........................ 167 Oracle 9i Fundamental
15
14.5 - Exceções em Blocos Anônimos.......................... 169 Capítulo 15 – PACKAGES ................................. 173 15.1 - Fundamentos ....................................... 174 15.2 - Criação ............................................ 175 15.2.1 - Especificação ................................... 175 15.2.2 - Corpo.......................................... 176 15.3 - Ativação ............................................ 177 15.4 - Dependências ....................................... 178 15.5 - Packages Embutidos.................................. 180 15.5.1 - DBMS_JOB ..................................... 180 15.5.2 - DBMS_LOB ..................................... 183 Capítulo 16 – TRIGGERS ................................. 191 16.1 - Fundamentos ....................................... 191 16.2 - Criação ............................................ 194 16.3 - DML ............................................... 196 16.3.1 16.3.2 16.3.3 16.3.4
-
INSERT ........................................ UPDATE ....................................... Delete ......................................... Múltiplos .......................................
196 196 197 198
16.4 - Atualização de Views.................................. 199 16.5 - Schema ............................................ 200 16.6 - DBMS_ALERT ....................................... 201 Capítulo 17 – OBJETOS .................................. 205 O Paradigma da orientação por Objetos ..................... 206 17.1 - Fundamentos ....................................... 210 17.2 - Tipos Objeto ........................................ 211 17.3 - Herança ............................................ 214 17.4 - Tabelas de Objetos ................................... 215 17.5 - Tabelas Aninhadas ................................... 217 17.6 - Vetores Variáveis..................................... 219 Capítulo 18 – INTRODUÇÃO À ADMNISTRAÇÃO ................ 223 Um Dia na Vida de Daniel Barbosa Alves (DBA) ............... 224 18.1 - O DBA ............................................. 224 18.2 - Organização Interna .................................. 226 18.2.1 - Organização Física ............................... 226 18.2.2 - Organização Lógica............................... 227 Oracle 9i Fundamental
16
18.3 - Objetos de um Banco de Dados ......................... 227 Capítulo 19 – ORGANIZAÇÃO FÍSICA ....................... 230 19.1 - Arquivos ........................................... 231 19.1.1 19.1.2 19.1.3 19.1.4 19.1.5 19.1.6
-
Data Files ...................................... Control Files .................................... Redo Log Files................................... Arquivos de Parâmetros (INIT.ORA e SPFILE.ORA) ...... Arquivos de Acompanhamento...................... Arquivo de Senhas ...............................
232 233 233 235 236 237
19.2 - Memória ........................................... 237 19.2.1 - Program Global Area (PGA) ........................ 237 19.2.2 - System Global Area (SGA) ......................... 237 19.3 - Processos........................................... 239 19.3.1 - Processo Usuário ................................ 239 19.3.2 - Processo Servidor ................................ 239 19.3.3 - Processo Background ............................. 240 19.4 - Instância ........................................... 242 19.4.1 19.4.2 19.4.3 19.4.4
-
Parâmetros ..................................... Etapas ......................................... Fechando: Shutdown ............................. Abrindo: Startup.................................
242 245 246 247
19.5 - Visão Geral ......................................... 248 19.6 - O Que Ocorre Durante um SELECT...................... 248 19.7 - O Que Ocorre Durante um UPDATE ..................... 249 19.8 - Notas sobre o Oracle sob Windows 2000 .................. 250 Capítulo 20 – ORGANIZAÇÃO LÓGICA: TABLESPACES .......... 258 20.1 - Fundamentos ....................................... 259 20.2 - OFA (Optimal Flexible Architecture)...................... 260 20.3 - Criação ............................................ 261 20.4 - Alteração ........................................... 267 20.5 - Eliminação ......................................... 269 20.6 - Enterprise Manager Console ........................... 270 Capítulo 21 – SEGMENTOS DE ROLLBACK/UNDO ............... 274 21.1 - Introdução aos Segmentos ............................. 275 21.2 - Introdução aos Segmentos de Rollback/ Undo ............. 276 21.3 - Gerência Automática (System Managed Undo) ............. 279 Oracle 9i Fundamental
17
21.4 - Flashback Queries ................................... 281 21.5 - Gerência Manual..................................... 283 21.6 - Regras de Ouro para Gerência Manual ................... 286 21.7 - Enterprise Manager Console ........................... 286 Capítulo 22 – SEGMENTOS DE TABELA ...................... 291 22.1 - Fundamentos ....................................... 292 22.2 - Alteração de Segmentos de Tabela ....................... 295 22.3 - Identificação de Linhas ................................ 297 22.4 - Encadeamento de Linhas .............................. 299 22.5 - Materialized Views ................................... 300 22.6 - Index-Organized Tables (IOTs) .......................... 301 22.7 - Partições ........................................... 302 22.8 - Estatísticas ......................................... 305 22.9 - Reorganização ....................................... 307 22.9.1 22.9.2 22.9.3 22.9.4 22.9.5 22.9.6 22.9.7
-
Testando Viabilidade do Processo ................... Criação da Tabela Intermediária .................... Preenchimento dos Dados ......................... Novas Características ............................. Sincronismo .................................... Troca de Tabelas................................. Eliminação .....................................
307 308 308 308 309 309 309
22.10 - Tabelas Externas.................................... 310 Capítulo 23 – SEGMENTOS DE ÍNDICE ...................... 315 23.1 - Fundamentos ....................................... 315 23.2 - Organização Interna .................................. 319 23.2.1 - Árvore-B ....................................... 319 23.2.2 - Bitmap ........................................ 321 23.3 - Alteração de Segmentos de Índice ....................... 323 23.4 - Acompanhamento .................................... 324 23.5 - Partições ........................................... 325 Capítulo 24 – SEGURANÇA ................................ 329 24.1 - Fundamentos ....................................... 330 24.2 - Usuários ........................................... 331 24.3 - Privilégios .......................................... 333 24.3.1 - Privilégios de Sistema ............................. 333 Oracle 9i Fundamental
18
24.3.2 - Privilégios de Objeto .............................. 335 24.4 - Roles .............................................. 338 24.5 - Profiles............................................. 339 24.6 - Autenticação via Sistema Operacional .................... 341 24.7 - Auditoria ........................................... 342 24.8 - Regras de Ouro ...................................... 344 Capítulo 25 – BACKUP & RECOVER ......................... 354 25.1 - Fundamentos ....................................... 355 25.2 - Operações Lógicas.................................... 359 25.2.1 - Exportação ..................................... 359 25.2.2 - Importação ..................................... 362 25.3 LogMiner ............................................ 365 25.4 DBMS_FLASHBACK ................................... 368 25.5 - Tablespaces Transportáveis ............................ 369 25.6 - Cold Backup ........................................ 371 25.7 - Hot Backup ......................................... 372 25.7.1 - Modo ArchiveLog................................. 372 25.7.2 - Hot Backup ..................................... 374 25.7.3 - Recuperação a partir de um Hot Backup ............. 376 25.8 Recovery Manager ..................................... 378 25.8.1 25.8.2 25.8.3 25.8.4 25.8.5
-
Terminologia .................................... Preparação ..................................... Backup ........................................ Recuperação .................................... Automação .....................................
378 380 381 384 387
25.9 - Conclusão .......................................... 388 Capítulo 26 – CRIAÇÃO DE UM BANCO DE DADOS ............. 398 26.1 - Fundamentos ....................................... 398 26.2 - Database Configuration Assistant ....................... 399 26.3 - Net Configuration Assistant ............................ 400 26.4 - Eliminação de um Banco de Dados ...................... APÊNDICE a: SQL*PLUS ................................... APÊNDICE b: MODELO DE CONTROLE ACADÊMICO ............... APÊNDICE C: BIBLIOGRAFIA COMENTADA ..................... APÊNDICE D: EXEMPLO DE RELATÓRIO DE LEVANTAMENTO .......
401 402 404 406 411
Medidas Básicas .......................................... 412 Oracle 9i Fundamental
19
APÊNDICE E: STANDBY DATABASES .......................... 421 E.1 - Fundamentos ........................................ 421 E.2 - Parâmetros no Banco Principal .......................... 422 E.3 - Parâmetros no Banco Standby........................... 424 E.4 - Implantando Modo Manual ............................. 424 E.5 - Implantando Modo Automático .......................... 425 E.6 - Implantando Modo Leitura .............................. 426 E.7 - Desativando Servidor Standby ........................... 427 E.8 - Conclusões .......................................... 427 APÊNDICE F: APOIO NA INTERNET .......................... 429 APÊNDICE G: INSTALAÇÃO NO WINDOWS 2000 ................. 434 G.1 - Fundamentos ........................................ 434 G.2 - Requerimentos de Hardware ............................ 434 G.3 - Requerimentos de Software ............................. 434 G.4 - Processo ............................................ 435 G.5 - Verificação .......................................... 435 G.6 - Instalação no Cliente .................................. 437
MARCAS REGISTRADAS Oracle é marca registrada da Oracle Inc. Windows, Access, MS-SQL Server são marcas registradas da Microsoft Corporation. SQL Navigator é marca registrada da Quest Inc. Todos os demais nomes registrados, marcas registradas, ou direitos de uso citados neste livro, pertencem aos respectivos proprietários.
Oracle 9i Fundamental
20
Capítulo 1 – Bancos de Dados OBJETIVOS • • • •
Conhecer o estudo de caso utilizado ao longo do livro; Rever termos básicos relacionados a Bancos de Dados; Travar um primeiro contato com a linguagem SQL; Informar sobre o real significado do mundo Oracle.
ARQUIVOS NECESSÁRIOS •
Nenhum.
PRÉ-REQUISITOS • • • •
Noções de Modelagem de Dados; Definir entidade, atributo, relacionamento; Compreender o papel da Normalização no Projeto de um Banco de Dados; Identificar as diferentes etapas prévias à construção de um Banco de Dados.
Oracle 9i Fundamental
21
MOTIVAÇÃO O Mundo Oracle O maior mérito da Oracle Corporation foi apostar decisivamente em uma ferramenta de gerência de bancos de dados relacionais. O estrondoso sucesso no início dos anos setentas levou à criação de versões específicas às plataformas de hardware. No "boom" do PC, a Oracle lançou sua versão para micros. Há muito o nome Oracle deixou de significar apenas uma poderosa ferramenta para implementação de Bancos de Dados corporativos, cujo único objetivo era ler, gravar e proteger dados. Hoje a Oracle tem produtos na área de desenvolvimento (Forms Developer, Designer, Reports Developer, JDeveloper), Servidor de Aplicações (Oracle Application Server), ERP (Financials, Human Resources, etc.), Internet (Commerce Server, Self-Service Web Applications), OLAP (Data Mart Suite, Data Mining Suite, Discoverer) e, evidentemente, administração de Bancos de Dados (Oracle-Server, Enterprise Manager). Uma das grandes razões do sucesso da Oracle foi criar produtos que pudessem ser utilizados em diversas plataformas: desde o VMS até o Unix, passando pelo Windows (3.1, 9x, NT, 2000, XP). Ao longo do livro serão construídas e alimentadas com dados as tabelas discutidas no presente capítulo. Desta forma, juntamente com o Oracle-Server, será utilizada a ferramenta SQL*Plus Worksheet que, além de responsável pela conexão entre Cliente e Servidor (podem estar em uma mesma máquina ou em duas), reconhece e submete comandos SQL para execução no Servidor e permite, entre outras facilidades, a entrada de dados interativa, formatação de saída e edição de comandos SQL e próprios por meio de um editor de textos.
TEORIA 1.1 - O Problema O famoso CEVOG (Centro Educacional de Volta Grande), melhor escola da região, completa trezentos anos de existência. Dizem que até Tiradentes rabiscou suas primeiras letras por lá.
Oracle 9i Fundamental
22
Em breve, o atual diretor, Moura XI, passará o cargo para seu filho, o jovem promis-sor Moura XII. Cargo este já ocupado pelo lendário Moura I, o Fundador. Para comemorar tal importante data e também a passagem do cargo, finalmente o CEVOG resolveu render-se à modernidade: a partir deste ano, o notório centro também oferecerá cursos de informática à comunidade. O jovem Moura XII está bastante preocupado: como disponibilizar cursos de computação se todo o controle interno ainda é manual? O Controle Acadêmico a ser implantado tentará copiar o utilizado há tanto tempo pelos cursos regulares. Existem dois cadastros: o de Alunos (Nome, Endereço, Telefone) e o de Cursos (Descrição, Carga Horária, Prérequisitos). Há dez cursos e, a princípio, uns trezentos alunos. Nada foi definido quanto à criação de turmas, nem há a menor idéia de como implantar o controle de instrutores. Seria interessante guardar um histórico de cada aluno (notas, freqüências) para poder controlar prérequisitos em futuras matrículas. Os problemas são muitos, mas nada que possa arrefecer os ânimos dos Moura. Se eles já foram até citados como centro de excelência de ensino nos idos anos quarentas (do século XIX!), não será um curso de informática que os fará recuar ante o inexorável avanço do tempo.
1.1.1 - A Situação Ideal Moura, o Doze, deseja implantar o seguinte: •
•
•
Criar um cadastro de Instrutores (Nome, Endereço, Telefone, Data de admissão) para que seja implantado um eficiente sistema de alocação; Integrar os cadastros de Alunos e Cursos para saber, em questão de minutos, se um determinado indivíduo está fazendo ou já fez um dado curso; Criar outro cadastro de Notas (Turma, Matrícula, Nota) para que se tenha uma idéia do nível de cada aluno.
Numa próxima ocasião será implantado um controle rigoroso sobre cobrança, prevendo, inclusive, uma modalidade de pagamento a prazo mais sofisticada. A idéia é oferecer os cursos para o mundo via Internet, assim os dados armazenados serão da ordem de peta bytes, o que justifica a utilização do Sistema Gerenciador de Bases de Dados Objeto-Relacionais Oracle 9i.
1.2 - A Solução A solução será dividida em três etapas: Oracle 9i Fundamental
23
Projeto Conceitual
Inicialmente são identificadas entidades, relacionamentos e atributos. Não existe preocupação com eventuais limitações de hardware e de software. O resultado desta etapa é o Modelo de Entidades e Relacionamentos (M.E.R.).
Projeto Lógico
Nesta fase identificam-se as tabelas físicas do futuro Banco de Dados. Levam-se em conta as regras de normalização para que não haja redundâncias na montagem final.
Projeto Físico
Consiste na implementação do Banco em Oracle, que será feito ao longo do livro.
1.2.1 - Projeto Conceitual Analisando o problema, vê-se claramente a presença de três entidades: Alunos, Instrutores e Cursos, cujos atributos poderiam ser os listados em seguida: Entidade
Atributos
Alunos
Matrícula, Nome, Telefone, Endereço, UF
Instrutores
Nome, Telefone, Data admissão
Cursos
Nome, Carga horária, Preço, Pré-Requisitos
Vê-se ainda que o relacionamento entre um aluno e um curso é a Turma, o mesmo, aliás, entre instrutor e curso. Um atributo do relacionamento Aluno-Turma poderia ser sua nota. As cardinalidades seriam as seguintes: Alunos x Turmas: N:N Cursos x Turmas: 1:N Instrutores x Turmas: 1:N O resultado final poderia ser este:
Oracle 9i Fundamental
24
1.2.2 - Projeto Lógico Como já foi dito, nesta etapa são especificadas as tabelas físicas, com as respectivas chaves, do Banco de Dados e são resolvidos problemas referentes à normalização. Infelizmente não é possível implementar relacionamentos muitos-paramuitos, assim haverá mais uma tabela: AlunosTurmas, ou melhor, Histórico: Tabela
Campos
Alunos
Matrícula, Nome, Telefone, Endereço, UF
Histórico
Código Turma, Matrícula, Nota
Turmas
Código Turma, Sala, Código Instrutor, Código Curso
Cursos
Código Curso, Nome, Carga horária, Preço, Pré-requisito
Instrutores
Código Instrutor, Nome, Telefone, Data admissão
Observação Os campos em negrito representam as chaves primárias. Como era esperado, todos os relacionamentos têm a cardinalidade umpara-muitos. Na próxima etapa, o Projeto Físico, serão criadas as tabelas reais, levandose em consideração os tipos e tamanhos permitidos pelo Sistema Gerenciador de Banco de Dados Relacionais (SGBDR), no caso, o Oracle.
1.3 - SQL Toda interação com o Oracle acontece, em última análise, via SQL. Trata-se de uma linguagem cujos comandos dividem-se em três categorias: Oracle 9i Fundamental
25
• • •
DML (Data Manipulation Language); DDL (Data Definition Language); DCL (Data Control Language).
Ao contrário de linguagens ditas procedurais (COBOL, Pascal, Basic, etc.), a SQL permite especificar o que deve ser feito em vez do como. Por exemplo, o trecho apresentado em seguida, escrito em uma linguagem procedural qualquer, percorreria todos os registros de uma tabela: Inicio Enquanto não-fim (Tabela) Leia Registro Avance Fim-Enquanto Fim
Já em SQL, teríamos apenas um comando: select * from Tabela
A título de exemplo, a relação seguinte explica alguns comandos SQL: Comando
Descrição
Tipo
select
Recupera dados de uma ou mais tabelas. É o comando mais utilizado da SQL.
DML
insert update delete
Servem para incluir, alterar e eliminar linhas de uma tabela respectivamente.
DML
commit rollback
Responsáveis pelo controle de transações, permitem que o usuário desfaça (ROLLBACK) ou confirme (COMMIT) alterações em tabelas.
DML
create alter drop
Úteis para definir, alterar e remover estruturas do Banco de Dados.
DDL
grant revoke
Permitem remover direitos de acesso dos usuários do Banco de Dados e seus componentes, ou concedê-los.
DCL
Oracle 9i Fundamental
26
EXERCÍCIOS 1. Na tabela seguinte numere a terceira coluna para que os termos que estão na segunda sejam explicados na quarta coluna:
Seu Número
Número
Termo
Definição
1
Banco de Dados
Sinônimo de Atributo, representa um tipo de informação.
2
Tabela
Campo que identifica univocamente cada registro.
3
Campo
Utilizado para unir duas tabelas que tenham um campo em comum. Uma fornece sua Chave Primária e a outra, uma Chave Estrangeira.
4
Chave Primária
Mecanismo que permite visualizar dados que estejam em tabelas diferentes.
5
Chave Estrangeira
"Sistema de armazenamento de dados baseado em computador, cujo objetivo global é registrar e manter informação considerada significativa à organização" [Date].
6
Registro
Depósito de dados em forma matricial em que as linhas representam registros e as colunas, campos.
7
Relacionamento
Linguagem de manipulação de dados.
8
Visão
Campo idêntico a uma Chave Primária em outra tabela.
9
SQL
O mesmo que tupla. Imaginando que uma tabela fosse um conjunto, então seriam os elementos desse conjunto.
Observação [Date] refere-se a C.J. Date; a frase em questão encontra-se no livro "Introdução a Sistemas de Bancos de Dados", página 26, Editora Campus. Oracle 9i Fundamental
27
Capítulo 2 – TABELAS OBJETIVOS • • • • • •
Realizar conexões ao Servidor; Criar tabelas, levando em consideração nomes de campos, tipos e constraints; Utilizar os primeiros comandos da ferramenta SQL*Plus Worksheet; Alterar tabelas; Eliminar tabelas; Alimentar tabelas com dados.
ARQUIVOS NECESSÁRIOS • •
Monta_Tabela_Instrutores.sql; Monta_Tabelas.sql.
PRÉ-REQUISITOS • • • • •
Noções de Modelagem de Dados; Definir entidade, atributo, relacionamento; Compreender o papel da Normalização no Projeto de um Banco de Dados; Identificar as diferentes etapas prévias à construção de um Banco de Dados; Conhecer conceitos básicos, tais como: Banco de Dados, Tabela, Campo, Registro, Chave Primária, Chave Estrangeira e Relacionamento.
TEORIA 2.1 - Conexão Para que seja possível trabalhar com Oracle, é preciso, antes de tudo, realizar uma conexão. Ela pode ser feita com inúmeras ferramentas, por exemplo, SQL*Plus Worksheet, utilizada ao longo do livro.
Oracle 9i Fundamental
28
Em ambientes gráficos, como Windows 98, NT ou 2000, segue-se um caminho de menus, tal como: Start, Programs, Oracle – OraHome92, Application Development, SQL*Plus Worksheet3. Será mostrada a caixa de diálogo seguinte:
Atenção
No momento dessa conexão saiba que já existe um Banco de Dados (conhecido no Cliente como Serviço) e ele está pronto para ser utilizado. Futuramente, nos capítulos de Administração de Bancos de Dados (18 em diante), você aprenderá como criar novos Bancos de Dados e disponibilizá-los para uso.
Em ambientes não gráficos deve-se utilizar outra ferramenta, a SQL*Plus, cuja ativação seria: sqlplus usuário/senha@banco
Em que usuário, senha e banco são fornecidos pelo Administrador (DBA).
2.2 - Criação de Tabelas Uma vez realizada a conexão, pode-se começar a interagir com o OracleServer via comandos SQL. Por exemplo, a criação das tabelas do estudo de caso será feita pelo comando create table cuja sintaxe simplificada é mostrada em seguida:
3
A localização das ferramentas pode variar de uma instalação para outra. Ao longo deste livro, assumiremos a instalação padrão do Oracle 9i sob Windows 2000 Server.
Oracle 9i Fundamental
29
CREATE TABLE [schema.]tabela (coluna1 tipo_de_dado [DEFAULT expressão] [constraint_coluna], ... (colunaN tipo_de_dado [DEFAULT expressão] [constraint_coluna], [constraint_tabela] );
Os colchetes representam cláusulas opcionais. A tabela seguinte explica a sintaxe do comando: Opções Schema Tabela
Coluna
Tipo_de_ dado
Expressão
Constraint_ coluna Constraint_ tabela
Descrição Representa o proprietário da tabela. Quando omitido, assume-se que a tabela pertencerá ao usuário corrente. Nome da tabela a ser criada. Nome da coluna (campo). Deve iniciar por uma letra; pode ter no máximo 30 caracteres (A-Z, a-z, 0-9, underscore e $) e também não podem ser palavras reservadas do Oracle. Podem existir até inconcebíveis mil colunas. Tamanho e tipo de dado da coluna. Veja, ainda neste capítulo, uma descrição dos tipos possíveis. Especifica um valor predefinido para a coluna. Utilizado para evitar NULL quando uma coluna for omitida em um comando INSERT (inserção de dados). Pode ser um literal, uma expressão, funções SQL, tais como: SYSDATE (data corrente) ou USER (usuário corrente), mas não pode ser utilizado o nome de outra coluna ou pseudocolunas geradas por Sequences (NEXTVAL ou CURRVAL)4. Especifica a restrição de integridade para uma coluna, como, por exemplo, valores que podem ser armazenados. Recomenda-se que tenha nome. Restrição de integridade como parte da definição de uma tabela. Utilizada para definir chaves compostas. Também aconselha-se denominá-la.
Atenção Para que você possa criar uma tabela, alguém, geralmente o DBA, deve ter lhe dado o direito de criação de tabelas.
2.2.1 - Tipos de Dados Cada campo em uma tabela deve possuir um tipo previamente estabelecido. Por tipo entende-se um domínio de valores que o campo pode conter. A tabela seguinte explicita os tipos de dados mais importantes utilizados pelo Oracle-Server: 4
Sequences serão vistas adiante, no capítulo 6.
Oracle 9i Fundamental
30
Tipo Char (n)
Varchar2 (n)
Clob
Long
Blob
Raw e Long raw
Number (p,e)
Date
Timestamp
Interval Year (p) to month
Interval Day (dp) to second (sp)
Descrição Cadeia de caracteres com tamanho fixo n. O default é 1 e o máximo, 2.000. Cadeia contendo caracteres de tamanho variável com o máximo de n, em que n pode ter o valor de até 4.000. Para que dois campos desse tipo sejam consideradas iguais, elas devem possuir, além do mesmo conteúdo, o mesmo tamanho. Significa Character Long Object. Permite armazenar extensas cadeias con-tendo caracteres de tamanho variável com o máximo de 4 gigabytes. Existem funções especiais que manipulam campos deste tipo. Mais detalhes no Capítulo 15, Packages. Antigo mecanismo que permitia armazenar longas cadeias contendo caracteres de tamanho variável com o máximo de 2 gigabytes. Só pode existir um campo desse tipo por tabela. Um campo deste tipo pode ser substituído por outro do tipo CLOB. Significa Binary Long Object. Permite armazenar extensa cadeia contendo dados binários (não são interpretados pelo Oracle, como, por exemplo, sons, imagens, etc.). Possuem tamanho variável com o máximo de 4 gigabytes. Para manipulá-los, devemse utilizar funções especiais. Mais detalhes no Capítulo 15, Packages. Quando não existia o tipo BLOB, eram utilizados para armazenar dados binários. Limites raw: 2.000 bytes; long raw: 2.GB Valores numéricos em que p indica a precisão (máximo de 38) e indica a escala (número de casas decimais) que varia de –84 a +127. Por exemplo, number(5,2) especifica um número na faixa entre -999,99 e +999,99. Armazena data e hora, incluindo século, ano, mês, dia, hora, minuto e se-gundo. Intervalo: 1/1/4712 a.C. até 31/12/9999. Campos deste tipo ocupam 7 bytes. Permite armazenar datas/horas com maior precisão (máxima: 9, default: 6). Por exemplo, caso seja necessário especificar milésimos de segundo, a precisão deve ser 3. Armazenam intervalos de tempo em anos/meses. P representa a quan-tidade dígitos para o ano (possíveis: 0 a 9; default: 2). Intervalos podem ser obtidos, por exemplo, ao subtrair uma data de outra. Armazenam intervalos de tempo em dias, horas, minutos e segundos. DP representa a quantidade de dígitos para o dia (possíveis: 0 a 9; default: 2). SP representa a quantidade de dígitos para o segundo (possíveis: 0 a 9; default: 6).
Oracle 9i Fundamental
31
2.2.2 - Constraints Um constraint ou restrição representa um mecanismo capaz de implementar controles que garantam a consistência dos dados (Integridade de dados e refe-rencial). Pode ser definido tanto em nível de coluna (afeta apenas um campo) como em nível de tabela (afeta todos os campos). Uma alternativa a esses controles é a utilização de Triggers que apresentam performance menor, mas oferecem toda a flexibilidade de uma linguagem de programação (PL/SQL)5. A tabela seguinte mostra as restrições. Logo após, exemplos revelam como aplicá-las. Nome
Uso
Null
Unique
Check
Primary key Foreign key
Informa se o campo em questão pode receber valores nulos. Caso não possa, deve ser precedido pela palavra not. Indica que os valores na coluna, ou conjunto de colunas em questão, não podem ser repetidos. Cria um índice6 automaticamente. Determina uma regra de validação, isto é, especifica os valores que uma coluna pode assumir. Em nível de campo, somente pode fazer referência ao próprio campo que está sendo trabalhado. Já em nível de tabela, pode referenciar várias colunas. Identifica a Chave Primária da tabela. Também cria um índice automaticamente. Identifica uma Chave Estrangeira da tabela. Implementada pela cláusula references.
Primeiro exemplo: Criação da tabela Instrutores7 create table instrutores (cod_instrutor number(3) constraint instrutores_pk primary key, nome_instrutor varchar2(30) constraint instrutores_nome_nu not null, tel_instrutor varchar2(10), admissao date default sysdate);
Observações •
5 6 7
A tabela recém-criada possui quatro campos (cod_instrutor, nome_instrutor, tel_instrutor e admissao);
O assunto triggers será visto no capítulo 16. Índices serão estudados nos capítulos 6 e 23. O código apresentado em seguida Monta_Tabela_Instrutores.sql.
encontra-se
Oracle 9i Fundamental
no
Script
32
• • •
•
Os dois primeiros campos têm restrição. Note a convenção utilizada no sufixo (PK para Primary Key e NU para Not Null); O campo admissao apresenta um valor default: a data atual; Estando o SQL*Plus Worksheet aberto, uma vez concluída a digitação, executa-se o comando anterior, pressionando a tecla F5 ou clicando no botão Executar, presente na barra de ferramentas à esquerda; Todo comando SQL deve ser finalizado por ponto-e-vírgula;
A digitação do comando pode ser feita opcionalmente em um editor externo. Para ativar o arquivo gerado, utilize o comando start. Por exemplo: start G:\LivroO9i\Scripts\ParteI\Monta_Tabela_Instrutores.sql
Também é possível abrir diretamente o arquivo contendo comandos e executá-los. Utilize o comando Arquivo, Abrir do SQL*Plus Worksheet. O Comando start pertence ao SQL*Plus Worksheet e pode ser abreviado como @. Para comprovar a criação da tabela, deve ser usado o comando describe do SQL*Plus Worksheet. Este comando pode ser abreviado como desc. describe instrutores Nome ----------------------------------------COD_INSTRUTOR NOME_INSTRUTOR TEL_INSTRUTOR ADMISSAO
Nulo? Tipo -------- --------------------------NOT NULL NUMBER(3) NOT NULL VARCHAR2(30) VARCHAR2(10) DATE
O SQL*Plus Worksheet trabalha com um buffer em que fica armazenado o histórico de comandos emitidos. Para acessá-lo, ative o comando Folha de Trabalho, Histórico de Comandos:
Oracle 9i Fundamental
33
Segundo exemplo: Criação da tabela Alunos A próxima criação de tabela traz exemplo de regra de validação (constraint check): create table alunos (matricula number(3) constraint alunos_pk primary key, nome_aluno varchar2(30) constraint alunos_nome_nu not null, tel_aluno varchar2(10), endereco_aluno varchar2(30), cidade_aluno varchar2(20) default 'Rio de Janeiro', uf char(2) default 'RJ' constraint alunos_uf_ch check (uf in ('SP', 'MG', 'RJ', 'ES')) );
Observações • • •
Não podem existir dois constraints homônimos; Evite usar nomes com palavras acentuadas (matrícula, endereço); A restrição check serve para qualquer regra de validação. Por exemplo, caso fosse preciso restringir os valores no campo nota da tabela Historico: ... check (nota > 0), ...
Terceiro exemplo: Criação da tabela Turmas A próxima criação de tabela traz exemplo de referência (constraint foreign key): create table turmas (cod_turma number(3) constraint turmas_pk primary key, cod_curso constraint turmas_curso_fk references cursos(cod_curso), cod_instrutor constraint turmas_instrutor_fk references instrutores(cod_instrutor), sala number(2) );
Observações •
•
•
Antes de criar a tabela apresentada anteriormente, outra já deve ter sido construída: CURSOS. Se preferir, extraia o comando que cria essa tabela do arquivo Monta_Tabelas.sql; A cláusula references informa que a tabela corrente estará relacionada com a mencionada na forma de 1 (mencionada) para N (corrente). O campo refe-renciado deve ser chave primária (neste caso, pode ser omitido) ou possuir restrição unique e ser do mesmo tipo do campo corrente; Note a impossibilidade da criação de um relacionamento N:N. Já o 1:1 deve ser controlado via programação (Triggers). Oracle 9i Fundamental
34
Quarto exemplo: Criação da tabela Historico A próxima tabela possui um constraint em nível de tabela (especificação da chave primária composta) e duas chaves estrangeiras: create table historico (cod_turma constraint historico_turma_fk references turmas (cod_turma), matricula constraint historico_aluno_fk references alunos (matricula), nota number (7,2), constraint historico_pk primary key (cod_turma, matricula));
Observações •
• •
Para que esta criação tenha sucesso, já devem existir as tabelas TURMAS e ALUNOS. Se elas ainda não existirem, obtenha os comandos de criação a partir do Script Monta_Tabelas.sql; Constraints em nível de tabela não podem ser not null; Como as chaves estrangeiras devem ser de mesmo tipo e tamanho das chaves primárias equivalentes, não é preciso especificar os tipos desses campos.
2.3 - Alteração de Tabelas Para alterar a estrutura de uma tabela, deve-se utilizar o comando alter table. Por alterar, entende-se:
• • • •
Criar, alterar ou eliminar colunas; Renomear a tabela; Criar ou eliminar constraints; Habilitar ou desabilitar constraints.
A sintaxe simplificada é a seguinte: alter table [schema.]tabela [add (coluna tipo_de_dado [default expressão] [constraint_coluna],...)] [modify (coluna tipo_de_dado [default expressão] [constraint_coluna], ...)] [rename to novo_nome_tabela] [add constraint_coluna/constraint_tabela] [drop constraint_coluna/constraint_tabela [cascade]] [enable constraint_coluna/constraint_tabela] [disable constraint_coluna/constraint_tabela];
Oracle 9i Fundamental
35
Primeiro exemplo: Inserção da coluna de endereços alter table instrutores add endereco varchar2(40);
Segundo exemplo: Alteração da coluna de endereços alter table instrutores modify endereco varchar2(60);
Terceiro exemplo: Exclusão da coluna de endereços alter table instrutores drop column endereco;
Atenção Tenha muito cuidado ao emitir um comando que exclua uma coluna! Lembre-se que os dados nela contidos TAMBÉM serão eliminados.
Quarto exemplo: Inserção da restrição para notas alter table historico add constraint historico_nota_ch check (nota >=0 and nota 30 order by carga_horaria desc; NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Fundamentos da Modelagem de Dados 40 Introdução à Lógica de Programação 32 Oracle: SQLPlus e SQL 32
Note que a ordem das cláusulas (primeiro where, depois order by) deve ser obedecida. A cláusula where apresenta um operador relacional. Como esse (>) existem outros: Operador
Descrição
=
Igual
Diferente
>
Maior
<
Menor
>=
Maior igual
ou
= 30 and carga_horaria to_date('31-1-1998', 'dd-mm-yyyy'); COD_INSTRUTOR ------------3 7 9 10
NOME_INSTRUTOR TEL_INSTRU ADMISSAO ------------------------------ ---------- -------Augusto Lemos Vega 722-1300 12/11/98 Beatriz Bellatrix 18/09/98 Joana Aldebaran 06/09/01 Matias Agena 06/09/01
Observe que a data fornecida na função to_date deve obedecer ao formato fornecido DD-MM-YYYY, a não ser que seja especificado outro: select * from instrutores where admissao > to_date('9-1-1998','mm-dd-yyyy');
3.4.4.1 - Processamento Condicional A função nvl recém-mostrada oferece, de certa forma, processamento condicional. Entretanto, problemas mais complexos que exijam tratamento de várias hipóteses requerem a utilização da função case. Ela pode ser empregada de duas formas: testando várias expressões lógicas ou avaliando apenas uma. O exemplo seguinte avalia duas expressões lógicas e ainda oferece uma terceira possibilidade, quando as duas anteriores resultarem falsas: select nome_curso Curso, preco, case when preco < 400 then 'Barato' when preco > 900 then 'Caro' else 'Médio' end Classificação from cursos;
E a saída: CURSO PRECO CLASSI ---------------------------------------- ---------- -----Introdução à Lógica de Programação 800 Médio Fundamentos da Modelagem de Dados 950 Caro Redes I 0 Barato Introdução a Sistemas Operacionais 0 Barato Análise Orientada por Objetos 0 Barato Delphi: Recursos Básicos 400 Médio Delphi: Acesso a Bancos de Dados 400 Médio Oracle: SQLPlus e SQL 750 Médio Oracle: PL/SQL 750 Médio Redes II 0 Barato 10 linhas selecionadas.
3.4.5 - Funções de Grupo Finalmente, existem as funções de grupo que, ao contrário das outras, afetam várias linhas. Nesta categoria estão aquelas que contam, calculam média, acham um valor máximo, etc. Com estas funções freqüentemente
Oracle 9i Fundamental
60
utilizam-se as cláusulas group by e having para agrupar linhas e aplicar filtros a grupos respectivamente. Algumas representantes: Função
Descrição
avg (coluna)
Média dos valores de uma coluna.
Count (coluna)
Total de linhas selecionadas.
max (coluna)
Valor máximo de uma coluna.
min (coluna)
Valor mínimo de uma coluna.
sum (coluna)
Soma dos coluna.
valores
de
uma
Todas as funções desconsideram valores nulos, exceto count, quando o argumento for *.
Primeiro exemplo: count select count(carga_horaria) from cursos; COUNT(CARGA_HORARIA) -------------------6 select count(*) from cursos; COUNT(*) --------10
Segundo exemplo: sum select nome_curso, sum(preco) Arrecadado from cursos c inner join turmas t using(cod_curso) inner join historico h using(cod_turma) group by nome_curso order by 2 desc; NOME_CURSO ARRECADADO ---------------------------------------- ---------Introdução à Lógica de Programação 24000 Fundamentos da Modelagem de Dados 19000 Delphi: Acesso a Bancos de Dados 4000 Análise Orientada por Objetos 0 Introdução a Sistemas Operacionais 0 Redes I 0 6 rows selected.
Perceba que qualquer coluna não especificada na cláusula group by deve constar associada a uma função de grupo.
Terceiro exemplo: Limitando valores Oracle 9i Fundamental
61
select nome_curso, sum(preco) Arrecadado from cursos c inner join turmas t using(cod_curso) inner join historico h using(cod_turma) group by nome_curso having sum(preco) > 10000 order by 2 desc; NOME_CURSO ARRECADADO ---------------------------------------- ---------Introdução à Lógica de Programação 24000 Fundamentos da Modelagem de Dados 19000
Em caso de dúvidas, deve-se recorrer à documentação Oracle instalada ou, melhor, na Internet. Por exemplo, supondo a necessidade de localizar mais detalhes sobre a cláusula group by, deve-se fazer o seguinte10: Acesse o site http://technet.oracle.com. Se você ainda não for usuário cadastrado, registre-se após clicar em Membership; Uma vez cadastrado, de volta à página inicial, clique em Documentation; Dentre os quatro grupos exibidos, selecione Oracle 9i Database; Neste ponto você deve selecionar a documentação específica do seu Sistema Operacional, ou ativar a genérica clicando em HTML ou PDF sob General Documentation; Agora há vários caminhos possíveis. Por exemplo, você poderia clicar em books; Surgirá uma lista de "livros". O assunto que estamos procurando está no livro SQL Reference, como, aliás, a grande maioria dos assuntos tratados nos capítulos um a sete. Sendo assim, localize o tal livro e clique em Search; Digite group by. Para otimizar a busca, selecione Only Examples na Caixa de Combinação Display Topics. Serão mostrados vários tópicos. Localize GROUP BY Examples – NOWAIT | WAIT.
3.5 - Operadores de Conjunto Comumente uma tabela é vista como um conjunto. Inclusive, muito do Modelo Relacional foi extraído da teoria de conjuntos. Sendo assim, é possível relacionar dados em tabelas diferentes por meio dos operadores de união, interseção e diferença. Os operadores são:
10
Operador
Descrição
Union
Retorna a união entre dois conjuntos de dados com estruturas semelhantes.
Leve em consideração que páginas de Internet são entidades voláteis, portanto sujeitas a mudanças sem prévio aviso. O roteiro ora descrito foi executado com sucesso em janeiro de 2002.
Oracle 9i Fundamental
62
Operador
Descrição
Intersect
Retorna os dados que são comuns a dois conjuntos de dados.
Minus
Representa o que um conjunto tem e ou outro não.
Para os exemplos seguintes, suponha que tenha sido criada uma tabela de cursos descontinuada11: select cod_curso, nome_curso, carga_horaria from cursos_velhos; COD_CURSO --------101 102 103 104 105 106 107 108 109 110
NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Windows 3.1: Recursos Básicos 16 Windows 3.1: Recursos Avançados 16 Word 2.0: Recursos Básicos Word 2.0: Recursos Avançados Excel 4.0: Recursos Básicos Excel 4.0: Recursos Avançados Access 1.0: Recursos Avançados 24 Corel Draw 3.0 24 Lotus 1-2-3 for Windows 16 Delphi: Recursos Básicos 24
Primeiro exemplo: Mostrar os cursos básicos (novos e velhos) sem repetição
select nome_curso, carga_horaria from cursos where upper(nome_curso) like '%BÁSICOS%' union select nome_curso, carga_horaria from cursos_velhos where upper(nome_curso) like '%BÁSICOS%' order by 1; NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Delphi: Recursos Básicos 24 Excel 4.0: Recursos Básicos Windows 3.1: Recursos Básicos 16 Word 2.0: Recursos Básicos
Observe que as tabelas que estão sendo "unidas" devem ter a mesma estrutura.
Segundo exemplo: Mostrar os cursos básicos (novos e velhos) com repetição select nome_curso, carga_horaria from cursos where upper(nome_curso) like '%BÁSICOS%' union all select nome_curso, carga_horaria from cursos_velhos where upper(nome_curso) like '%BÁSICOS%' order by 1; 11
A Tabela cursos_velhos Monta_Cursos_Velhos.SQL.
pode
ser
montada
e
alimentada
Oracle 9i Fundamental
a
partir
do
script
63
NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Delphi: Recursos Básicos 24 Delphi: Recursos Básicos 24 Excel 4.0: Recursos Básicos Windows 3.1: Recursos Básicos 16 Word 2.0: Recursos Básicos
Terceiro exemplo: Mostrar os cursos básicos (novos e velhos) comuns às tabelas select nome_curso, carga_horaria from cursos where upper(nome_curso) like '%BÁSICOS%' intersect select nome_curso, carga_horaria from cursos_velhos where upper(nome_curso) like '%BÁSICOS%'; NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Delphi: Recursos Básicos 24
Quarto exemplo: Mostrar os cursos velhos que não estão na primeira tabela select nome_curso, carga_horaria from cursos_velhos where upper(nome_curso) like '%BÁSICOS%' minus select nome_curso, carga_horaria from cursos where upper(nome_curso) like '%BÁSICOS%' order by 1; NOME_CURSO CARGA_HORARIA ----------------------------------- ------------Excel 4.0: Recursos Básicos Windows 3.1: Recursos Básicos 16 Word 2.0: Recursos Básicos
3.6 - Dicionário de Dados O Oracle Data Dictionary consiste em um conjunto de tabelas e views12, também chamadas system tables ou metadados, que proporcionam um acesso apenas de leitura a todos os usuários de um Banco de Dados. O Dicionário de Dados é alterado e mantido pelo Oracle. O proprietário de todas essas tabelas e visões é o usuário SYS. Essas tabelas e views iniciam-se por vários prefixos, entretanto os mais impor-tantes são:
12
Prefixo
Descrição
USER_
Contém os objetos dos quais o usuário é proprietário. Por exemplo: user_objects, user_tables, user_constraints, user_tab_columns, user_resource_limits.
Por view entende-se uma visão envolvendo vários campos de várias tabelas. A criação de views será vista mais adiante.
Oracle 9i Fundamental
64
Prefixo
Descrição Existem 190 na versão 9.0 e 214 na 9.2. Objetos públicos que podem ser vistos por todos. Exemplos: all_objects, all_tables, all_constraints, all_tab_columns. Existem 172 na versão 9.0 e 210
ALL_
na 9.2. DBA_
Permite que os usuários com o privilégio DBA13 acessem qualquer objeto do Banco de Dados. Existem 244 na versão 9.0 e 297 na 9.2.
V$
Possui informações sobre a performance do Servidor. Inicialmente disponível somente ao DBA. Existem 230 na versão 9.0 e 265 na 9.2.
Além destes, existem outros objetos importantes: Dictionary (dict)
Mostra todas as tabelas e visões do Dicionário de Dados.
Tab, Cat
Exibem as tabelas do usuário corrente.
Col
Colunas das tabelas do usuário corrente.
Primeiro exemplo desc user_constraints Nome ----------------------------------------OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION R_OWNER R_CONSTRAINT_NAME DELETE_RULE STATUS DEFERRABLE DEFERRED VALIDATED GENERATED BAD RELY LAST_CHANGE INDEX_OWNER INDEX_NAME INVALID VIEW_RELATED
Nulo? Tipo -------- --------------------------NOT NULL VARCHAR2(30) NOT NULL VARCHAR2(30) VARCHAR2(1) NOT NULL VARCHAR2(30) LONG VARCHAR2(30) VARCHAR2(30) VARCHAR2(9) VARCHAR2(8) VARCHAR2(14) VARCHAR2(9) VARCHAR2(13) VARCHAR2(14) VARCHAR2(3) VARCHAR2(4) DATE VARCHAR2(30) VARCHAR2(30) VARCHAR2(7) VARCHAR2(14)
select table_name, constraint_name, constraint_type from user_constraints order by 1,2; TABLE_NAME -------------------------ALUNOS ALUNOS ALUNOS 13
CONSTRAINT_NAME -----------------------------ALUNOS_NOME_NU ALUNOS_PK ALUNOS_UF_CH
C C P C
A concessão de privilégios a um usuário será analisada no capítulo 24.
Oracle 9i Fundamental
65
CURSOS CURSOS CURSOS CURSOS_VELHOS CURSOS_VELHOS CURSOS_VELHOS HISTORICO HISTORICO HISTORICO INSTRUTORES INSTRUTORES TURMAS TURMAS TURMAS
CURSOS_NOME_NNU CURSOS_PK SYS_C00904 CURSOS_VELHOS_NOME_NNU CURSOS_VELHOS_PK SYS_C00934 HISTORICO_ALUNO_FK HISTORICO_PK HISTORICO_TURMA_FK INSTRUTORES_NOME_NU INSTRUTORES_PK TURMAS_CURSO_FK TURMAS_INSTRUTOR_FK TURMAS_PK
Oracle 9i Fundamental
C P U C P U R P R C P R R P
66
EXERCÍCIOS 1. Ligue seu equipamento, realize a conexão necessária para trabalhar com o Oracle-Server, verifique as tabelas do controle acadêmico e alimente Histórico. • Execute o script Cria_Alimenta_Historico.sql e depois execute a procedure criada. Por exemplo: exec AlimentaHistorico(10,10) preencherá dez turmas com dez alunos. 2. Mostre todos os alunos. 3. Mostre nome e telefone dos alunos cujos nomes comecem por A. 4. Mostre os alunos ordenados por nome. 5. Cursos com respectivas arrecadações. 6. Alunos que cursaram a turma 1. 7. Nomes de alunos com respectivos cursos assistidos. • Elimine linhas duplicadas por meio da cláusula DISTINCT. 8. Quantos alunos houve por curso? 9. Arrecadação média por turma. 10. Abra o script Saida_Nao_Formatada.sql e melhore a apresentação dos nomes (em maiúsculas), números (formato moeda), datas (d/m/a) e valores nulos (algum texto explicativo). Não se esqueça de criar títulos para as colunas. select cod_turma, nome_instrutor, nome_curso, carga_horaria*preco_hora_instrutor, admissao from instrutores i, cursos c, turmas t where i.cod_instrutor = t.cod_instrutor and t.cod_curso = c.cod_curso order by cod_turma;
Oracle 9i Fundamental
67
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Mostrar todos os registros e campos de uma tabela
Select * from tabela;
Filtrar campos
Select campo1, campo2,...,campoN from tabela; select campo1, campo2,...,campoN from tabela where condição
Filtrar linhas
Filtrar valores nulos
A condição pode envolver operadores relacionais, aritméticos, lógicos ou miscelâneos (between, like, in). select campo1, campo2,...,campoN from tabela where campo is null;
Cláusula ORDER BY. Exemplo: Ordenar
select * from cursos where carga_horaria > 24 order by nome_curso;
Cláusula GROUP BY com funções de grupo. Exemplo:
Agrupar dados
select carga_horaria, count(cod_curso) from cursos group by carga_horaria;
Quaisquer campos mencionados na lista de campos, que não estejam envolvidos com funções de grupo, devem constar na cláusula GROUP BY. Cláusula HAVING. Exemplo: Filtrar dados agrupados
select carga_horaria, count(cod_curso) from cursos group by carga_horaria having count(cod_curso) > 1;
Oracle 9i Fundamental
68
ANOTAÇÕES
Oracle 9i Fundamental
69
Capítulo 4 – ATUALIZAÇÃO DE DADOS OBJETIVOS • • •
Realizar mudanças nos dados previamente armazenados em uma tabela; Excluir linhas; Dominar o conceito de transação.
ARQUIVOS NECESSÁRIOS •
Nenhum
PRÉ-REQUISITOS • • • • • •
Conectar-se ao Servidor via SQL*Plus Worksheet; Criar tabelas (comando CREATE TABLE); Alterar a estrutura de tabelas previamente criadas (comando ALTER TABLE); Eliminar tabelas (comando DROP TABLE); Inserir dados em tabelas (comando INSERT); Consultar dados já armazenados (comando SELECT).
TEORIA 4.1 - Fundamentos Uma vez criadas as tabelas e devidamente alimentadas, é comum existirem ope-rações que alterem registros ou os excluam. Este capítulo detalha os comandos SQL que efetuam tais ações, bem como explica o conceito de transação: conjunto de comandos que são confirmados em grupo. Os comandos vistos neste capítulo são: Comando
Descrição
Update
Atualiza valores de campos em uma ou mais linhas.
delete truncate table
Apaga uma ou mais linhas.
commit
Nenhuma inserção, atualização ou exclusão (com delete) acontece de verdade até que seja emitido este comando, seja de forma
Apaga todas as linhas sem possibilidade de volta.
Oracle 9i Fundamental
70
explícita ou implícita, como veremos adiante. rollback
Desfaz explicitamente os efeitos de um insert, update ou delete.
4.2 - Alteração de Linhas Para alterar valores em linhas de uma tabela, utilizamos o comando update. Sua sintaxe é: UPDATE tabela SET coluna = valor [, coluna = valor ...] [WHERE condição];
Se a cláusula where for omitida, todas as linhas serão alteradas.
Exemplo: Atualização do preço dos cursos de Oracle em 10% update cursos set preco = preco * 1.1 where upper(nome_curso) like 'ORACLE%'; 2 linhas atualizadas.
Não se esqueça de que os dados não foram ainda gravados. Isto somente acontecerá se a transação corrente for encerrada normalmente. Detalhes em 4.4. Observe a praticidade da linguagem SQL. Você imagina como seria uma porção de código procedural que realizasse algo análogo ao exemplo apresentado anterior-mente?
4.3 - Eliminação de Linhas Linhas são eliminadas por meio de dois comandos: delete ou truncate table. Sintaxe do delete: DELETE [FROM] tabela [ WHERE condição];
Se a cláusula where for omitida, todas as linhas serão eliminadas.
Primeiro exemplo: Eliminando as matrículas da turma 10 delete historico where cod_turma = 10; 10 linhas deletadas.
Segundo exemplo: Eliminação frustrada Quando os registros por eliminar têm linhas associadas em outras tabelas, isto é, houver um constraint associado, a eliminação não acontece: Oracle 9i Fundamental
71
delete from cursos; delete from cursos * ERRO na linha 1: ORA-02292: restrição de integridade (MORELLI.TURMAS_CURSO_FK) violada - registro filho localizado
Deve-se frisar que, mesmo que alguns cursos possam ser excluídos (não possuem turmas associadas), a operação como um todo é cancelada. Outro comando para eliminar linhas em uma tabela é o truncate table. Enquanto o delete apenas remove as linhas da tabela, o truncate table remove todas as linhas e libera a área de armazenamento utilizada pela tabela. Este comando não permite rollback (volta).
Terceiro exemplo: Eliminando cursos velhos truncate table cursos_velhos; Tabela truncada. select * from cursos_velhos; não há linhas selecionadas
Resulta impossível aplicar o comando truncate table em tabelas referenciadas por chaves estrangeiras, mesmo que as tabelas relacionadas estejam vazias. Por exemplo, suponha que não existam linhas em HISTORICO; o comando a seguir: Atenção
Truncate table alunos;
provocaria o erro: truncate table alunos * ERRO na linha 1: ORA-02266: chaves exclusiva/primária na tabela referenciadas por chaves externas ativadas
4.4 - Transações Uma transação representa um conjunto de comandos (um ou mais) cujo resultado será gravado de uma vez. Durante uma transação, as linhas afetadas por ela ficam presas, ou locked. Ela se inicia quando se executa o primeiro comando SQL e termina nas seguintes situações: Commit
Comando que grava definitivamente os efeitos dos comandos da transa-ção (insert, delete, update).
Rollback
Comando que desconsidera os efeitos dos comandos da transação (insert, delete, update).
Fim sessão
da
Se a sessão for encerrada sem problemas, ocorre um commit implícito, senão há um rollback implícito. Oracle 9i Fundamental
72
Comando DDL ou DCL
Todo comando DDL ou DCL provocam o fim da transação corrente; logo, há um commit implícito. Se houver qualquer problema durante a gravação definitiva, acontece um rollback implícito.
O comando set transaction inicia uma transação com o Banco de Dados que pode ser do tipo Read Only ou Read Write. Ele somente pode ser usado após um commit ou rollback.
Primeiro exemplo: Comando set transaction set transaction read only name 'Tran1';
Uma transação que somente deixe visualizar os dados é muito útil para efeitos de consistência. Imagine um ambiente em que estejam conectados os usuários A, B e C. Caso A deseje emitir um relatório longo, envolvendo tabelas que B e C estejam atualizando, A deve "fotografar" o estado dos dados no início da emissão e desconsiderar os commits que B e C derem. Neste caso, A deve iniciar sua transação com o comando citado. Outra vantagem consiste no maior desempenho obtido nas transações que sejam somente de leitura. Em transações de leitura/gravação, somente um usuário pode alterar uma tabela a cada vez. Enquanto ele não encerrar sua transação, os demais usuários somente podem ver dados como estavam antes da transação modificadora começar. Caso alguém tente emitir um insert, update ou delete em uma tabela que outro está alterando, a sessão ficará em suspenso até que a transação seja encerrada. Quando o comando commit é executado, as alterações nos dados são gravadas no Banco de Dados, os valores anteriores são perdidos e o lock desfeito, podendo então serem acessados os dados por outros usuários.
Segundo exemplo: Commit simples insert into instrutores (cod_instrutor, nome_instrutor) values(11, 'Arquimedes Horáclito'); commit;
E a saída: 1 linha criada. Validação completa.
Quando acontece o comando rollback, as alterações nos dados são descartadas, voltando os dados ao seu estado anterior, o lock também é desfeito e as linhas são liberadas para serem acessadas por outros usuários.
Terceiro exemplo: Duas transações commit;
Oracle 9i Fundamental
73
set transaction read write name 'tran_grava'; insert into instrutores (cod_instrutor, nome_instrutor) values(12, 'Mário Alnilam'); select nome_instrutor from instrutores;
E a saída: Validação completa. Conjunto de transações. 1 linha criada. NOME_INSTRUTOR -----------------------------Maria Carolina Sirio ... Mário Alnilam 12 linhas selecionadas.
Emitindo o comando: rollback;
Saída: Rollback completo. select count(nome_instrutor) from instrutores; COUNT(NOME_INSTRUTOR) --------------------11
O Oracle permite que sejam definidas marcas, denominadas savepoints, na transação corrente, a fim de possibilitar um rollback de apenas partes da transação. Estas marcas são especificadas com a utilização do comando savepoint.
Quarto exemplo: Comando savepoint Inserindo uma linha: insert into instrutores (cod_instrutor, nome_instrutor) values(12, 'Mário Alnilam');
Estabelecendo um savepoint: savepoint inclusao_ok;
Inserindo outra linha: insert into instrutores (cod_instrutor, nome_instrutor) values (13, 'Nair Mintaka');
Confirmando: select nome_instrutor from instrutores; NOME_INSTRUTOR -----------------------------Maria Carolina Sirio ... Mário Alnilam Nair Mintaka
Oracle 9i Fundamental
74
13 linhas selecionadas.
Voltando até o ponto previamente marcado: rollback to inclusao_ok;
Resposta: Rollback completo.
Confirmando: select nome_instrutor from instrutores; NOME_INSTRUTOR -----------------------------Maria Carolina Sírio ... Mário Alnilam 12 linhas selecionadas.
Salvando operações efetuadas: commit;
Terminada a transação, a marca é eliminada. Criando uma marca com nome que já exista, simplesmente acontece uma substituição.
EXERCÍCIOS14 1. Ligue seu equipamento e realize a conexão necessária para trabalhar com o Oracle-Server. 2. Atualize os preços de todos os cursos em 20%. 3. Desfaça o último comando. 4. Comprove por que não é possível eliminar turmas com alunos matriculados. Você saberia a razão? 5. Crie uma tabela qualquer e comprove que a transação corrente foi encerrada. 6. Matricule alguns alunos e encerre a sessão. Comprove se a saída provocou um commit ou rollback. 7. Faça o seguinte teste e anote as conclusões ao final de cada etapa: a. Insira um instrutor; b. Peça que um vizinho liste sua tabela de instrutores. Ele verá o que você vê? c. Emita um commit;
14
Os exercícios apresentados, principalmente a partir do 7, presumem que existem pelo menos dois usuários conectados a uma base comum. Caso isto não ocorra, efeito semelhante pode ser obtido simplesmente abrindo duas sessões de SQLPlus Worksheet.
Oracle 9i Fundamental
75
d. Repita o segundo passo. E agora? Você sabe explicar o motivo da diferença? e. Insira outro instrutor; f. Peça que alguém insira um instrutor em sua tabela. Ele conseguiu? Observe que ele conseguiu inserir, pois a tabela não foi bloqueada por você e sim apenas uma linha. Ele teria uma surpresa se você tivesse emitido um comando update que "trancasse" toda a tabela. g. Emita um rollback. O que seu vizinho vê? 8. Faça outro teste e também anote as conclusões ao final de cada etapa: a. Insira um instrutor; b. Peça que um vizinho insira outro instrutor; c. Peça que o vizinho encerre a transação normalmente. Por que ele não vê o que você vê? d. Emita um commit. E agora? Que conclusões você tira? 9. Neste exercício você compreenderá a diferença entre um constraint deferrable e not deferrable: a. Elimine a restrição que limita as unidades da federação dos alunos: alter table alunos drop constraint
alunos_uf_ch;
b. Recrie a restrição, mas agora deferrable, isto é, a verificação de consistência acontecerá ao final da transação e não ao final do comando, como normal-mente acontece. alter table alunos add constraint alunos_uf_ch check (uf in ('SP', 'MG', 'RJ', 'ES')) deferrable initially deferred;
c. Realize testes que comprovem a mudança anterior. Você imagina alguma situação em que o recurso recém-aprendido será útil? Quem sabe ganhos de performance em ambientes em que a ocorrência de erros seja mínima....
Oracle 9i Fundamental
76
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Atualizar campos de uma tabela
Utilize o comando update. Veja sintaxe e exemplos em 4.2.
Eliminar linhas de uma tabela
Utilize o comando delete. Veja sintaxe e exemplos em 4.3. Eventualmente, podem-se eliminar todos os registros de uma tabela via comando truncate table.
Iniciar uma transação
Basta encerrar a anterior.
Finalizar uma transação, ratificando as mudanças
Utilize o comando commit.
Finalizar uma transação, cancelando as mudanças
Utilize o comando rollback.
Oracle 9i Fundamental
77
ANOTAÇÕES
Oracle 9i Fundamental
78
Capítulo 5 – RELATÓRIOS OBJETIVOS • • •
Melhorar os resultados de consultas no SQL*Plus Worksheet; Trabalhar com variáveis de ambiente e bind variables; Criar scripts que gerem comandos SQL.
ARQUIVOS NECESSÁRIOS •
Nenhum
PRÉ-REQUISITOS • • • • • • • • •
Conectar-se ao Servidor via SQL*Plus Worksheet; Criar tabelas (comando CREATE TABLE); Alterar a estrutura de tabelas previamente criadas (comando ALTER TABLE); Eliminar tabelas (comando DROP TABLE); Inserir dados em tabelas (comando INSERT); Consultar dados já armazenados (comando SELECT); Alterar conteúdos de linhas (comando UPDATE); Eliminar linhas (comandos DELETE e TRUNCATE TABLE); Conhecer o conceito de transação e manipular os comandos relacionados (COMMIT, ROLLBACK).
TEORIA 5.1 - Fundamentos Em arquivos com extensão .sql podem ser inclusos, além da sentença select, comandos SQL*Plus Worksheet para configuração do ambiente, entrada de variáveis, formatação de colunas, títulos, rodapés, etc. Isto permite melhorar bastante a apre-sentação das queries, criando verdadeiros relatórios. Por exemplo, ao longo deste capítulo, você fará o seguinte relatório: Centro Educacional de Volta Grande
Oracle 9i Fundamental
79
CEVOG ARRECADAÇÃO dos CURSOS de INFORMÁTICA
Pág:
1
Curso Turma Arrecadado ---------------------------------------- ----- -----------Delphi: Acesso a bancos de Dados 7 $12,000.00 **************************************** -----------Total $12,000.00 Delphi: Recursos Básicos
12 19
$12,000.00 $12,000.00 -----------$24,000.00
3 9 17 20
$28,500.00 $28,500.00 $28,500.00 $28,500.00 -----------$114,000.00
1 2 6 15
$24,000.00 $24,000.00 $24,000.00 $24,000.00 -----------$96,000.00
11 18
$24,750.00 $24,750.00 -----------$49,500.00
**************************************** Total Fundamentos da Modelagem de Dados
**************************************** Total Introdução à Lógica de Programação
**************************************** Total Oracle: SQL*Plus e SQL **************************************** Total
-----------$295,500.00
Total Geral Usuário : MORELLI
5.2 - Variáveis de Ambiente Por intermédio de algumas variáveis de ambiente, ou sessão, podemos configurar a saída. Todas elas têm seu valor modificado com set e exibido com show. As principais são: Comando
Descrição
colsep "texto"
Define o texto ou caractere que será exibido entre as colunas de uma consulta. O default é " ".
echo {on | off}
A opção off não exibe os comandos do arquivo na tela quando ele for executado. O default é on.
feedback {n | off | on}
Exibe o total de linhas retornadas por uma consulta quando o número de linhas é igual a n ou mais. O default é 6 linhas.
heading {off | on}
Determina se será exibido o cabeçalho das colunas. O default é on.
linesize n
Define o número de caracteres por linha no relatório. O default é 80. O comum é 132.
Oracle 9i Fundamental
80
Comando
Descrição
pagesize n
Determina o número de linhas por página. O default é 24. O comum é 55 ou 60.
pause {on | off | texto}
Permite controlar o scroll da tela, pressionando enter após cada pausa do vídeo. O default é off.
Termout {on | off}
Inibe ou ativa a saída dos comandos na tela.
wrap {on | off}
Indica que, caso a largura de linhas no relatório ultrapasse o tamanho de linesize, elas serão truncadas (off) ou não (on). O default é on.
A sentença show all exibe o valor de todas as variáveis. Deve-se redefinir as variáveis com seu valor original após o término de cada relatório. Lembre-se que não existe um comando para retornar todas as variáveis aos seus valores default, por isso é importante conhecer seu valor anterior ou desconectar-se e conectar-se novamente.
5.3 - Comandos SQL*Plus Worksheet de Formatação 5.3.1 - Column Define cabeçalho, largura e formato de dado para uma coluna do relatório. Sua sintaxe é: column
[ {coluna | alias}
[opções ...] ]
As opções disponíveis são: Opção
Descrição
cle[ar]
Elimina todas as formatações definidas.
for[mat] formato
Define a formatação do dado da coluna, podendo ser: An - largura do campo para os tipos de dado char ou date. 9 - representação numérica com supressão de zeros não signi-ficativos. 0 - representação numérica, forçando a exibição de zeros não significativos. $ - representa o caractere "$" flutuante. . - indica a posição do ponto decimal. , - indica a posição do caractere separador de milhar.
hea[ding] "texto"
Define o cabeçalho para a coluna. A utilização do caractere "|", separando palavras no texto, força a quebra em mais de uma linha.
jus[tify] alinhamento
Define o alinhamento do cabeçalho da coluna (não os dados). Pode ser left, right ou center (l, r, c). Oracle 9i Fundamental
81
Opção
Descrição
noprint | print
Oculta ou mostra uma coluna.
Null "texto"
Especifica um texto para ser exibido em caso de valores NULL.
Truncated
Trunca o valor da coluna quando ela ultrapassar a largura definida.
Wrapped
Continua a exibição da coluna na próxima linha quando ela ultrapas-sar a largura definida.
Observe que vários comandos podem ser abreviados. Assim, em vez de digitar clear, pode-se digitar cle.
Primeiro exemplo: Listagem simples column nome format a30 heading 'Nome' trunc column nome
Saída: COLUMN nome ON HEADING 'Nome' FORMAT a30 truncate column telefone heading 'Telefone | Residencial' column telefone clear column telefone
Saída: SP2-0046: COLUMN 'telefone' não definido select nome_instrutor nome from instrutores order by 1;
Nome -----------------------------Almir Altair Arquimedes Horáclito Augusto Lemos Vega Beatriz Bellatrix Carlos Regulos Joana Aldebaran Leonardo Guimarães Rigel Maria Carolina Sirio Matias Agena Mário Alnilam Mônica Silveira Capela Pedro Paulo Canopo 12 linhas selecionadas.
Segundo exemplo: Listagem numérica column nome format a45 heading 'Nome' trunc column ch justify right format 999 null 'Sem Carga Horária' heading ' **** Carga Horária *****'
Oracle 9i Fundamental
-
82
select nome_curso nome, carga_horaria ch from cursos order by 2 desc; Nome ------------------------------------Redes I Introdução a Sistemas Operacionais Análise Orientada por Objetos Redes II Fundamentos da Modelagem de Dados Introdução à Lógica de Programação Oracle: SQLPlus e SQL Delphi: Recursos Básicos Oracle: PL/SQL Delphi: Acesso a bancos de Dados
**** Carga Horária ***** ------------------------Sem Carga Horária Sem Carga Horária Sem Carga Horária Sem Carga Horária 40 32 32 24 24 24
10 linhas selecionadas.
Perceba o hífen indicando que o comando em questão prosseguirá na linha seguinte.
5.3.2 - Ttitle e Btitle Utiliza-se ttitle para definir o título do relatório, e btitle para o seu rodapé. Eles podem incluir data corrente, usuário e número da página. A sintaxe do btitle é a mesma do ttitle: ttitle [texto ou &variável] [off | on]
Em seguida são listados os comandos que geraram o cabeçalho e o rodapé do relatório exibido no item 5.1: ... ttitle left 'Centro Educacional de Volta Grande' skip left 'CEVOG' right 'Pág: 'format 999 sql.pno skip center 'ARRECADAÇÃO dos CURSOS de INFORMÁTICA' skip center ' '
-
btitle center 'Usuário : ' sql.user ... ttitle off btitle off
5.3.3 - Break e Compute Quando se deseja informar uma quebra com cálculos no relatório, devemse utilizar os comandos break e compute. Deve-se notar que os dados devem ser ordenados pelas quebras. Em seguida são listados os comandos que geraram as quebras e os cálculos do relatório exibido no item 5.1: compute sum label Total of ARRECADADO on CURSO compute sum label "Total Geral" of ARRECADADO on report break on report skip 2 on CURSO skip 2
Oracle 9i Fundamental
83
Observe a presença dos campos ARRECADADO e CURSO no comando select15: select nome_curso CURSO, t.cod_turma TURMA, sum(preco) ARRECADADO from cursos c inner join turmas t using(cod_curso) join historico h on h.cod_turma = t.cod_turma group by nome_curso, t.cod_turma having sum(preco) >0 order by 1,2;
A referência à coluna CURSO no comando break evita que nomes de cursos sejam emitidos várias vezes.
5.4 - Bind Variables Pode-se criar um script contendo uma cláusula where para restringir as linhas que serão exibidas. Para alterar a condição cada vez que for executado o arquivo, utilizam-se as variáveis de substituição (bind variables). Elas podem alterar valores na cláusula where, uma cadeia de caracteres ou ainda nomes de tabelas ou colunas. A utilização deste recurso melhora a performance geral no que diz respeito à compilação do comando. Existem dois comandos para criação de variáveis: define e variable: Comando
Descrição
define variável=valor
Cria uma variável do tipo char e assinala um valor a ela.
define variável
Exibe a variável, seu valor e tipo de dados.
undefine variável
Elimina variável.
define
Exibe todas as variáveis do usuário com valor e tipo de dado.
variable variável tipo
Declara uma variável de um dado tipo.
Primeiro exemplo: Criando variável UF Define uf = RJ
Segundo exemplo: Listando variáveis Define
Saída: DEFINE _SQLPLUS_RELEASE = "900010001" (CHAR) DEFINE _EDITOR = "Notepad" (CHAR) DEFINE _O_VERSION = "Oracle9i Enterprise Edition Release 9.0.1.1.1 - Production With the Partitioning option 15
Propositalmente seguiu-se o padrão SQL-92 em vez do SQL-86.
Oracle 9i Fundamental
84
JServer Release 9.0.1.1.1 - Production" (CHAR) DEFINE _O_RELEASE = "900010101" (CHAR) DEFINE UF = "RJ" (CHAR)
Uma outra forma de listar variáveis: prompt uf
Saída: Uf
Mostrando conteúdo: prompt &preco_minimo
Saída: RJ
Terceiro exemplo: Usando uma variável para listagem parametrizada select count(nome_aluno) from alunos where uf = '&uf'
Saída: antigo 1: select count(nome_aluno) from alunos where uf = '&uf' novo 1: select count(nome_aluno) from alunos where uf = 'RJ' COUNT(NOME_ALUNO) ----------------22
Para evitar a exibição dos valores antigos e novos, utilize a variável de ambiente verify: set verify off select count(nome_aluno) from alunos where uf = '&uf'
Saída: COUNT(NOME_ALUNO) ----------------22 SQL> set verify on
Para retornar ao comportamento padrão, basta atribuir ON à variável de ambiente verify.
Quarto exemplo: Outra forma de declaração de variáveis variable cotacao number exec :cotacao := 2.70 print cotacao
Oracle 9i Fundamental
85
5.5 - Geração de SQL Uma das grandes aplicações dos relatórios com SQL*Plus Worksheet consiste em montar scripts que contenham comandos SQL que gerem outros comandos SQL. Isto resulta muito útil quando for preciso automatizar tarefas.
Primeiro exemplo: Gerando describes set echo off set pagesize set linesize set feedback spool x.list select 'desc spool off
0 100 off ' || table_name from cat;
set pagesize 20 set feedback on set echo on start x.list
O arquivo x.list conterá tantos describes quantas forem as tabelas do usuário corrente. O efeito deste script é mostrar as estruturas de todas as tabelas.
Segundo exemplo: Gerando inserts select 'insert into instrutores', 'values ('|| cod_instrutor || ',' || '''' || nome_instrutor || '''' || ');' from instrutores;
tem como resultado: 'INSERTINTOINSTRUTORES' 'VALUES('||COD_INSTRUTOR||','||''''||NOME_INSTRUTOR||''''||');' ----------------------- ---------------------------------------------insert into instrutores values (1,'Maria Carolina Sírio'); insert into instrutores values (2,'Pedro Paulo Canopo'); insert into instrutores values (3,'Augusto Lemos Vega'); insert into instrutores values (4,'Mônica Silveira Capela'); insert into instrutores values (5,'Almir Altair'); insert into instrutores values (6,'Leonardo Guimarães Rigel'); insert into instrutores values (7,'Beatriz Bellatrix'); insert into instrutores values (8,'Carlos Regulos'); insert into instrutores values (9,'Joana Aldebaran'); insert into instrutores values (10,'Matias Agena'); insert into instrutores values (11,'Arquimedes Horáclito'); insert into instrutores values (12,'Mário Alnilam');
Este script apresentado seria muito útil para preencher uma tabela vazia com a mesma estrutura de INSTRUTORES.
Terceiro exemplo: Gerando selects select 'select sum(data_length) from cols where table_name = ' || '''' || table_name || '''' || ';' from cat;
Oracle 9i Fundamental
86
resultado: select select select select select
sum(data_length) sum(data_length) sum(data_length) sum(data_length) sum(data_length)
from from from from from
cols cols cols cols cols
where where where where where
table_name table_name table_name table_name table_name
= = = = =
'ALUNOS'; 'CURSOS'; 'HISTORICO'; 'INSTRUTORES'; 'TURMAS';
Este comando gera uma lista de selects, sendo um para cada tabela do usuário, e permite ter uma exata noção de quanto espaço está sendo gasto por linha em cada tabela. Observe que os valores listados diferem da soma dos tamanhos dos campos a partir da emissão do comando describe. Isto acontece, pois, além dos dados pro-priamente ditos, há uma série de informações extras que são gravadas em cada linha da tabela para efeitos de controle.
EXERCÍCIOS 1. Crie colunas para os campos Nome_Curso (Cursos), Cod_Turma (Turmas) e Alunos (campo calculado). 2. Elabore um cabeçalho e um rodapé para um relatório que mostrará as turmas, o curso e quantos alunos foram matriculados por turma. 3. Monte o SQL que mostre a relação de cursos/turmas ordenados decrescen-temente por quantidade de alunos. 4. Totalize por curso e ao final do relatório. 5. Reúna os comandos que geraram o relatório em um arquivo texto e direcione a saída para outro arquivo texto. 6. Desabilite cabeçalho, rodapé, quebras e colunas. Acrescente esses comandos ao arquivo que gerou o relatório.
Oracle 9i Fundamental
87
REFERÊNCIA RÁPIDA Tarefa
Ativar variáveis de ambiente
Como fazer Utilize o comando SQL*Plus Worksheet SET. Exemplos: set linesize 200 set echo off
Alternativamente, pode-se Environment, Options.
acessar
o
menu
Formatar cabeçalhos de campos
Utilize o comando column. Veja sintaxe e exemplos em 5.3.1.
Formatar uma página
Dimensione-a com a variável de ambiente linesize; insira um cabeçalho com ttitle e um rodapé com btitle.
Realizar quebras e cálculos em relatórios
Utilize os comandos break e compute. Veja sintaxe e exemplos em 5.3.3.
Declarar uma bind variable
variable Limite number
Atribuir um conteúdo a uma variável declarada por VARIABLE Listar bind variables
Utilize os comandos variable ou define. Exemplo:
Utilize o comando exec. Exemplo: Exec :limite := 500
Utilize os comandos variable ou define sem argumentos. Exemplo: DEFINE
Utilizar variáveis em comandos SQL
Exemplo: Select * from cursos where preco > :limite;
Oracle 9i Fundamental
88
Capítulo 6 – OUTRAS ESTRUTURAS DE DADOS OBJETIVOS • • • •
Conhecer e Conhecer e Conhecer e Conhecer e
implementar implementar implementar implementar
objetos objetos objetos objetos
do do do do
tipo tipo tipo tipo
Índice; Visão; Seqüência; Sinônimo.
ARQUIVOS NECESSÁRIOS •
Nenhum
PRÉ-REQUISITOS • • • • • • • • • • • •
Conectar-se ao Servidor via SQL*Plus Worksheet; Criar tabelas (comando CREATE TABLE); Alterar a estrutura de tabelas previamente criadas (comando ALTER TABLE); Eliminar tabelas (comando DROP TABLE); Inserir dados em tabelas (comando INSERT); Consultar dados já armazenados (comando SELECT); Pesquisar o Dicionário de Dados; Alterar conteúdos de linhas (comando UPDATE); Eliminar linhas (comandos DELETE e TRUNCATE TABLE); Conhecer o conceito de transação e manipular os comandos relacionados (COMMIT, ROLLBACK); Elaborar relatórios com SQL*Plus Worksheet; Gerar scripts de comandos SQL a partir de outros comandos SQL.
Oracle 9i Fundamental
89
TEORIA 6.1 - Fundamentos Até o momento foi criado explicitamente apenas um tipo de objeto: tabela. O Oracle oferece inúmeras outras estruturas de dados que são muito úteis no dia-a-dia do banco, a começar pelos índices, já criados via constraints, que aceleram bastante o acesso aos dados. Depois de criar explicitamente índices, será visto como construir views que permi-tem visualizar, de uma forma simples, dados que estão em tabelas diferentes. Por exemplo, seria interessante que o nome dos instrutores e os alunos de suas turmas pudessem estar "juntos". Seguem as sequences que geram números seqüenciais. Isto é particularmente útil quando existem campos cujos conteúdos, geralmente chaves primárias, são números que não podem ser repetidos. A utilização de sequences permite que o conteúdo dessas chaves seja gerado automaticamente. O capítulo termina com synonyms que representam uma forma mais econômica de referência a tabelas que pertençam a outros usuários e até a outros bancos.
6.2 - Índices Imagine o seguinte comando que cria uma tabela com 26 campos com 30 bytes cada um: create a char b char ... z char
table grande ( (30) (30) (30));
Ao acessar o campo d, o Oracle precisa carregar as colunas a, b, c, ..., z. Como cada registro ocupa 26 x 30 = 780 bytes mais o identificador de cada linha (rowid) que possui 10 bytes, a cada 10 registros seriam necessários 7,7 Kb. Agora imagine que fosse possível criar uma estrutura "auxiliar" que contivesse dois campos: d e outro com endereços para as linhas da tabela (rowid). Cada registro ocuparia 40 bytes, assim os mesmos 7,7 Kb permitiriam carregar 197 linhas! Quase vinte vezes mais! Índices (index) são estruturas especiais inseridas no banco de dados com o objetivo de melhorar o desempenho de acesso às tabelas. Sua função é reduzir o I/O em disco utilizando uma estrutura de árvore-B (B*Tree) para localizar rapidamente os dados. Ao varrer a árvore-B, ele identifica a chave e recupera o seu rowid, ponteiro para acesso ao dado, localizando o registro rapidamente. O Oracle cria automaticamente um índice do tipo unique ao criar uma chave primária, o qual recebe o mesmo nome da constraint. Oracle 9i Fundamental
90
Índices são utilizados durante comandos select (cláusulas where order by e group by), portanto, quando houver índices compostos, deve-se colocar primeiro a coluna mais usada. Uma analogia clara para índices seriam índices remissivos de livros. O comando para a criação de índices é o create index, cuja sintaxe é: CREATE [UNIQUE] INDEX índice ON tabela (coluna [ASC | DESC] [,coluna,...);
Os colchetes representam cláusulas opcionais. A tabela seguinte explica a sintaxe do comando: Opções
Descrição
Unique
Informa que o índice em questão não aceitará valores repetidos.
Índice
Nome do índice a ser criado.
Tabela
Nome da tabela sobre a qual será criado o índice.
Coluna
Nome das colunas que comporão o índice. Este será usado automaticamente em cláusulas where, order by ou group by sempre que a primeira coluna for mencionada.
asc | desc
Especifica a classificação: ascendente (asc), default, ou descendente (desc).
Primeiro exemplo: Criação de um índice para turmas create index turmas_cod_curso_idx on turmas (cod_curso);
Pode-se confirmar a existência de índices por meio de uma visão do dicionário de dados do Oracle user_indexes, que armazena informações sobre os índices do usuário. Também podem-se verificar as colunas envolvidas em um índice utilizando user_ind_columns.
Segundo exemplo: Confirmando a existência de índices select index_name from user_indexes; INDEX_NAME -----------------------------ALUNOS_PK ... TURMAS_COD_CURSO_IDX TURMAS_PK
E para verificar as colunas: select index_name, column_name, column_position, column_length from user_ind_columns where table_name = 'TURMAS'; INDEX_NAME COLUMN_NAME COLUMN_POSITION COLUMN_LENGTH -------------------- ----------- --------------- ------------TURMAS_PK COD_TURMA 1 22
Oracle 9i Fundamental
91
TURMAS_COD_CURSO_IDX COD_CURSO
1
22
Para eliminar um índice, usa-se o comando drop index.
Terceiro exemplo: Eliminando um índice drop index turmas_cod_curso_idx;
Deve-se lembrar que este comando não elimina índices criados a partir de constraints. Concluindo, deve-se criar um índice quando: • A tabela é volumosa, muito consultada e pouco atualizada; • A coluna ou colunas são utilizadas freqüentemente em cláusulas where, order by, group by ou em joins; • A coluna contém uma grande quantidade de valores nulos; • A tabela é grande e a maior parte das queries retorna menos de 2 a 4% das linhas. Na verdade, isto significa que, quando houver muitos valores diferentes (a maior incidência como 2 a 4%), é bom indexar. A situação ótima para indexar ocorre quando não há valores repetidos (índices únicos); • Deve-se considerar também a possibilidade de criar índices em campos cujos conteúdos sejam consultados em forma de intervalo. Por exemplo: datas, siglas, códigos de chaves estrangeiras, etc. Quando uma tabela for muito consultada segundo um determinado critério, vale a pena pensar em Index-Organized Tables (IOTs), que consistem em objetos capazes de armazenar dados como acontece nos índices, ou seja, em forma de árvore. Há ganhos de performance pois a tabela é o próprio índice. Veremos este recurso em detalhes no capítulo 22. E não se deve criar índice quando: • A tabela é muito atualizada; • A tabela é pequena; • A coluna ou colunas são pouco utilizadas como condição em queries; • A coluna ou colunas já possuem um constraint primary key ou unique; • A maior parte das queries retorna mais de 2 a 4% das linhas; • A coluna é do tipo raw, lob, long ou long raw. O Oracle não permite indexar campos destes tipos.
6.3 - Views Uma view (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 Oracle 9i Fundamental
92
de uma ou mais tabelas do banco. A utilização de visões proporciona as seguintes vantagens: Evitar que usuários não autorizados tenham acesso a todos os dados de uma tabela. Para isto, cria-se uma visão com apenas alguns campos necessários; Associar a uma visão consultas que utilizam critérios de seleção complexos, e assim, facilitar ao usuário. Para criar uma visão, deve-se utilizar o comando create view. Sua sintaxe simplificada é: CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW nome_visão [alias,...] AS subquery [WITH CHECK OPTION [CONSTRAINT nome_constraint] [WITH READ ONLY];
em que: Opções
Descrição
Replace
Recria a view, se ela já existir.
Force
Cria a view, mesmo que a tabela base não exista.
Noforce
Só cria a view se a tabela base existir. Opção default.
Subquery
Sentença select na qual será baseada a view. Não é possível especificar a cláusula order by.
with check option
Caso exista algum filtro especificado na cláusula WHERE do comando SELECT, a condição será utilizada para impedir atualizações realizadas diretamente sobre a View que contrariem este filtro. Sem esta cláusula, as alterações poderiam ser feitas, porém não seriam vistas ao listar o conteúdo retornado pela View. Opcionalmente pode-se especificar o nome do constraint que determina a restrição à alteração.
with read only
Indica que não podem ser executados comandos de DML (insert, delete, update) sobre a view.
Os dados de uma view nem sempre podem ser alterados. Vejamos situações em que as atualizações normalmente são proibidas: • Tentativa de inserção em uma view que não possua todos os campos obrigatórios da tabela base (chave primária e não nulos); • Tentativa de atualização de um campo calculado ou chave da tabela primária; • Exclusão de registros que possuam outros relacionados. Como veremos em breve, essas restrições podem ser burladas graças aos Triggers do tipo Instead of. Mais detalhes no capítulo 16.
Primeiro exemplo: Criação de uma view create view arrecadado as
Oracle 9i Fundamental
93
select nome_curso CURSO, t.cod_turma TURMA, sum(preco) ARRECADADO from cursos c inner join turmas t using (cod_curso) join historico h on t.cod_turma = h.cod_turma group by nome_curso, t.cod_turma having sum(preco) >0;
E para visualizar os dados por meio da view: select * from arrecadado order by arrecadado desc; Saída16: CURSO TURMA ARRECADADO ---------------------------------------- ---------- ---------Fundamentos da Modelagem de Dados 3 9500 Fundamentos da Modelagem de Dados 9 9500 Introdução à Lógica de Programação 1 8000 Introdução à Lógica de Programação 6 8000 Introdução à Lógica de Programação 2 8000 Delphi: Acesso a Bancos de Dados 7 4000 6 linhas selecionadas.
Quando o comando select que gera a View possuir grande complexidade, a performance nas consultas poderá ser consideravelmente degradada. Neste caso, seria aconselhável criar um outro tipo de objeto: Materialized View. Trata-se de uma tabela temporária contendo os dados da Visão. No capítulo 22 veremos como criar e alimentar tal objeto. A estrutura da view pode ser vista pelo já conhecido comando describe ou pela também visão user_views.
Segundo exemplo: Confirmando a existência de views desc arrecadado Name Null? ---------------------------- -------CURSO NOT NULL TURMA ARRECADADO
Type ---VARCHAR2(60) NUMBER(3) NUMBER
O corpo: select view_name, text_length, text from user_views; VIEW_NAME TEXT_LENGTH TEXT ----------------- ----------- ------------------------ARRECADADO 219 select nome_curso CURSO,...
Para eliminar uma visão, usa-se o comando drop view.
Terceiro exemplo: Eliminando uma view drop view arrecadado;
16
Os dados seguintes foram obtidos após a execução dos Scripts Monta_Tabelas.sql e Cria_Alimenta_Historico.sql. A Stored Procedure AlimentaHistorico foi executada com os argumentos: 10, 10.
Oracle 9i Fundamental
94
Quarto exemplo: Cláusula WITH CHECK OPTION Imagine que se tenha criado uma visão representando os cursos com carga horária igual ou maior que 32: CREATE view vCursosLongos as select cod_curso, nome_curso, carga_horaria from cursos where carga_horaria >= 32 with check option;
Note que a cláusula with check option impedirá que, por meio da view, sejam inseridos ou alterados cursos com carga horária menor que 32. De fato: insert into vCursosLongos (cod_curso, nome_curso, carga_horaria) values ('Outro Curso', 10);
Produzirá a mensagem seguinte: insert into vCursosLongos (cod_curso, nome_curso, carga_horaria) * ERRO na linha 1: ORA-01402: violação da cláusula where da view WITH CHECK OPTION
6.4 - Sequences Muitas aplicações necessitam utilizar um valor numérico seqüencial como chave primária em uma tabela. Com o uso de Sequences (seqüências) esses valores podem ser gerados automaticamente pelo Oracle. A sequence gera valores para o mnemônico nextval, que pode ser utilizado no comando insert. A sintaxe do comando para criação de sequences é: CREATE SEQUENCE seqüencia [INCREMENT BY n] [START WITH n] [MAXVALUE n | NOMAXVALUE] [CYCLE | NOCYCLE] [CACHE n | NOCACHE];
em que: Opção
Descrição
Seqüencia
Nome da seqüência que não pode ser o mesmo de uma tabela ou view.
Increment by n
Especifica de quanto será o incremento ou decremento da seqüên-cia. O default é 1.
start with n
Especifica o primeiro número a ser gerado. O default é 1.
maxvalue n
Especifica o valor máximo que a seqüência pode assumir. O default é nomaxvalue, indo até 1027.
minvalue n
Especifica o valor mínimo para seqüências que estejam sendo decrementadas. É mutuamente exclusiva à anterior. Oracle 9i Fundamental
95
Opção
Descrição
cycle | nocycle
Indica que, quando atingir o valor máximo, a numeração continuará a partir do valor inicial. O default é nocycle.
Cache n | nocache
Especifica quantos valores o Oracle pré-aloca e mantém em memória. O default é 20.
Primeiro exemplo: Criação de uma sequence create sequence id_curso increment by 1 start with 11 maxvalue 999 nocycle;
Segundo exemplo: Confirmando a existência de sequences select sequence_name, increment_by,max_value, last_number from user_sequences;
E a saída: sequence_name increment_by max_value last_number ----------------- ------------ ---------- ---------id_curso 1 999 11
Observação Se for executado um rollback, o número da seqüência não volta atrás! Duas pseudocolunas são utilizadas nas seqüências: nextval, que retorna o próximo número da seqüência, e currval, valor corrente.
Terceiro exemplo: nextval insert into cursos (cod_curso, nome_curso) values (id_curso.nextval, 'Oracle: Administração');
Constatando: select cod_curso, nome_curso from cursos;
Saída: COD_CURSO NOME_CURSO --------- -----------------------------------------1 Introdução à Lógica de Programação ... 11 Oracle: Administração
Quarto exemplo: currval
Oracle 9i Fundamental
96
select id_curso.currval from dual;
Saída: CURRVAL --------11
Quinto exemplo: Eliminando uma sequence drop sequence id_curso;
Outra forma de gerar valores automaticamente consiste em utilizar o tipo raw para garantir unicidade, e a função sys_guid() para obter novos valores. Por exemplo, o comando seguinte cria uma tabela com dois campos e depois insere-lhe uma linha. create table gerada (cod raw(32), num int); insert into gerada (cod, num) values (sys_guid(),1); select * from gerada;
O resultado do último comando seria: COD NUM -------------------------------- ---------906499066237483298EDB761D9A88182 1
O conteúdo retornado pela função sys_guid() resulta da concatenação de vários dados e ocupa 16 bytes. Sua utilização é recomendada quando a unicidade for crítica, ou seja, uma linha deve possuir conteúdo único no Database.
6.5 - Synonyms Tipicamente, um Banco de Dados Oracle é utilizado por dezenas de usuários que têm vários objetos. Acontece freqüentemente que um usuário precisa de uma tabela, índice, view ou sequence de outro e, para facilitar a manipulação desses objetos, cria synonyms (sinônimos). O comando que cria synonyms é o seguinte: CREATE [PUBLIC] SYNONYM sinônimo FOR objeto
em que: Opção
Descrição
public
Especifica que o synonym pode ser usado por todos. O default é que somente o criador possa utilizá-lo.
objeto
Informa o nome do objeto sobre o qual se aplica o sinônimo. Pode ser tabela, índice, view ou sequence.
Oracle 9i Fundamental
97
Atenção
Para que seja possível criar um sinônimo público, o usuário deve ter recebido explicitamente o privilégio para tal. Este assunto será detalhado no capítulo 24, que trata sobre segurança.
Primeiro exemplo: Criação de um synonym create public synonym cursos_dba for cursos;
Supondo que o usuário corrente se chamasse DbaAcad e houvesse outro usuário denominado Pedro, este poderia fazer referência à tabela cursos de DbaAcad como: select * from cursos_dba
em vez de: select * from dbaacad.cursos
Isto, claro, após terem sido concedidas as permissões adequadas. Este assunto também será tratado no capítulo 24, Segurança.
Segundo exemplo: Confirmando a existência de synonyms Os synonyms públicos podem ser vistos em all_synonyms e os privativos, em user_synonyms: select synonym_name, table_owner from all_synonyms where table_name = 'CURSOS';
Saída: SYNONYM_NAME TABLE_OWNER -------------------------- -----------------------------CURSOS_DBA DBAACAD
Terceiro exemplo: Eliminando um synonym drop public synonym cursos_dba;
EXERCÍCIOS 1. Crie um índice com as características seguintes e depois confirme sua existência: • Tabela Alunos; • Campos uf (ascendente), nome_aluno (decrescente).
Oracle 9i Fundamental
98
2. Em quais comandos seguintes o índice recém-criado seria utilizado? a. select uf, nome_aluno from alunos order by 1,2 desc; b. select nome_aluno from alunos order by 1; c. select nome_aluno from alunos order by uf; 3. Crie uma view que informe o quanto cada instrutor arrecadou. 4. Monte uma view que revele alunos, cursos e total pago por cada um. 5. Faça uma view que mostre a média vendida por curso. 6. Crie sequences para que os códigos nas chaves primárias das tabelas "de ponta" possam ser gerados automaticamente. 7. Monte uma view que sirva como base para a Lista de Presenças. Devem constar: nome do aluno, nome do curso, carga horária, nome do instrutor e sala.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Criar índices
Utilize o comando create index. Para comprovar o sucesso da operação, investigue IND ou USER_INDEXES.
Eliminar índices
Utilize o comando drop index.
Criar views
Utilize o comando create view. Para comprovar o sucesso da ope-ração, investigue USER_VIEWS.
Eliminar views
Utilize o comando drop view.
Criar sequences
Utilize o comando create sequence. Para comprovar o sucesso da operação, investigue USER_SEQUENCES.
Eliminar sequences
Utilize o comando drop sequence.
Criar synonyms
Utilize o comando create synonym. Para comprovar o sucesso da operação, investigue USER_SYNONYMS.
Eliminar synonyms
Utilize o comando drop synonym.
Oracle 9i Fundamental
99
ANOTAÇÕES
Oracle 9i Fundamental
100
Capítulo 7 – SUBQUERIES OBJETIVOS • • • • • •
Conhecer o conceito de subquery; Identificar situações em que a utilização de uma subquery é necessária; Construir subqueries de uma linha; Construir subqueries de múltiplas linhas; Construir subqueries de múltiplas colunas; Construir subqueries correlatas.
ARQUIVOS NECESSÁRIOS •
Monta_Tabelas_Salas.sql.
PRÉ-REQUISITOS • • • • • • • • • • •
Conectar-se ao Servidor via SQL*Plus Worksheet; Criar tabelas (comando CREATE TABLE); Alterar a estrutura de tabelas previamente criadas (comando ALTER TABLE); Eliminar tabelas (comando DROP TABLE); Inserir dados em tabelas (comando INSERT); Consultar dados já armazenados (comando SELECT); Pesquisar o Dicionário de Dados; Alterar conteúdos de linhas (comando UPDATE); Eliminar linhas (comandos DELETE e TRUNCATE TABLE); Conhecer o conceito de transação e manipular os comandos relacionados (COMMIT, ROLLBACK); Criar e manipular views.
TEORIA 7.1 - Fundamentos Uma subquery consiste em uma consulta utilizada dentro de um comando SQL. Há várias situações em que as subqueries são necessárias: • Mostrar cursos cujo preço seja maior que a média dos preços; Oracle 9i Fundamental
101
Atualizar em 10% o preço do curso mais caro; Selecionar os alunos cujo estado de origem seja o mesmo de qualquer aluno de sobrenome "Silva"; • Atualizar conteúdos de campos com base em outros; • Mostrar nomes de instrutores que não ministraram cursos17; etc. Uma subquery pode ser utilizada dentro de um comando select, update, create table, delete ou insert. Existem os seguintes tipos de subqueries: • •
Tipo
Descrição
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.
Trabalhando com subqueries, é possível utilizar vários operadores: Operador
Descrição
=, , >, >=, all (select preco from cursos where upper(nome_curso) like 'DELPHI%') and upper(nome_curso) not like 'DELPHI%';
NOME_CURSO PRECO --------------------------------------------- --------Introdução à Lógica de Programação 800 Fundamentos da Modelagem de Dados 950 Oracle: SQL*Plus Worksheet e SQL 825 Oracle: PL/SQL 825
A consulta anterior retorna os cursos que não sejam de Delphi, que tenham preço maior que todos os cursos de Delphi. Atenção para o quadro comparativo: A expressão eqüivale a: < any menor que o maior < all menor que o menor > any maior que o menor > all maior que o maior Oracle 9i Fundamental
105
any = any
not in In
7.4 - Subqueries de Múltiplas Colunas Primeiro exemplo: update update cursos set (carga_horaria, preco) = (select carga_horaria, preco from cursos where cod_curso = 2) where cod_curso = 1;
Este comando atualiza o curso de código 1 com valores do curso 2. Não se esqueça de verificar se as colunas especificadas em set conferem com as da subquery.
Segundo exemplo: select com in select nome_curso, carga_horaria, preco, pre_requisito from cursos where (carga_horaria, preco) in (select carga_horaria, preco from cursos where pre_requisito is not null);
Saída: NOME_CURSO CARGA_HORARIA PRECO PRE_REQUISITO ------------------------------- ------------- --------- ------------Delphi: Recursos Básicos 24 400 1 Delphi: Acesso a bancos de Dados 24 400 1 Oracle: PL/SQL 24 825 8 Oracle: SQL*Plus Worksheet e SQL 32 825 2
Observe que são retornados cursos cujo par carga horária-preço esteja no conjunto de cursos que possuam pré-requisito. Para facilitar a compreensão, execute-as em separado, visualize o resultado, e depois emita o comando anterior.
7.5 - Subqueries Correlatas18 Supondo que existam mais duas tabelas, SALAS e TIPOS_SALAS, e uma view, V_SALAS, que mostrem a média de alunos por tipo de sala. Eis V_SALAS: create view v_salas as select s.descricao sala, t.descricao tipo_sala, count(matricula) Alunos from tipos_salas t inner join salas s on t.cod_tipo_sala = s.tipo_sala join turmas tu on s.cod_sala = tu.sala
18
As tabelas SALAS e TIPOS_SALA podem ser montadas e alimentadas a partir do script Monta_Tabelas_Salas.sql.
Oracle 9i Fundamental
106
join historico h on tu.cod_turma = h.cod_turma group by s.descricao, t.descricao;
Listando seus dados: SALA -----------------------------Ceres Jupiter Marte Mercurio Netuno Terra Urano Venus
TIPO_SALA ALUNOS ------------------------------ ---------Luxo 10 Básica 10 Padrão 20 Básica 10 Padrão 10 Luxo 10 Padrão 10 Básica 20
A média de alunos por tipo de sala seria assim obtida: select tipo_sala, avg(alunos) Media from v_salas group by tipo_sala; TIPO_SALA MEDIA ------------------------------ ---------Básica 13,3333333 Luxo 10 Padrão 13,3333333
Teríamos como visualizar as salas cuja quantidade de alunos supera a do tipo: select sala, tipo_sala, alunos from v_salas v where alunos > (select avg(alunos) from v_salas where tipo_sala = v.tipo_sala); SALA -----------------------------Marte Venus
TIPO_SALA ALUNOS ------------------------------ ---------Padrão 20 Básica 20
Observe que a utilização do campo v.tipo_sala na subquery caracteriza a correlação e determina uma forma de execução diferente: para cada linha externa executa-se a subquery interna. Ao lidar com grandes tabelas, pode ocorrer que a execução da subquery correlata seja mais lenta que a criação de uma tabela auxiliar e execução de uma consulta com join. Pode-se facilmente comprovar isto ativando a opção timing do SQL*Plus Worksheet: set timing on/off.
Segundo exemplo: update A próxima seqüência de comandos tem por objetivo desnormalizar a tabela de salas, acrescentando-lhe uma nova coluna: alter table salas add (tipo varchar2(30)); update salas set tipo = (select descricao from tipos_salas where cod_tipo_sala =salas.tipo_sala);
Oracle 9i Fundamental
107
A confirmação e a saída estão em seguida: select descricao, tipo from salas; DESCRICAO -----------------------------Mercúrio Vênus Terra Marte Ceres Júpiter Saturno Urano Netuno Plutão 10 rows selected.
TIPO ------------------Básica Básica Luxo Padrão Luxo Básica Básica Padrão Padrão Luxo
Terceiro exemplo: exists No exemplo seguinte, caso cod_cliente tivesse valores nulos, seria mais confiável utilizar o operador exists em lugar de in. Em vez de: select nome_instrutor where cod_instrutor (select cod_instrutor where t.cod_instrutor
from instrutores i not in from turmas t = i.cod_instrutor);
NOME_INSTRUTOR ----------------------------Matias Agena
seria melhor: select nome_instrutor from instrutores i where not exists (select cod_instrutor from turmas t where t.cod_instrutor = i.cod_instrutor);
ou, mais eficiente: select nome_instrutor from instrutores i where not exists (select 1 from turmas t where t.cod_instrutor = i.cod_instrutor);
EXERCÍCIOS 1. Atualize o campo Nota do Sr. Zebedeu para 8.5 na turma 1. 2. Atualize o campo Nota dos Srs. Yamandu, Wellington e Tadeu para 7 em todas as turmas. 3. Dê nota 8 a todos os alunos que cursaram Delphi. 4. Aumente 20% o preço do curso que teve mais alunos. 5. Acrescente um campo em Cursos que mostre o total arrecadado. 6. Mostre os pares instrutor-curso que pertençam ao grupo de instrutores que ministra Delphi.
Oracle 9i Fundamental
108
ANOTAÇÕES
Oracle 9i Fundamental
109
Capítulo 8 – PROGRAMAÇÃO CLIENTE/ SERVIDOR OBJETIVOS • • • •
Destacar a evolução da atividade de criar programas sob enfoque Cliente/Servidor; Apresentar as principais características da linguagem de programação PL/SQL; Diferenciar as unidades de programa PL/SQL: procedures, functions, packages e triggers; Criar Procedures e Functions com SQL*Plus Worksheet.
ARQUIVOS NECESSÁRIOS • •
08_Ex_Proc.sql; 08_Ex_Func.sql.
PRÉ-REQUISITOS • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso à bases Oracle; Conhecer os principais objetos Oracle: tabela, índice, constraint, visão e se-qüência; Programar em qualquer linguagem que comporte tipos básicos de proces-samento: seqüência, decisão, iteração.
MOTIVAÇÃO Criando Programas sob Enfoque Cliente-Servidor Com a explosão do poder computacional dos microcomputadores, as máquinas clientes passaram a ter uma performance próxima à dos Servidores. Com isto, as aplicações começaram a ser divididas, sendo que parte era executada no Servidor, parte era executada nos 19
Consulte no Apêndice C, Bibliografia Comentada, Application Server e assuntos correlatos.
livros
Oracle 9i Fundamental
que
tratam
do
Oracle
110
Clientes. O que parecia ser uma grande idéia (Servidor mais "livre") trouxe também sérios problemas: os processos de instalação e manutenção tornaram-se atividades extremamente vulneráveis. Na verdade, essa discussão ainda gera muita polêmica. Há os que preferem Clientes "gordos" e há os que exaltam as vantagens dos "magros". Sugiro um meio termo: algo como 70% no Servidor e 30% nos Clientes. Hoje aplicações nascem não apenas em duas camadas, mas em várias. Por exemplo: existe a interface, magérrima, em browser que se conecta a um Servidor HTTP. Este, por sua vez pode se conectar a um Servidor de Aplicações que, por sua vez, fará acessos ao Servidor de Dados. Com a explosão da Internet, nos últimos anos ganharam força produtos que criam uma completa infra-estrutura para desenvolvimento de portais, aplicações voltadas para o comércio eletrônico, etc. Um belo exemplo é o Oracle Application Server (O9iAS), que já está na segunda versão. Infelizmente, esse interessante produto está além do escopo desta obra19. A programação predominantemente no Servidor consiste na criação de novos objetos de Banco de Dados: Stored Procedures, Functions e Triggers, que proporcionam algumas vantagens: •
•
•
•
Se muitos programas compartilharem um Banco de Dados e houver funcionali-dades que lidem com o banco, comuns a eles, então é possível implementá-las no Servidor, evitando redundância de código; Caso seja necessário executar várias vezes um grupo de comandos SQL consecu-tivos, convém criar um bloco, compilá-lo e armazená-lo no Servidor. Isto trará um evidente ganho de performance, já que serão realizados menos acessos pela rede; De uma forma geral, o software de Banco de Dados é mais estável do que uma ferramenta de programação, ou seja, é mais provável uma determinada empresa mudar de um Visual Basic para um Delphi do que de um Oracle para um SQL Server; O tráfego de rede pode ser drasticamente reduzido. Imagine um grupo de coman-dos PL/SQL (SELECTs, INSERTs, etc.) que, juntos, possuem 200 caracteres. Chamados por, digamos, vinte usuários trinta vezes ao dia, isto representa pouco mais de 1 MB onerando a rede. Agora imagine que pudéssemos "empacotar" os 200 caracteres em uma Stored Procedure com 10 letras. O tráfego cairia para pouco menos que 6 KB; Oracle 9i Fundamental
111
O problema recém-mencionado levanta outro ponto importantíssimo: a simpli-cidade. O que deve ser mais legível para um programa: um grupo de comandos com 200 caracteres ou uma simples ativação de Stored Procedure? Finalmente, a Segurança pode ser bastante incrementada já que programas não precisariam emitir comandos, tais como: INSERTs ou DELETEs. Isto ficaria a cargo de Stored Procedures ou Functions que, de quebra, ainda poderiam realizar críticas sofisticadas. A linguagem PL/SQL gera rotinas compiladas no Servidor Oracle; portanto, os próximos capítulos giram em torno da programação no Servidor.
TEORIA 8.1 - PL/SQL A linguagem de programação Procedural Language/Structured Query Language (PL/SQL) une o estilo modular de linguagens, como Pascal e C, à versatilidade no acesso a bancos de dados obtida via SQL. Trata-se de uma escolha óbvia para quem deseja programar parte de uma aplicação no Servidor Oracle. Além do ganho de performance já discutido, a utilização da PL/SQL apresenta outras vantagens: • Modularidade: não existe o conceito de programa único e monolítico. Qualquer porção de código deve residir em blocos, geralmente pequenos. Isto facilita o desenvolvimento de grandes projetos feitos por vários profissionais; • Tipos de Processamento: como toda linguagem dita procedural, a PL/SQL permite criar estruturas de programação, tais como: decisão (if/else) e repe-tição (loop, while e for); • Variáveis: podem-se utilizar desde as de tipos primitivos (char, number, boolean) até as compostas (registros e vetores). Inclusive, pode-se associar o tipo de uma variável ao de um campo de tabela; • Packages: várias rotinas afins podem ser agrupadas fisicamente de maneira que os detalhes da implementação fiquem encapsulados do mundo exterior. O próprio Oracle Server oferece diversos packages prontos que estendem a funcionalidade da PL/SQL; • Exceções: quando ocorrerem erros de execução (divisão por zero, conteúdo de chave primária duplicado), mensagens explicativas podem ser emitidas para que o usuário tome as medidas corretivas necessárias. Oracle 9i Fundamental
112
A criação de rotinas PL/SQL pode ser realizada em diversas ferramentas: desde a simples SQL*Plus, passando por uma melhoria (SQL*Plus Worksheet), até gráficas como SQL Navigator ou Oracle Forms. Por criação entende-se a compilação e armazenamento no Servidor. A seguir, discutimos as principais características dessas quatro ferramentas:
SQL*Plus
Interface de linha, geralmente os códigos são editados à parte em um editor como Bloco de Notas. Não possui facilidades de depuração (breakpoints, execução passo a passo, etc.) e a compilação é feita no Servidor. Mais detalhes no Apêndice A.
SQL*Plus Worksheet
Versão melhorada da tradicional SQL*Plus, possui mais facilida-des de edição.
SQL Navigator
Interface gráfica, editor poderoso, depuração e vasto material de ajuda para desenvolver em PL/SQL. Compila no cliente. Muito utilizado para desenvolvimento de Stored Procedures e Triggers. Obtenha uma versão trial em www.quest.com
Oracle Forms
Integrante do pacote Developer, desenvolvimento de aplicações completas.
permite
o
Nos próximos capítulos serão utilizadas as ferramentas SQL*Plus Worksheet e SQL Navigator.
8.2 - PL/SQL ou Java? Um freqüente argumento utilizado contra a utilização da linguagem PL/SQL reside no fato de ela ser "proprietária" do ambiente Oracle, isto é, se por acaso for necessária uma migração para outro SGBDR, todo o trabalho realizado na criação de Stored Procedures, Triggers ou Functions terá sido praticamente em vão. Pensando nesta pouca propensão à portabilidade da sua linguagem de programação, a Oracle apresentou uma importante novidade na versão 8 de seu SGBDR: a possibilidade de criar "programas" também na popularíssima e portável por excelência, Java. Java foi criada a partir de outra famosa linguagem: a C++, cuja principal característica consiste em criar linhas de código que facilmente possam ser integradas em qualquer ambiente. Utilizando Java, pode-se tirar pleno proveito do Paradigma da Orientação por Objetos20 e assim desenvolver componentes que sigam o padrão CORBA, por exemplo. A questão, portanto, não está em escolher PL/SQL ou Java. Ambas representam poderosas linguagens e cada uma atende muito bem a um grupo específico de problemas. Para atender a requisitos intrinsicamente
20
Para saber mais detalhes sobre o POO, não deixe de ler a Motivação do capítulo 17, muito bem escrita por Luiz Paulo Maia.
Oracle 9i Fundamental
113
ligados a Bancos de Dados, PL/SQL! Para criar porções de código genéricas, que precisem ser executadas em diferentes ambientes, Java! Evidentemente, a Oracle fez o possível para que a integração entre as duas linguagens aconteça da forma mais branda possível, assim, facilmente pode-se chamar uma rotina Java a partir de uma unidade de programa escrita em PL/SQL e vice-versa. Como a linguagem Java possui aplicações mais distantes dos Bancos de Dados, não a discutiremos neste livro. Mas, não deixe de consultar o Apêndice C no qual consta uma extensa bibliografia comentada, inclusive com livros abordando Java.
8.3 - Unidades de Programa Como já foi mencionado, trabalhar em PL/SQL consiste basicamente em criar pequenos e coesos blocos de código denominados Unidades de Programa. De uma forma geral, um bloco possui a seguinte estrutura: [declare]
Seção de declarações de variáveis, constantes e cursores (grupo de linhas de uma ou mais tabelas). Também acontecem inicializações. begin
Seção em que são colocados os comandos SQL e as estruturas de programação (if, while, etc.). exception
(opcional)
Identificação dos erros e emissão de mensagens. end;
Existem quatro tipos de Unidades de Programa: Procedure
Bloco de comandos que pode receber parâmetros de entrada ou de saída. Ativado como se fosse um comando da linguagem. Veja item 8.4 para maiores detalhes.
Function
Bloco de comandos que pode receber parâmetros apenas de entrada e, necessariamente, retorna um valor em seu nome. A ativação ocorre em expressões. Veja item 8.5 para maiores detalhes.
Package
Reunião física de procedures, functions e cursores. Dividido em duas partes: especificação e corpo. Na primeira realizam-se as declarações de membros públicos e na segunda implementa-se o código dos blocos e declaram-se variáveis privativas. Mais detalhes no capítulo 15.
Trigger
Rotina disparada automaticamente antes ou depois de comandos UPDATE, INSERT ou DELETE. Muito utilizados para auditoria, críticas sofisticadas e controle de integridade referencial. Veja o capítulo 16 para obter mais informações. Oracle 9i Fundamental
114
Eventualmente podem existir blocos dentro de outros blocos. São os ditos Anônimos e servem para destacar uma determinada funcionalidade do resto.
8.4 - Procedures Pequenas porções de código que realizam tarefas específicas e ativadas como comandos. Elas podem receber parâmetros de entrada, saída ou entrada e saída. Para criar uma procedure no SQL*Plus Worksheet, devemos digitar ou abrir um arquivo texto contendo a seguinte estrutura: CREATE OR REPLACE NOME_PROCEDURE (lista de parâmetros opcional) IS Declarações locais BEGIN Comandos END;
Exemplo create or replace procedure AlimentaHistorico (ultima_turma in number, ultimo_aluno in number) is begin delete historico; /*comentário: elimina registros atuais */ for i in 1..ultima_turma loop for j in 1..ultimo_aluno loop insert into historico (cod_turma, matricula) values (i,j); end loop; end loop; commit; End; /
Observações •
•
As palavras or replace são opcionais, entretanto, caso não sejam utilizadas e a procedure já existir, devemos excluí-la explicitamente antes de recriá-la; A rotina anterior recebe dois parâmetros numéricos de entrada. Caso ela devolva outro, a segunda linha mudaria para:
(ultima_turma in number, ultimo_aluno in number, afetadas out number)
Quando um parâmetro for de entrada e saída, utilizam-se as palavras in out. Deve-se frisar que tanto nas passagens de parâmetro por valor (in) como por referência (in out ou out), o conteúdo do argumento será copiado •
Oracle 9i Fundamental
115
para uma área em memória. Isto pode se tornar um problema para argumentos que contenham muitos bytes. Uma alternativa seria a utilização da palavra reservada nocopy que procura, sempre que possível, não fazer uma cópia do argumento passado: (ultima_turma in number, ultimo_aluno in number, afetadas out NOCOPY number)
A execução da rotina apresentada pode ser: exec alimentahistorico (10, 10);
Para verificar a existência de uma procedure, deve-se investigar a visão user_objects: select object_name from user_objects where object_type = 'PROCEDURE';
E a saída: OBJECT_NAME ---------------------------------------------------------ALIMENTAHISTORICO
Observe que foi utilizado o comando delete em vez de truncate table, como talvez fosse mais aconselhável. Isto acontece pela impossibilidade de utilizar comandos que encerrem transações, tais como: create, alter, drop e o próprio truncate table. Esta limitação será contornada utilizando SQL dinâmica, como veremos no capítulo 11.
8.5 - Functions Enquanto procedures podem receber vários parâmetros de entrada, saída ou entrada--saída, functions apenas recebem parâmetros de entrada e devolvem um valor em seu nome. Para criar uma function no SQL*Plus Worksheet, devemos editar um arquivo texto contendo a seguinte estrutura: CREATE OR REPLACE NOME_FUNCTION (lista de parâmetros de entrada opcional) RETURN tipo de retorno IS Declarações locais BEGIN Comandos END;
Exemplo create or replace function ValorEmDolar (reais in number, cotacao in number)
Oracle 9i Fundamental
116
return number is begin return reais/cotacao; end; /
Observações As palavras or replace são opcionais, entretanto, caso não sejam utilizadas e a function já existir, devemos excluí-la explicitamente antes de recriá-la. A execução da função anterior pode ser: column nome_curso format a40 select nome_curso, preco "Em R$", ValorEmDolar(preco, 2.70) "Em US$" from cursos;
E a saída: NOME_CURSO Em R$ Em US$ ---------------------------------------- ---------- ---------Introdução à Lógica de Programação 950 351,851852 Fundamentos da Modelagem de Dados 950 351,851852 ... Redes II 0 0
Para verificar a existência de uma function, deve-se investigar a visão user_objects: select object_name from user_objects where object_type = 'FUNCTION'; OBJECT_NAME ---------------------------------------------------------VALOREMDOLAR
Uma função pode ser ativada a partir de um comando SQL do tipo DML (DDL, não) nas cláusulas where, having, order by, group by em select; values em insert; set em update e where em delete. Quando isto ocorrer, a função não pode ter comandos SQL e os tipos passados ou de retorno devem ser compatíveis com o Oracle Server. Também deve-se observar que quem emitir um comando SQL possuindo uma function e não for o dono dela, deve possuir privilégio de execução. Mais detalhes no Capítulo 24, Segurança. A seguir, veremos outras formas de execução. Primeiro declaramos duas variáveis: variable cotacao number variable em_dolares number
Atribuindo valores: exec :cotacao := 2.70
Oracle 9i Fundamental
117
exec :em_dolares := ValorEmDolar(1000, :cotacao)
Exibindo: print em_dolares EM_DOLARES ---------370,37037
Outra forma: select ValorEmDolar(2000, 2.70) from dual; VALOREMDOLAR(2000, 2.70) ----------------------740,740741
O código-fonte de uma function (ou procedure também) pode ser visualizado a partir da visão user_source: select text from user_source where name = 'VALOREMDOLAR'; TEXT ----------------------------------------------------------function ValorEmDolar (reais in number, cotação in number) return number is begin return reais/cotação; end;
EXERCÍCIOS 1. Construa uma function que receba um número e devolva-o dobrado. • Por exemplo, se a entrada for 5, a saída deverá ser 10. • Caso existam erros, mostre-os com SHOW ERRORS. 2. Faça uma procedure que receba um número e mostre seu dobro. • Ative a função já criada. • Para exibir um valor, utilize a procedure embutida put_line que pertence ao package embutido DBMS_OUTPUT. Por exemplo: dbms_output.put_line(to_char(6));
•
Não se esqueça de ligar a variável de ambiente SERVEROUTPUT.
Oracle 9i Fundamental
118
3. Permita que a procedure seja ativada sem argumentos. • Para que isto seja possível, o argumento deve aceitar valor default. Por exemplo: create or replace procedure ChamaDobra (ent in number default 150)
4. Mostre o dobro dos preços dos cursos. 5. Constate o armazenamento no Servidor dos objetos recém-criados. Investigue as visões USER_OBJECTS e USER_SOURCE.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Criar uma procedure
Utilize o comando create or replace procedure. Veja exem-plo no item 8.4.
Eliminar uma procedure
Utilize o comando drop procedure.
Criar uma function
Utilize o comando create or replace function. Veja exemplo no item 8.5.
Eliminar uma function
Utilize o comando drop function.
Listar procedures ou functions criadas
Inspecione a visão USER_OBJECTS, filtrando o campo OBJECT_TYPE para PROCEDURE ou FUNCTION.
Listar o código-fonte das procedures ou functions criadas
Inspecione a visão USER_SOURCE, filtrando o campo NAME para o nome da procedure ou function desejada.
Oracle 9i Fundamental
119
Capítulo 9 – SQL NAVIGATOR OBJETIVOS • • • •
Carregar em memória a ferramenta SQL Navigator e conectar-se ao Servidor; Identificar os elementos do ambiente do SQL Navigator; Criar procedures e functions no SQL Navigator; Utilizar o help do SQL Navigator.
ARQUIVOS NECESSÁRIOS • •
08_Ex_Proc.sql; 08_Ex_Func.sql.
PRÉ-REQUISITOS • • •
Compreender as conseqüências da programação no Servidor; Diferenciar os tipos de Unidades de Programa da linguagem PL/SQL; Criar procedures e functions com SQL*Plus Worksheet.
TEORIA 9.1 - Fundamentos SQL Navigator é um software que permite o desenvolvimento de Unidades de Programa PL/SQL. Trata-se de uma ferramenta cliente ao Servidor Oracle, assim como o SQL*Plus Worksheet, entretanto, ao contrário deste, possui um ambiente de desenvolvimento completo. Assim, não há necessidade de recorrer a editores de texto externos, como o Bloco de Notas. Existe uma série de vantagens adicionais em relação ao SQL*Plus Worksheet: • A interface é gráfica, organizada em janelas, portanto bem mais amigável; • O desenvolvimento de Unidades de Programa pode ser efetuado localmente, já que possui um compilador PL/SQL embutido; • Há recursos que permitem realizar depuração de Unidades de Programa, ou seja, é possível interromper a execução em uma Oracle 9i Fundamental
120
determinada linha (breakpoint), inspecionar valores de variáveis, alterá-los, etc. Infelizmente, o SQL Navigator deve ser adquirido de forma independente do Servidor, entretanto é possível obter uma versão demo com validade de trinta dias no sítio www.quest.com21. Em fevereiro de 2002, estava disponível a versão 4.2. O SQL Navigator pode ser utilizado em qualquer Windows. Uma vez instalado em um ambiente Windows 2000, por exemplo, devemos localizar o comando: Start, Programs, Quest Software, SQL Navigator 4, SQL Navigator 4. Antes que seja possível manipular qualquer objeto do Servidor, deve-se realizar uma conexão como mostra a figura ao lado.
9.2 - Elementos do Ambiente 9.2.1 - DB Navigator A janela mais importante do ambiente é a do DB Navigator, ativada teclando F12: Esta janela mostra uma conexão ativa, por isso, caso seja fechada, encerra-se a sessão correspondente. Ela permite o acesso a qualquer objeto "visível" da sessão corrente: tabelas com seus campos, visões, unidades de programa, etc. Por exemplo, poderíamos editar o conteúdo da tabela ALUNOS! Siga o caminho: expanda My Schema, depois Tables. Clique com o botão direito sobre Alunos e escolha a opção Edit Data. O resultado pode ser algo assim:
21
Consulte o Apêndice F para conhecer outros sítios de fabricantes de ferramentas similares ao SQL Navigator. Por exemplo, não deixe de visitar www.precise.com nem www.leccotech.com.
Oracle 9i Fundamental
121
O SQL Navigator pode manter várias sessões simultaneamente, cada uma com sua janela DB Navigator. Procedures ou Functions já criadas podem ser visualizadas ativando o item My Schema, Procedures ou My Schema, Functions. Clicando com o botão direito do mouse sobre o nome da procedure ou function e escolhendo o comando Open, ativa-se o Stored Program Editor, um dos tantos ambientes de edição responsáveis pela criação e alteração de objetos.
9.2.2 - Stored Program Editor Além do DB Navigator, o SN trabalha com vários editores que podem ser acessados pelo menu View, Visual Object Editor. Um dos mais importantes é o editor de programas que serve para trabalhar procedures, functions ou Packages. A figura seguinte mostra a edição da procedure AlimentaHistorico que foi previa-mente criada pelo SQL*Plus Worksheet.
Observe a variedade de cores apresentada no código, cada uma revelando uma ca-racterística do texto editado. Oracle 9i Fundamental
122
Uma vez selecionada a Unidade de Programa, é possível editá-la e compilála. Como o SQL Navigator possui um compilador PL/SQL embutido, o Servidor não é onerado nesta atividade. Para executar o código mostrado, tecle F9. Será mostrado um miniassistente que permitirá caracterizar a execução da rotina. Neste caso em particular, peça para editar o resultado final, pois argumentos devem ser informados. O resultado final, já editado, poderia ficar assim22:
9.2.3 - SQL Editor A última figura mostra o SQL Editor (View, New SQL Editor) que permite testar porções de código isoladas. Veja outro exemplo:
9.2.4 - Trigger Editor 22
A cláusula EXCEPTION será explicada em detalhes no capítulo 14.
Oracle 9i Fundamental
123
Finalmente, existe um editor específico para Triggers, assunto visto em detalhes no capítulo 16:
Para chegar à janela mostrada na figura anterior, siga o caminho: menu View, Visual Object Editor, Trigger Editor; depois escolha o dono das tabelas (Parent Schema) e a tabela (ALUNOS, por exemplo). Aguarde o capítulo 16 para saber mais!
EXERCÍCIOS 1. Ative o SQL Navigator e conecte-se ao Servidor. • Novas conexões podem ser obtidas pelo comando Session.
Session, New
2. Analise as possibilidades de ajuda oferecidas pelo SQL Navigator. • No menu Help estão, entre outras, três possibilidades: Contents, Context Help e How to use Help. • Aprenda um pouco mais sobre o DB Navegador. 3. Abra a função criada no capítulo anterior. • Pelo DB Navegador, item My Schemas, localize-a no item Functions. Clique com o botão direito sobre ela e selecione Open. • Provoque um erro de compilação e tente salvá-la. 4. Execute a função. • Pelo SQL Editor ative-a: select (to_char(dobra(10))) from dual 5. Altere a função para que aceite um parâmetro default. • Utilize o Stored Program Editor.
Oracle 9i Fundamental
124
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Ativar o SQL Navigator
Localize-o pelos menus a partir do Iniciar (Start) ou execute o arquivo SQLNAV4.EXE.
Conectar-se ao Servidor
Ao carregar o SQL Navigator, fornecer usuário, senha e host string. Novas conexões podem ser obtidas pelo comando Session, New Session. Em caso de dúvidas, consulte o administrador.
Ativar editores ambiente
Ative comandos do menu View, Visual Object Editor.
do
Localizar um objeto
DB Navigator; My Schema. É possível inspecionar tabelas, visões, seqüências, sinônimos, procedures, funções e Packages.
Ativar o Help
Menu Help, Contents ou tecle F1.
Oracle 9i Fundamental
125
Capítulo 10 – VARIÁVEIS OBJETIVOS • • • •
Compreender como PL/SQL implementa o conceito de variável; Declarar variáveis de tipos escalares ou compostos; Identificar o escopo de uma variável; Manipular variáveis.
ARQUIVOS NECESSÁRIOS • •
10_Vetores.sql; 10_Escopo.sql.
PRÉ-REQUISITOS • • •
Já ter trabalhado com variáveis em alguma linguagem de programação; Diferenciar os tipos de Unidades de Programa da linguagem PL/SQL; Criar procedures e functions com SQL*Plus Worksheet ou SQL Navigator.
TEORIA 10.1 - Fundamentos Variáveis possuem inestimável valor em qualquer linguagem de programação. Com elas é possível, temporariamente, armazenar valores para que possam ser manipu-lados depois. Para que uma variável exista, deve possuir quatro características:
Nome
Identificação da variável na Unidade de Programa. Deve ser claro, isto é, revelar a função da variável. Exemplos: nome_cliente, valorTotal, media_salarios
Tipo
Conjunto de valores que pode assumir (numérico, texto, data, lógico). Há os embutidos e os criados. Veja próximo item para obter uma lista detalhada dos tipos fornecidos pela PL/SQL.
Endereço
Posição em memória ocupada pela variável. Esse dado é Oracle 9i Fundamental
126
transparente ao programador. Conteúdo
Valor que uma variável possui em um determinado instante.
Para que uma variável possa ser utilizada, ela deve ser previamente declarada. Esta operação consiste na especificação de nome, tipo e, eventualmente, conteúdo inicial. Toda declaração ocorre na seção de declarações da Unidade de Programa (entre is e begin). A linguagem PL/SQL trabalha tanto com alocação estática quanto dinâmica. No primeiro caso, o espaço de memória é previamente reservado antes da execução e, no segundo, podem acontecer requisições durante a execução. Este livro trata do primeiro caso, apenas. Quanto à ocupação de memória, variáveis podem ser simples (escalares) ou compostas. Enquanto variáveis simples ocupam uma posição de memória, as compostas consistem em grupos de variáveis, como, por exemplo: vetores (todas do mesmo tipo e identificadas por índice), registros (tipos diferentes, identificadas por nome) ou objetos (dados e procedimentos definidos na mesma estrutura). Deve-se ainda destacar a presença de tipos voltados para dados extensos (Large Objects). Assim, existem: CLOB e NCLOB (grandes cadeias de caracteres), BLOB (dados binários) e BFILE (referência a um arquivo externo).
10.2 - Tipos Escalares Como já mencionado, variáveis de tipos escalares caracterizam-se por conterem apenas um valor de cada vez. Existem quatro subtipos: numéricos, textos, data e lógico. A tabela seguinte destaca os mais importantes: Tipo
Descrição
Char (n)
Cadeia de caracteres com tamanho fixo n. O default é 1 e o máximo, 32.767. Deve-se observar que o tipo equivalente no Servidor armazena até 2.000 posições.
Varchar2 (n)
Cadeia contendo caracteres de tamanho variável com o máximo de n, em que n pode ter o valor de até 32.767. Novamente há uma limitação: não se pode atribuir o conteúdo de uma variável deste tipo a um campo varchar2, já que este somente aceita até 4.000 posições. Para que duas variáveis desse tipo sejam consideradas iguais, elas devem possuir, além do mesmo conteúdo, o mesmo tamanho.
Long
Antigo tipo, em vias de extinção. Armazena até 32.760 caracteres.
Raw e Long raw
Tipos antigos que devem ser migrados para blob assim que possível.
Oracle 9i Fundamental
127
Tipo
Descrição
Number (p,e)
Valores numéricos em que p indica a precisão (máximo de 38); e indica a escala (número de casas decimais) que varia de –84 a +127. Por exemplo, number (5,2) especifica um número na faixa entre -999,99 e +999,99.
Binary_ Integer
Valores numéricos inteiros com sinal. Faixa: -231 a +231
Date
Armazena data e hora, incluindo século, ano, mês, dia, hora, minuto e segundo. Intervalo: 1/1/4712 a.C. até 31/12/9999. Campos deste tipo ocupam 7 bytes.
Timestamp
Permite armazenar datas/horas com maior precisão (máxima: 9, default: 6). Por exemplo, caso seja necessário especificar milésimos de segundo, a precisão deve ser 3.
Interval Year (p) to month
Armazenam intervalos de tempo em anos/meses. P representa a quantidade de dígitos para o ano (possíveis: 0 a 9, default: 2). Intervalos podem ser obtidos, por exemplo, ao subtrair uma data de outra.
Interval Day (dp) to second (sp)
Armazenam intervalos de tempo em dias, horas, minutos e segundos. DP representa a quantidade de dígitos para o dia (possíveis: 0 a 9, default: 2). SP representa a quantidade de dígitos para o segundo (possíveis: 0 a 9, default: 6).
Boolean
Aceita apenas os valores: TRUE, FALSE ou NULL.
Alguns tipos possuem especializações (subtipos). Por exemplo, em vez de number podem ser utilizados: integer, int ou smallint (números inteiros com até 38 dígitos); real, double precision ou float (representação em ponto flutuante); dec, decimal ou numeric (armazenados em ponto fixo). A declaração de uma variável escalar se faz especificando: • nome da variável; • modificador constant (opcional), caso o valor não possa mudar durante a execução; • tipo; • modificador not null (opcional), caso a variável não possa receber null; • atribuição (opcional). Veja alguns exemplos: total_arrecadado number(7,2) := 100; idade number(3) := 50; max_alunos constant number(4) := 2000; nome varchar2(20); aposentado boolean not null := false; periodo interval year(3) to month := '101-3'; -- A variável acima representa um intervalo de 103 anos e três meses. data_corrente date :=sysdate;
Oracle 9i Fundamental
128
O SQL Navigator procura facilitar o ato de declarar variáveis de alguns tipos. Execute. View, Code Assistant. Na pequena janela aberta, clique em Sintax and Web Catalog, depois expanda: Sintax, PL/SQL Syntax e Data Types. Finalmente, basta localizar o tipo desejado e arrastá-lo para a janela de código. Uma variável pode ser declarada como sendo do mesmo tipo que um campo de tabela: preco
cursos.preco%type := 200;
Durante a execução, variáveis que não tiverem sido caracterizadas como constant podem mudar de valor: ... total_arrecadado aposentado
:= total_arrecadado + 300; := (idade >=65);
10.3 - Tipos Compostos 10.3.1 - Vetores (Tables) Um vetor, ou table para PL/SQL, representa um conjunto, a princípio ilimitado, de variáveis do mesmo tipo. Cada componente é identificado por um índice, entretanto as posições não precisam ser imediatamente consecutivas. Veja o exemplo seguinte: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
create or replace function ContaMaioresQueMedia return number is type tipo_vetor is table of number(2) index by binary_integer; lista tipo_vetor; i integer; soma integer :=0; qtos number := 0; media integer; begin lista(1) := 78; lista(2) := 60; lista(3) := 47; lista(4) := 50; lista(5) := 21; for i in 1..lista.count loop soma := soma + lista(i); end loop; media := trunc(soma/lista.count); for i in 1..lista.count loop if lista(i) > media then qtos:=qtos+1; end if; end loop; return qtos; end;
Oracle 9i Fundamental
129
Observações Os elementos do vetor não precisam ser consecutivos, isto é, podemos criar a posição 3 e depois a 5; Para criar um vetor, temos previamente que definir um tipo (linha 4). Obriga--se a utilização de um indexador, sempre do tipo binary integer Ao criar um vetor, não existe limite de componentes. Eles são inseridos dinamicamente; As estruturas de programação for e if serão vistas com mais detalhes no capítulo 12.
10.3.2 - Registros (Records) Freqüentemente nos vemos às voltas com a necessidade de manipular alguns registros de uma tabela, ou parte dela, em memória. Neste caso, podemos criar um tipo que espelhe a estrutura de uma tabela: ... type tipo_reg_curso is record (cod_curso number(3), nome_curso varchar2(60), carga_horaria number(3), preco number(7,2), pre_requisito number(3)); reg_curso tipo_reg_curso;
O acesso aos campos pode ser assim: reg_curso.carga_horaria := 20;
Caso a variável em memória seja exatamente o registro da tabela, podemos ter: reg_curso
cursos%rowtype;
Finalmente, podemos ter a própria tabela em memória: ... type tipo_tab_cursos is table of cursos%rowtype index by binary_integer; reg_curso tipo_tab_cursos; ...
e um possível acesso a campos: reg_curso(1).carga_horaria := 20;
No capítulo 13 abordaremos o assunto Cursores que oferece uma forma alternativa de manipular registros de tabelas em memória. No capítulo 17 trataremos dos Objetos que representam formas alternativas de armazenamento de dados. Oracle 9i Fundamental
130
10.4 - Escopo Toda variável pode ser manipulada em uma determinada área de código que chamamos de escopo. Em princípio, o escopo de uma variável compreende as linhas entre o begin e o end de uma Unidade de Programa, mas há ocasiões em que se transcende esta região. Como veremos no capítulo referente a Packages e depois no de Objetos, uma variável pode ser vista por várias rotinas internas ou até mesmo externas à estrutura na qual está declarada. Problemas referentes a escopo surgem na utilização de blocos anônimos. Veja um exemplo extremo: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
create or replace procedure EscopoComplicado is valor number(2) := 30; v2 number(3) := 100; begin declare /* Aqui começa o Segundo Bloco */ valor varchar2(15) := 'Agora é Texto'; begin declare /* Aqui começa o Terceiro Bloco */ valor date := sysdate; begin valor := valor +30; v2:= v2+1; end; valor := 'Outro Texto'; v2 := v2+1; end; valor := valor + 1; v2 := v2 +1; end;
Observações O código mostrado apresenta três blocos aninhados; Não há conflito entre variáveis, pois nos bloco não existem declarações redundantes; O escopo da variável v2 é maior que o da de valor declarada nos blocos internos, que, por sua vez, nada tem a ver com a variável valor mais externa; Qual é o valor final de v2? Para executar o script anterior no SQL Navigator, ative o comando View, New SQL Editor, carregue o arquivo em questão, e execute-o com F9. Para executar a rotina criada, abra uma nova janela e digite: begin EscopoComplicado; end;
Nenhuma saída será mostrada.
Oracle 9i Fundamental
131
EXERCÍCIOS 1. As declarações apresentadas em seguida estão corretas? Se não estiverem, explique a razão. a. v1, v2 number(2); b. v3 number(3) := 1000; c. v4 boolean := 1=1; d. msg varchar2(100) := 'Olá, ' || user; 2. Crie uma função que receba um número entre 1 e 12 e mostre o nome do mês equivalente. • Assuma que a entrada será correta. • Utilize um vetor para armazenar o nome dos meses. 3. Faça uma procedure que receba dois números por parâmetro, armazene-os em duas variáveis, depois troque o conteúdo de uma variável pelo conteúdo da outra. • Os parâmetros não podem ser apenas IN ou apenas OUT. • Para ativá-la, utilize o script seguinte no SQL*Plus Worksheet: var n1 number var n2 number exec :n1 := 1 exec :n2 := 4 exec troca (:n1, :n2) print n1 print n2
4. Qual é o erro do código seguinte? 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
create or replace procedure AcheErro is valor number(2) := 30; v2 number(2) := 40; begin declare /* Aqui começa o Segundo Bloco */ valor varchar2(15) := 'Agora é Texto'; v3 number; begin valor := 'Outro Texto'; v2 := v2+1; end; valor := valor + 1; v2 := v2 +1; v3 :=4; end;
5. Crie uma função que receba três números por parâmetro e retorne a média.
Oracle 9i Fundamental
132
REFERÊNCIA RÁPIDA Tarefa Declarar es-calar
uma
Como fazer variável
Especifique nome seguido de tipo. Opcionalmente informe os modificadores constant ou not null e realize uma atribuição com o operador :=.
Atribuir um valor a uma va-riável escalar
Utilize o operador :=.
Declarar uma com-posta
Inicialmente crie um tipo que revele a estrutura da variável, depois faça como se fosse uma variável escalar.
variável
Atribuir um valor a uma variável composta (vetor ou registro)
Para elementos de um vetor, identifique-o pelo índice. Por exemplo: vetor(i) := valor; Duas variáveis que sejam do mesmo tipo vetor podem ter seus conteúdos trocados. Para campos de um registro, identifique-o pelo nome. Exemplo: registro.campo := valor;
Duas variáveis que tenham a mesma estrutura de registro podem ter seus conteúdos trocados.
Oracle 9i Fundamental
133
Capítulo 11 – PL/SQL: SQL OBJETIVOS • • • • •
Retornar valores que estejam no Servidor, via Unidades de Programa; Incluir dados em tabelas; Alterar dados; Eliminar linhas de tabelas; Executar comandos SQL de forma dinâmica.
ARQUIVOS NECESSÁRIOS • • • • • •
11_Retorna_Info_Curso.sql; 11_Calcula_Total_Arrecadado.sql; 11_Insere_Instrutor.sql; 11_Atualiza_Telefone_Instrutor.sql; 11_Elimina_Inst_Sem_Turmas.sql; 11_Exemplos_SQL_Dinamica.sql.
PRÉ-REQUISITOS • • •
Dominar comandos SQL do tipo DML (Select, Insert, Delete, Update); Diferenciar os tipos de Unidades de Programa da linguagem PL/SQL; Criar procedures e functions que manipulem variáveis escalares ou compostas.
TEORIA 11.1 - Seleção (Select/Into) Via rotinas PL/SQL é possível manipular os dados de um banco. Na verdade, PL/SQL é a junção de comandos SQL (os de definição, DDL, somente podem ser executados via SQL Dinâmica, como veremos no item 11.5) com PL (fluxo de programação, vistos no próximo capítulo). Relembre o ganho de performance obtido ao "aglutinar" comandos SQL em Unidades de Programa: o tráfego de rede diminui e guardam-se porções "executáveis". Oracle 9i Fundamental
134
A seleção de dados é obtida por uma variação do comando select. Veja um exemplo extraído do arquivo 11_Retorna_Info_Curso.sql: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
create or replace procedure retorna_info_curso (v_ch in cursos.carga_horaria%type) is v_nome cursos.nome_curso%type; v_preco cursos.preco%type; begin select nome_curso, preco into v_nome, v_preco from cursos where carga_horaria = v_ch; dbms_output.put_line ('curso: '|| v_nome); dbms_output.put_line ('preço: '|| to_char(v_preco)); end;
No SQL Navigator, para que a rotina put_line do package embutido dbms_output tenha o efeito esperado, deve-se emitir o comando Session, Server Output. Uma provável ativação é: begin Retorna_Info_Curso(40); end;
e a saída que surgirá na guia Spool, em azul: Curso: Fundamentos da Modelagem de Dados Preço: 950
Infelizmente, caso haja mais de um curso com a carga horária fornecida ou nenhum tenha a carga horária em questão, ocorrem problemas, já que o comando select/into somente funciona se houver um e apenas um dado por retornar. Assim: Retorna_Info_Curso(32);
resultaria no erro ORA-01422 (retorna-se mais de uma linha). Já o comando: Retorna_Info_Curso(99);
resultaria no erro ORA-01403 (nenhuma linha retornada). Estes dois problemas (ORA-01422 e ORA-01403) serão resolvidos com a utilização de Cursores, assunto visto no capítulo 13. As mensagens emitidas podem ser mais amistosas, caso estes erros possam ser tratados (mais detalhes no capítulo 14). Existem situações em que não há como acontecerem os erros citados. Analise o exemplo extraído do arquivo 11_Calcula_Total_Arrecadado.sql. 1. 2. 3. 4. 5.
create or replace function calcula_total_arrecadado return number Is v_soma number; Begin
Oracle 9i Fundamental
135
6. 7. 8. 9. 10. 11. 12. 13. 14.
select sum(preco) into v_soma from cursos c, turmas t, historico h Where c.cod_curso = t.cod_curso and t.cod_turma = h.cod_turma; return v_soma; end;
Uma possível execução no SQL*Plus Worksheet pode ser: var num number exec :num := Calcula_Total_Arrecadado
Supondo que a tabela HISTORICO tivesse 100 linhas, o resultado seria: print num NUM --------47000
Observações Note que todas as variáveis locais (declaradas e parâmetros) possuem prefixo v_. Isto foi feito para diferenciá-las de campos de tabelas no banco. Caso tenham o mesmo nome, o Oracle assume que o campo está sendo utilizado; Para que um usuário, que não seja o dono da tabela CURSOS nem da função, possa executá-la, deve receber privilégio de execução. Veja: nenhuma per-missão na tabela precisa ser concedida! No SQL Navigator, podemos realizar a seguinte execução: begin dbms_output.put_line(Calcula_Total_Arrecadado); end;
11.2 - Inserção (Insert) Uma interessante forma de incrementar a segurança de acesso aos dados de uma tabela consiste em criar pequenas Unidades de Programa, cada uma realizando uma operação específica (inserção, atualização, exclusão). Desta forma, o usuário não precisa aprender SQL para manipular os dados de uma tabela: basta chamar rotinas adequadas. O arquivo 11_Insere_Instrutor.sql oferece um exemplo de inserção: 1. 2. 3. 4. 5. 6. 7. 8.
create or replace procedure insere_instrutor (v_nome in instrutores.nome_instrutor%type, v_tel in instrutores.tel_instrutor%type, v_adm in instrutores.admissao%type) Is Begin insert into instrutores values (gera_cod_instrutor.nextval, v_nome, v_tel,v_adm);
Oracle 9i Fundamental
136
9. 10. 11.
commit; -- sem este comando, a gravação efetiva não ocorre end;
E uma possível execução: exec Insere_Instrutor('Luis Becrux','455-7877',sysdate) select * from instrutores; COD_INSTRUTOR ------------1 2 3 4 5 6 7 8 9 10 50
NOME_INSTRUTOR -----------------------------Maria Carolina Sirio Pedro Paulo Canopo Augusto Lemos Vega Mônica Silveira Capela Almir Altair Leonardo Guimarães Rigel Beatriz Bellatrix Carlos Regulos Joana Aldebaran Matias Agena Luis Becrux
TEL_INSTRU ---------9647-1622 274-9018 722-1300 212-7938 220-6022
455-7877
ADMISSAO -------01/02/97 03/08/96 12/11/98 30/12/97 03/10/96 17/07/97 18/09/98 01/03/97 21/01/02 21/01/02 29/01/02
11 linhas selecionadas.
Observe que foi criada uma sequence para que códigos possam ser gerados automaticamente.
11.3 - Alteração (Update) Em vez de utilizar o comando update para realizar uma atualização na tabela de instrutores, podemos desenvolver uma rotina que receba os dados necessários por parâmetro e realize a mudança. Haverá um grande ganho em simplicidade, como podemos ver no exemplo que consta no arquivo 11_Atualiza_Telefone_Instrutor. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
create or replace procedure atualiza_telefone_instrutor (v_cod in instrutores.cod_instrutor%type, v_novo_tel in instrutores.tel_instrutor%type) Is Begin update instrutores set tel_instrutor = v_novo_tel where cod_instrutor = v_cod; commit; end;
E uma possível execução: exec atualiza_telefone_instrutor(50,'399-58-73'); select * from instrutores where cod_instrutor = 50; COD_INSTRUTOR NOME_INSTRUTOR TEL_INSTRU ADMISSAO ------------- ------------------------------ ---------- --------
Oracle 9i Fundamental
137
50 Luis Becrux
399-58-73
29/01/02
Observações A rotina anterior não apresenta nenhum mecanismo de segurança, isto é, caso o código fornecido não exista, a execução NÃO será interrompida. Este problema será resolvido no capítulo que trata de Cursores (13); O inconveniente dessa abordagem é a explosão da quantidade de procedures/functions de um banco. Há que se encontrar um meiotermo.
11.4 - Exclusão (Delete) A eliminação de linhas também pode ser inserida em uma Unidade de Programa. Basta utilizar o comando delete, que funciona de forma idêntica ao da linguagem SQL. Veja um exemplo extraído do arquivo 11_Elimina_Inst_Sem_Turmas.sql: 1. 2. 3. 4. 5. 6.
Create or replace procedure elimina_instrutores_sem_turmas is Begin delete instrutores where cod_instrutor not in (select distinct cod_instrutor from turmas); end;
E uma possível execução: select nome_instrutor from instrutores where cod_instrutor not in (select distinct cod_instrutor from turmas); NOME_INSTRUTOR -----------------------------Matias Agena Luis Becrux exec Elimina_Instrutores_Sem_Turmas; select nome_instrutor from instrutores where cod_instrutor not in (select distinct cod_instrutor from turmas); não há linhas selecionadas
Observação Perceba que NÃO foi emitido o commit na rotina. Neste caso, ficou a cargo do usuário confirmar ou cancelar a operação.
Oracle 9i Fundamental
138
11.5 - SQL Dinâmica Uma limitação apresentada pela linguagem PL/SQL consiste em proibir a execução de comandos DDL (Creates, Drops, Alters, Truncate Table, etc.). Graças ao mecanismo denominado NDS (Native Dynamic SQL), contornase tal restrição. Veja o exemplo seguinte, extraído do arquivo 11_Exemplos_SQL_Dinamica.sql: 1 2 3 4 5 6 7
create or replace procedure LimpaHistorico Is comando varchar(200); Begin comando := 'truncate table historico'; execute immediate comando; end;
E uma possível execução: exec LimpaHistorico;
Observações O grande responsável pela SQL dinâmica é o comando execute immediate; Observe que não foi necessário efetuar um commit, já que o comando truncate table já encerra uma transação em si. Um segundo exemplo extraído do mesmo 11_Exemplos_SQL_Dinamica.sql revela como contar linhas de uma tabela qualquer, cujo nome seria passado por parâmetro: 1. 2. 3. 4. 5. 6. 7. 8. 9.
create or replace function linhastabelas ( tab in varchar2) return integer Is linhas integer; Begin execute immediate 'select count(*) from ' || tab into linhas; return linhas; end;
E uma possível execução no SQL Navigator: select linhastabelas('alunos') from dual;
As possibilidades oferecidas pelo recurso NDS são esplêndidas. Por exemplo, é possível utilizar parâmetros (bind variables) no comando execute immediate. Analise este terceiro exemplo, também extraído de 11_Exemplos_SQL_Dinamica. Ele permite atualizar qualquer campo de qualquer tabela: 1. 2.
create or replace function atualizagenerico ( tab in varchar2,
Oracle 9i Fundamental
139
3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
col in varchar2, valor in varchar2, condicao in varchar2 := null) return integer Is comando varchar(300); Begin comando := 'update '|| tab || ' set ' || col || ' = :valor where ' || nvl(condicao, '1=1'); execute immediate comando using valor; commit; return sql%rowcount; end;
Observações Perceba, na décima linha, a presença da bind variable como :valor. Ela será utilizada na linha seguinte, cláusula using; A expressão sql%rowcount, presente na décima terceira linha, representa a quantidade de linhas afetada pelo último comando DML, no caso, update. Voltaremos a mencioná-la no capítulo 13, Cursores; Exemplo de execução pelo SQL Navigator: declare linhas integer; begin linhas:= atualizagenerico('instrutores', 'tel_instrutor', '9647-1622', 'cod_instrutor=1'); dbms_output.put_line('Atualizadas='||linhas); end;
EXERCÍCIOS 1. Construa uma função que receba um código de curso e devolva o total arreca-dado pelas turmas do curso em questão. • Assuma que todo código fornecido existe. 2. Elabore uma função que receba um código de instrutor e devolva a quantidade de alunos treinados por ele. • Idem exercício 1. 3. Crie uma procedure que insira um novo aluno. • Crie uma sequence para geração automática de matrículas. • Assuma que a cidade será sempre Rio de Janeiro e o estado RJ. 4. Construa uma procedure que permita alterar a cidade de um aluno. 5. Crie uma procedure que aumente, em uma dada porcentagem fornecida, os preços dos cursos que contenham uma dada cadeia de caracteres. • Por exemplo, o seguinte comando: Oracle 9i Fundamental
140
Aumenta_Precos(20, ‘Oracle’);
aumenta em 20% todos os cursos que contenham a palavra ‘Oracle’. 6. Faça uma procedure que exclua alunos que não freqüentaram curso algum. 7. Construa uma procedure que cria um índice qualquer. Deve receber três parâmetros de entrada: o nome do índice, o nome da tabela ao qual será associado e uma cadeia de caracteres representando a lista de campos.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Selecionar uma linha de uma tabela ou visão
Utilize o comando select/into. Caso não seja retor-nada nenhuma linha ou mais de uma, ocorrerão pro-blemas. Veja item 4.1 para maiores detalhes.
Inserir dados em tabelas
Comando insert. Veja item 11.2.
Atualizar um ou mais campos em uma ou mais linhas
Comando update. Veja 11.3.
Excluir uma ou mais linhas de uma tabela
Comando delete. Veja 11.4.
Habilitar a saída em rotinas es-critas com SQL Navigator
No menu Session, escolha Server Output. Isto fará com que os resultados de dbms_output.put_line sejam mos-trados em janelas à parte. No SQL*Plus Worksheet obtém-se efeito análogo alterando a variável de ambiente serveroutput para on. Exemplo: set serveroutput on.
Executar comandos inter-namente a procedure ou função
Comando execute immediate. Veja 11.5.
DDL uma
Oracle 9i Fundamental
141
Capítulo 12 – pl/sql:pl OBJETIVOS •
• •
Expandir as possibilidades de processamento utilizando estruturas de programação que provoquem execução condicional ou repetitiva; Trabalhar com os comandos IF, FOR, WHILE, LOOP e FORALL, além de expressões CASE; Realizar depurações de Unidades de Programa com SQL Navigator.
ARQUIVOS NECESSÁRIOS • • • • • • •
10_Escopo.sql; 11_Retorna_Info_Curso.sql; 12_Classifica_Arrecadado.sql; 12_Alimenta_Historico_For.sql; 12_Alimenta_Historico_While.sql; 12_Alimenta_Historico_Loop.sql; 12_Alimenta_Historico_Forall.sql.
PRÉ-REQUISITOS • • •
Utilizar comandos SQL do tipo DML (Select, Insert, Delete, Update) em Unidades de Programa; Já ter trabalhado com processamento condicional ou repetitivo em alguma linguagem de programação; Conhecer a diferença entre testar e depurar.
TEORIA 12.1 - Processamento Condicional Até o presente momento, toda execução foi seqüencial, ou seja, todos os comandos de uma Unidade de Programa eram executados uma vez. Como qualquer linguagem de programação, a PL/SQL permite relacionar a execução de uma ou mais linhas a condições.
Oracle 9i Fundamental
142
O comando if implementa o processamento condicional. A forma mais elementar é: if condição then comandos executados caso a condição seja Verdadeira end if;
Quando também houver necessidade de processamento, quando a condição for falsa, pode-se utilizar a seguinte variação: if condição then comandos executados caso a condição seja Verdadeira else comandos executados caso a condição seja Falsa end if;
Finalmente, quando houver mais de duas hipóteses (V ou F), existe uma terceira variação: if condição1 then comandos executados caso a condição1 seja Verdadeira elsif condição2 then comandos executados caso a condição2 seja Verdadeira ... else comandos executados caso nenhuma condição testada for Verdadeira end if;
Veja um exemplo extraído do arquivo 12_Classifica_Arrecadado.sql: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
create or replace function classifica_arrecadado return varchar2 Is v_total number := 0; Begin select sum(preco) into v_total from cursos c, turmas t, historico h where c.cod_curso = t.cod_curso and t.cod_turma = h.cod_turma; if v_total < 30000 then return 'Fraco'; elsif v_total < 50000 then return 'Medio'; Else return 'Alto; '; end if; end;
Uma provável ativação seria: begin dbms_output.put_line(Classifica_Arrecadado); end;
Sendo a saída: Medio
Observações Oracle 9i Fundamental
143
Os comandos "subordinados" às condições não foram escritos mais à direita por acaso. Isto se chama indentação23 e representa uma técnica crucial para tornar legíveis os códigos de Unidades de Programas; Uma vez armazenada a função apresentada anteriormente no Servidor, podemos ativá-la pelo SQL*Plus Worksheet: select classifica_arrecadado from dual; CLASSIFICA_ARRECADADO --------------------------------------------------Medio
A condição pode ser expressa por meio de uma variável lógica: ... condicao_fraca boolean; begin ... condicao_fraca := v_total < 3000; if condicao_fraca then return 'Fraco'; elsif ...
Pelo SQL Navigator, a estrutura do comando if pode ser copiada a partir do Code Assistant (menu View, comando Code Assistant), abrindo as pastas Syntax and Web Catalog, PL/SQL Syntax e Conditional Control; Existe um problema na rotina anterior: o que aconteceria se a tabela HISTORICO estivesse vazia? A expressão case, vista no capítulo 3 como responsável pelo processamento condicional em um select, também pode ser utilizada em PL/SQL. Veja uma variante da função anterior, presente no mesmo arquivo: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 23
create or replace function classifica_arrecadado_case return varchar2 Is v_total number := 0; v_resultado varchar2(10); Begin select sum(preco) into v_total from cursos c, turmas t, historico h where c.cod_curso = t.cod_curso and t.cod_turma = h.cod_turma; v_resultado case
:=
Segundo o Dicionário Aurélio, o termo indentar significa "... Espacejar linha, parágrafo, etc. da margem esquerda para a direita...". Assim, devem ser evitadas variações inexistentes, tais como edentação ou identação.
Oracle 9i Fundamental
144
15. 16. 17. 18. 19. 20.
when v_total < 30000 then when v_total < 50000 then else 'Alto; ' end ; return v_resultado; end;
'Fraco' 'Medio'
Muito já se discutiu sobre qual forma (if ou case) seria mais adequada para cada situação. Na verdade, trata-se mais de uma questão de estilo de programação do que propriamente adequação. Quando o processamento consistir em apenas uma atribuição, a estrutura case pode ser utilizada em qualquer caso, porém não podemos utilizar o comando if dentro de um select, como vimos no capítulo 3. Lembre, entretanto, que a estrutura case não permite executar um bloco de comandos em seu interior.
12.2 - Processamento Repetitivo A linguagem PL/SQL oferece quatro formas de implementar o processamento repetitivo. Isto acontece por meio das estruturas for, while, loop e forall. Enquanto a primeira repete um bloco de comandos n vezes, sendo n conhecido, a segunda efetua a iteração mediante um teste. Já a forma loop repete infinitas vezes até que explicitamente seja forçado o fim do laço. Finalmente, a variante forall permite ganhos de performance, como veremos em breve. Em seguida são mostrados códigos de quatro procedures idênticas quanto aos objetivos, porém cada uma utiliza uma forma de repetição diferente.
12.2.1 - FOR O exemplo seguinte consta no arquivo 12_Alimenta_Historico_For.sql. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
create or replace procedure alimenta_historico_for (ultima_turma in number, ultimo_aluno in number) Is Begin delete historico; for i in 1..ultima_turma loop for j in 1..ultimo_aluno loop insert into historico (cod_turma, matricula) values (i,j); end loop; end loop; commit; end;
E uma possível execução: exec Alimenta_Historico_For (5,4)
Comprovando: select count(*) from historico; COUNT(*)
Oracle 9i Fundamental
145
--------20
Observações As variáveis que controlam o número de repetições (i,j) não precisam ser declaradas nem incrementadas; Opcionalmente, podemos ter uma contagem regressiva. A sexta linha pode ser assim escrita: for i in reverse ultima_turma..1 loop
Veja como a indentação deixa evidente a subordinação de comandos; Pelo SQL Navigator, a estrutura do comando for pode ser copiada a partir do Code Assistant pastas Sintax and Web Catalog, PL/SQL Syntax, Iterative Control, item For Loop.
12.2.2 - WHILE O exemplo seguinte consta no arquivo 12_Alimenta_Historico_While.sql. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
create or replace procedure alimenta_historico_while (ultima_turma in number, ultimo_aluno in number) Is v_turma number(2) :=1; v_aluno number(2) :=1; Begin delete historico; while v_turma ultima_turma; end loop; commit; end;
E uma possível execução: exec Alimenta_Historico_Loop(3,4)
Comprovando: select count(*) from historico; COUNT(*) --------12
Observações • •
• •
As variáveis que controlam o número de repetições (v_aluno e v_turma) devem ser declaradas e explicitamente incrementadas; Utilizamos o loop quando a execução de um bloco de comandos depende de uma condição que não permite antever o número de iterações, mas houver pelo menos uma repetição; Condição é a oposta da utilizada pelo while; Caso não seja utilizado o comando exit when, teremos um laço eterno. Isto também ocorreria se a condição nunca fosse satisfeita; Oracle 9i Fundamental
147
•
Pelo SQL Navigator, a estrutura do comando loop pode ser copiada a partir do Code Assistant pastas Sintax and Web Catalog, PL/SQL Syntax, Iterative Control, item Loop. Note que nenhuma estrutura do tipo Exit When será inserida.
12.2.4 - FORALL Durante a execução de um bloco de comandos PL/SQL, dependendo da instrução vigente, ora o controle é passado para o núcleo PL/SQL (PL/SQL engine), ora para o núcleo SQL (SQL Engine). Nas rotinas vistas neste capítulo, há, no pior dos casos 31 mudanças de núcleo24. Isto pode se tornar um sério problema de performance, quando a quantidade de mudanças alcançar valores excessivos. Existe um mecanismo capaz de minimizar essa perda de performance. Trata-se da técnica Bulk Binds, que consiste em pré-armazenar um conjunto de comandos DML (insert, update ou delete) e enviá-los de uma vez ao núcleo SQL. Ela pode ser obtida por meio do comando forall, como visto no exemplo seguinte, que consta no arquivo 12_Alimenta_Historico_ForAll.sql. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
create or replace procedure alimenta_historico_forall (ultima_turma in number, ultimo_aluno in number) is type tlista is table of number index by binary_integer; lista tlista; begin for j in 1..100 loop lista(j) := j; end loop; delete historico; for i in 1..ultima_turma loop forall j in 1..ultimo_aluno insert into historico (cod_turma, matricula) values (i,lista(j)); end loop; commit; end;
E uma possível execução: exec Alimenta_Historico_ForAll(6,5)
Comprovando: select count(*) from historico; COUNT(*) --------30
Observações 24
Isto ocorreu em Alimenta_Historico_While, pois ela foi chamada com os argumentos 6 e 5. Além dos trinta inserts, ainda ocorreu um delete.
Oracle 9i Fundamental
148
•
• •
Para os argumentos utilizados, acontecerão apenas sete mudanças entre núcleos. Isto porque os alunos de cada turma serão inseridos de uma só vez; A estrutura forall admite apenas um comando insert, update ou delete; A utilização de uma variável composta é obrigatória. Note que ela foi inicialmente preenchida e depois seus membros utilizados no insert.
12.3 - Depuração Uma vez concluída a digitação de uma Unidade de Programa e eliminados os erros de compilação (variáveis não declaradas, falta de ponto-e-vírgula, etc.), podem ocorrer erros de lógica, isto é, o resultado da execução difere do que era esperado. Para resolver as anomalias "lógicas", ajuda muito depurar o código. A depuração objetiva identificar a fonte do erro por meio de vários procedimentos: acompanhar a execução comando a comando; verificar o conteúdo de variáveis, eventualmente alterando seus conteúdos; interromper o fluxo em um determinado ponto; etc. Infelizmente, o SQL*Plus Worksheet não oferece nenhuma facilidade de depuração; entretanto, o SQL Navigator possui um conjunto de ferramentas que propicia esta atividade investigativa. Tudo começa pelo estabelecimento do modo de depuração. Isto acontece graças ao comando Session, PL/SQL Debugging. Após carregar a rotina por investigar no Stored Program Editor e recompilá-la, podem-se estabelecer breakpoints (pontos de parada) pelo comando Debug, Toggle Breakpoint. Uma vez disparada a execução e fornecidos os argumentos necessários, os elementos de depuração serão mostrados. A partir daí, utilizando comandos do menu Debug ou pela barra de ferramentas Debug, pode-se executar passo a passo ou até o próximo ponto de parada. Os conteúdos de variáveis podem ser investigados acrescentando watches (Debug, Add Watch). Na figura apresentada em seguida, vemos que a variável v_aluno não teve valor inicial atribuído e um ponto de parada foi estabelecido no segundo while:
Oracle 9i Fundamental
149
Perceba que, ao final da execução, a tabela HISTORICO não terá os alunos da primeira turma, já que o código do aluno era nulo e, por conseqüência, a inserção não pôde ocorrer. Além do comando que dispara a execução (Session, Run), há outros muito úteis sob o menu Debug. Veja um resumo deles: Comando
O que faz
Atalho
Continue
Execução normal.
Run to Cursor
Executar até o cursor.
Trace Into
Mergulhar na rotina corrente o procesF7 samento é desviado.
Step Over
Saltar uma procedure ou function, que são F8 tratadas como se fossem comandos normais.
Trace Out
Voltar à Unidade de Programa que invocou o bloco corrente. Caso não exista bloco Shift + F7 chamador, a execução é interrompida.
Abort Execution
Interromper execução.
Add Watch
Inspeção. Permite-se obter valores correntes Ctrl + F5 de variáveis e até mudá-los.
Toggle Breakpoint
Estabelecer (Breakpoint).
Auto Step Over
Executa passo a passo, mas de forma Shift + Ctrl + automática. F8
Auto Trace Into
Executa passo a passo, automaticamente, Shift + Ctrl + mas entrando nas procedures e function. F7
Pause Auto Stepping
Pausa na execução automática.
um
F4
ponto
Shift + Ctrl + F9
de
Oracle 9i Fundamental
parada
F5
Ctrl + Alt + P
150
Lembre-se que para cada comando apresentado anteriormente, existe associado um botão nas barras de ferramentas.
EXERCÍCIOS 1. Elabore uma função que receba dois números e devolva o maior. 2. Altere a procedure Retorna_Info_Curso para que emita uma classificação do curso mediante seu preço: Barato (menos que 300), Médio (entre 301 e 600) e Caro (mais que 601). • Avalie a necessidade de utilizar o comando IF com ELSIF ou não. 3. Crie uma função que receba um número entre 1 e 12 e mostre o nome do mês equivalente. • Assuma que a entrada pode ser incorreta. • Utilize um vetor para armazenar o nome dos meses. • Aproveite o exercício 2 do capítulo 3. 4. Crie uma procedure que receba um número por parâmetro e mostre a soma de seus divisores. 5. Faça uma procedure que receba um número por parâmetro e mostre quantos primos menores existem. 6. Depure a rotina que consta em 10_Escopo.sql, acompanhando o valor das variáveis.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Efetuar processamento condicional
Utilize a estrutura de programação if/then/elsif/else/end if.
Repetir um bloco de comandos várias vezes cujo número de iterações é conhecido
Estrutura for/in/loop/end loop
Repetir um bloco de comandos várias vezes cujo número de iterações NÃO é conhecido
Estrutura while/loop/end loop
Repetir um bloco de comandos várias vezes cujo número de iterações NÃO é conhecido, porém há pelo menos uma execução
Estrutura loop/exit when/end loop
Aumentar a eficiência de uma iteração, impe-dindo que o núcleo PL/SQL (PL/SQL Engine) invoque repetidas vezes o núcleo SQL (SQL Engine)
Comando forall
Oracle 9i Fundamental
151
Tarefa
Depurar
Como fazer Ligue o modo de depuração (Session, PL/SQL Debugging), carregue a rotina no Stored Program Editor, compile-a e exe-cute-a a partir do SQL Editor. Os princi-pais comandos de depuração encontramse sob o menu Debug. Ao final, não se esqueça de desligar o modo de depuração (Debug, PL/SQL Debugging).
Oracle 9i Fundamental
152
Capítulo 13 – CURSORES OBJETIVOS • • • • •
Compreender o conceito de cursor; Identificar situações em que a utilização de cursores resulta imprescindível; Trabalhar com cursores implícitos ou explícitos; Criar um cursor dinâmico; Realizar leituras ou atualizações em tabelas via cursores.
ARQUIVOS NECESSÁRIOS • • • • • • • • •
13_Classifica_Cursos.sql; 13_Exemplo_Cursor_Implicito.sql; 13_Exemplo_Cursor_Implicito_2.sql; (bulk bind) 13_Exemplo_Cursor_Explicito_1.sql; 13_Exemplo_Cursor_Explicito_2.sql; (cursor parametrizado) 13_Exemplo_Cursor_Explicito_3.sql; (usando FOR) 13_Exemplo_Cursor_Explicito_4.sql; (SQL dinâmica) 13_Cria_Tabela_Turmas_Cursos.sql; 13_Exemplo_Cursor_Atualizacao.sql.
PRÉ-REQUISITOS • •
Utilizar comandos SQL do tipo DML (Select, Insert, Delete, Update) em Unidades de Programa; Resolver problemas envolvendo processamento condicional ou repetitivo.
MOTIVAÇÃO Exemplo de processamento precisando Cursores A rotina seguinte classifica todos os cursos, segundo o preço: 1. 2. 3.
PROCEDURE Classifica_Cursos IS v_qtos_cursos number(3) := 0;
Oracle 9i Fundamental
153
4. v_curso_corrente number(3) := 1; 5. v_nome_curso cursos.nome_curso%type; 6. v_preco cursos.preco%type; 7. v_classifica varchar2(10); 8. 9. BEGIN 10. select count(*) 11. into v_qtos_cursos 12. from cursos; 13. 14. for i in 1..v_qtos_cursos loop 15. select nome_curso, preco 16. into v_nome_curso, v_preco 17. from cursos 18. where cod_curso = i; 19. if v_preco < 300 then 20. v_classifica := 'Barato'; 21. elsif v_preco < 600 then 22. v_classifica := 'Médio'; 23. else 24. v_classifica := 'Caro'; 25. end if; 26. dbms_output.put_line ('Curso: '|| v_nome_curso || ' é ' || v_classifica); 27. end loop; 28. 29. END;
A rotina anterior apresenta basicamente dois problemas bastante sérios: Assume que os códigos de cursos começam por 1 e são seqüenciais; Se houver, digamos, vinte cursos, existirão vinte acessos ao Servidor via comando select/into. Uma possível "melhoria" pode ser a criação de uma tabela espelho de cursos e a localização do menor código cujo registro deve ser eliminado após a classificação. O processo será repetido até que não restem mais registros.
TEORIA 13.1 - Fundamentos Um cursor representa uma tabela temporariamente armazenada em memória e criada como resultado dos comandos: select, insert, update, delete, commit ou rollback. Ele contém os registros afetados pelo comando que provocou sua criação. Existem dois tipos de cursor: o implícito, que dispensa qualquer tipo de tratamento, e o explícito, gerado apenas pelo select, que deve ser declarado e manipulado via comandos próprios. Criando um cursor explícito, podemos carregar o conteúdo de uma tabela em memória sem precisar emitir tantos select/into quantos forem os registros da tabela. Há quatro atributos que podem ser utilizados tanto por cursores implícitos quanto explícitos:
Oracle 9i Fundamental
154
sql%rowcount
Informa quantas linhas foram afetadas pelo comando que gerou o cursor.
sql%found
Será true caso alguma linha tenha sido afetada.
sql%notfound
Será false caso alguma linha tenha sido afetada.
sql%isopen
Será true caso o cursor esteja aberto. Somente faz sentido para cursores explícitos.
No caso de cursores explícitos, o prefixo sql será substituído pelo nome da variável representando o cursor. A rotina seguinte exemplifica a utilização de um cursor implícito. Ela consta no arquivo 13_Exemplo_Cursor_Implicito.sql: 1. create or replace function exclui_instrutores_cursor_imp 2. return varchar2 3. is begin 4. 5. delete instrutores 6. where cod_instrutor not in 7. (select distinct cod_instrutor from turmas); if sql%found then 8. return ('Foram eliminados: '|| to_char(sql%rowcount) || ' instrutores'); 9. 10. else 11. return ('Nenhum instrutor eliminado.'); 12. end if; 13. end;
Pelo SQL Navigator, a função anterior pode ser invocada em uma janela SQL Editor utilizando os comandos: declare saida varchar2(40); begin saida := exclui_instrutores_cursor_imp; dbms_output.put_line('Saida: '||saida); end;
Quando houver bulk binds, ainda pode-se utilizar o atributo composto sql%bulk_rowcount(n) que informa quantas linhas foram afetadas no n-ésimo comando subordinado à estrutura forall. O próximo exemplo utiliza cursores impícitos junto com bulk bind. Ele consta no arquivo 13_Exemplo_Cursor_Implicito_2.sql: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
create or replace procedure aumenta_preco_hora_instrutor is type lista_instrutores is table of number; instrutores lista_instrutores:= lista_instrutores (1, 2, 5, 6); i integer; begin forall i in instrutores.first..instrutores.last update turmas set preco_hora_instrutor = preco_hora_instrutor * 1.10 where cod_instrutor = instrutores(i); -- Mostra quantas linhas afetou cada update for i in instrutores.first..instrutores.last loop dbms_output.put_line ('Turmas afetadas pelo instrutor: '|| to_char(instrutores(i)) || ' é ' || to_char(sql%bulk_rowcount(i))); end loop; end;
Oracle 9i Fundamental
155
Observações •
• •
Existem algumas novidades no exemplo apresentado anteriormente. Em primeiro lugar, preencheu-se a lista de códigos de instrutores (linha 4) de uma forma inédita, utilizando um construtor. Mais detalhes no capítulo 17; Observe como os itens da lista foram percorridos, ou seja, aproveitando as propriedades first e last do vetor; Finalmente, utiliza-se o atributo composto bulk_rowcount para identificar a n-ésima linha alterada.
13.2 - Cursores Explícitos Quando for necessário carregar vários registros em memória, devem-se utilizar cursores explícitos, que são manipulados por meio de três comandos: open
Cria fisicamente a tabela temporária e posiciona o ponteiro de leitura no primeiro registro.
fetch
Carrega para variáveis locais o conteúdo da linha indicada pelo ponteiro de leitura.
close
Fecha o cursor.
Antes que um cursor explícito possa ser utilizado, deve-se declarar o comando select que proporcionará o conjunto de linhas. O exemplo seguinte resolve novamente o problema apresentado na Motivação, porém, desta vez, com cursor explícito. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
create or replace procedure Classifica_Cursos_Cur_Exp IS cursor ccursos is select nome_curso, preco from cursos; V_nome_curso V_preco V_classifica
cursos.nome_curso%type; cursos.preco%type; varchar2(10);
begin
open ccursos; fetch ccursos into v_nome_curso, v_preco; while ccursos%found loop if v_preco < 300 then v_classifica := 'Barato'; elsif v_preco < 600 then v_classifica := 'Médio'; else v_classifica := 'Caro'; end if; dbms_output.put_line('Curso: '|| v_nome_curso || ' é ' || v_classifica); 21. fetch ccursos into v_nome_curso, v_preco;
Oracle 9i Fundamental
156
22. 23. 24.
end loop; close ccursos; End;
Com SQL Navigator, um exemplo de ativação e saída pode ser: begin Classifica_Cursos_Cur_Exp; end;
E a saída, na guia spool: *** SCRIPT START : Session:MORELLI@CONTACAD(2) Processing ... begin Classifica_Cursos_Cur_Exp; end;
22-fev-2002 22:02:16 ***
Curso: Introdução à Lógica de Programação é Caro Curso: Fundamentos da Modelagem de Dados é Caro Curso: Redes I é Barato Curso: Introdução a Sistemas Operacionais é Barato Curso: Análise Orientada por Objetos é Barato Curso: Delphi: Recursos Básicos é Médio Curso: Delphi: Acesso a Bancos de Dados é Médio Curso: Oracle: SQLPlus e SQL é Caro Curso: Oracle: PL/SQL é Caro Curso: Redes II é Barato *** SCRIPT END : Session:MORELLI@CONTACAD(2) 22-fev-2002 22:02:16 ***
Observações • •
•
As linhas em destaque na procedure evidenciam as operações: declaração, abertura, leitura e fechamento; Observe como o atributo %found foi utilizado para controlar o fim do laço. Agora não é necessário conhecer de antemão o número de registros, nem preocupar-se com a seqüencialidade dos códigos; Eventualmente, um cursor pode ser parametrizado. Por exemplo, suponha que desejamos filtrar os cursos que não atingem um determinado preço:
1. create or replace procedure Class_Cursos_Cur_Exp_Param 2. (v_valor_minimo number) 3. IS cursor ccursos (v_valor_minimo in number) is 4. 5. select nome_curso, preco from cursos 6. where preco > v_valor_minimo; 7. 8. BEGIN 9. open ccursos (v_valor_minimo); fetch ccursos into v_nome_curso, v_preco; 10.
Oracle 9i Fundamental
157
• • •
A saída mostrará apenas os cursos cujo preço seja maior que o valor for-necido via parâmetro; O código anterior encontra-se em 13_Exemplo_Cursor_Explicito_2.sql; Pelo SQL Navigator, diversos exemplos de manipulação de cursores explícitos podem ser arrastados a partir do Code Assistant (menu View, comando Code Assistant), abrindo as pastas Syntax and Web Catalog, PL/SQL Syntax e Explicit Cursor.
A procedure Classifica_Cursos_Cur_Exp pode ser reescrita utilizando um laço for: 1. create or replace procedure class_cursos_cur_exp_for 2. Is 3. cursor ccursos is select nome_curso, preco from cursos; 4. 5. 6. V_classifica varchar2(10); 7. 8. Begin for reg_curso in ccursos loop 9. if reg_curso.preco < 300 then 10. 11. v_classifica := 'Barato'; 12. elsif reg_curso.preco < 600 then 13. v_classifica := 'Médio'; Else 14. 15. v_classifica := 'Caro'; 16. end if; 17. dbms_output.put_line ('Curso: '|| 18. reg_curso.nome_curso || ' é ' || v_classifica); 19. end loop; 20. end;
Observações Note que não foi necessário abrir, ler ou fechar o cursor. E ainda dispen-samos as variáveis locais que receberiam conteúdos de campos. Estas simpli-ficações seriam inviáveis caso o cursor fosse parametrizado; O código apresentado anteriormente se encontra em: 13_Exemplo_Cursor_Explicito_3.sql. Uma forma de flexibilizar rotinas que possuam cursores consiste em utilizar a novíssima técnica NDS (Native Dynamic SQL), já vista no capítulo 11. O exemplo seguinte aceita filtros que sejam baseados em um ou mais campos da tabela CURSOS: 1. 2. 3. 4. 5. 6.
create or replace procedure class_cursos_sql_dinamica (ent_filtro varchar2 := null) Is type tpCursor_Dinamico is ref cursor; v_cursor tpCursor_Dinamico ; v_nome_curso cursos.nome_curso%type;
Oracle 9i Fundamental
158
7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
v_preco cursos.preco%type; v_classifica varchar2(10); v_comando varchar2(100); Begin v_comando := 'select nome_curso, preco from cursos where ' || nvl(ent_filtro, '1=1') ; open v_cursor for v_comando; fetch v_cursor into v_nome_curso, v_preco; while v_cursor%found loop if v_preco < 300 then v_classifica := 'Barato'; elsif v_preco < 600 then v_classifica := 'Médio'; Else v_classifica := 'Caro'; end if; dbms_output.put_line ('Curso: '|| v_nome_curso || ' é ' || v_classifica); fetch v_cursor into v_nome_curso, v_preco; end loop; close v_cursor ; end;
Observações Possíveis ativações da rotina anterior: begin class_cursos_sql_dinamica ('carga_horaria > 32'); end; begin class_cursos_sql_dinamica ('preco > 0'); end; begin class_cursos_sql_dinamica ; end;
Como o comando SQL não é conhecido em tempo de compilação, devese criar uma variável dinâmica, ou ponteiro. Isto explica a declaração na quarta linha, na qual se especifica um tipo cujas variáveis serão ponteiros para outras variáveis; Note que o comando open (linha 12) apresenta uma pequena variação: a cláusula for; O código anterior se encontra em: 13_Exemplo_Cursor_Explicito_4.sql.
13.3 - Cursores de Atualização As linhas retornadas por um cursor explícito podem ter seus conteúdos alterados também. Imagine que seja necessário reajustar em 10% os preços dos cursos que tiveram três ou mais turmas, e dar um desconto de 10% para aqueles que tiveram uma ou duas turmas. Como resulta impossível atualizar uma visão que contenha dados agrupados, criaremos uma tabela auxiliar: Oracle 9i Fundamental
159
create table turmas_cursos as select c.cod_curso cod_curso, preco, count(cod_turma) turmas from cursos c, turmas t where c.cod_curso = t.cod_curso group by c.cod_curso, preco;
O código anterior se encontra no arquivo 13_Cria_Tabela_Turmas_Cursos.sql. Analise a procedure responsável pela atualização: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
create or replace procedure atualiza_precos_com_cursor Is cursor ccursos is select cod_curso,preco, turmas from turmas_cursos for update of preco nowait; Begin for linha_corrente in ccursos loop if linha_corrente.turmas > 2 then update turmas_cursos set preco = preco * 1.1 where current of ccursos; Else update turmas_cursos set preco = preco * 0.9 where current of ccursos; end if; end loop; /* Atualização da tabela Cursos */ /* Os cursos que não têm turmas não podem ser alterados */ update cursos c set preco = (select preco from turmas_cursos where cod_curso = c.cod_curso) where cod_curso in (select cod_curso from turmas_cursos); end;
Observações • • • •
Concluída a execução da rotina anterior, deve-se emitir um commit para ratificar as mudanças; Apenas um campo pode ser atualizado; A cláusula nowait causa uma exceção tratável caso a tabela esteja bloqueada por outro usuário; Além de update, também pode-se utilizar o comando delete: ... delete tabela where current of cursor; ...
•
•
Note a subquery correlata que atualiza a tabela CURSOS mediante os valores de Turmas_Cursos. Sem o filtro da linha 23, os preços dos cursos que não tenham turmas seriam alterados para NULL; Um cursor não precisa ser a imagem exata de uma tabela, isto é, podem existir menos colunas e linhas do que na tabela referenciada. Oracle 9i Fundamental
160
EXERCÍCIOS 1. Faça uma procedure que atribua a nota 8 aos alunos que freqüentaram cursos de Delphi e informe quantos registros foram alterados. 2. Parametrize a procedure Classifica_Cursos_Cur_Exp para que somente sejam tratados cursos de Oracle. • Como seria para que o usuário escolha o tipo de curso? (Oracle, Delphi, Redes, etc.); • E como seria possível ao usuário a escolha de qualquer filtro, sobre qualquer campo? 3. Execute a procedure Atualiza_Precos_Com_Cursor, tendo a tabela Turmas_Cursos bloqueada por outra sessão. • Analise a mensagem exibida. O que acontece se não houver a cláusula nowait? 4. Acrescente um novo campo à tabela INSTRUTORES, denominado OBSOLESCÊNCIA, depois faça uma rotina que o atualize segundo o critério seguinte: • BAIXA, caso o instrutor tenha ministrado mais de duas turmas; • MÉDIA, para uma ou duas turmas; e • ALTA, para zero turmas. 5. Aumente em 20% os preços dos cursos que forem maiores que a média dos preços de todos os cursos, e abata 10% dos preços que forem menores que essa média.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Manipular um cursor implícito
Após algum dos comandos: select, delete, update, insert, commit ou rollback, investigue os atributos sql%found, sql%notfound ou sql%rowcount.
Declarar um cursor explícito
Use o comando: cursor nome_cursor is comando SELECT.
Abrir um cursor
Comando: open nome_cursor (lista opcional de parâmetros).
Ler conteúdo da linha corrente de um cursor
Comando: fetch nome_cursor into lista de variáveis Deve haver tantas variáveis quanto a quantidade de campos citados no comando select.
Oracle 9i Fundamental
161
Tarefa
Como fazer
Fechar um cursor
Comando: close nome_cursor Para checar se o cursor está realmente aberto, podese utilizar o atributo nome_cursor%isopen.
Simplificar a utilização de cursores
Utilize com a estrutura for. Veja a rotina-exemplo que consta no arquivo 13_Exemplo_Cursor_Explicito_3.sql.
Atualizar linhas de uma tabela via cursor
Acrescente a cláusula for update of campo à declaração. Veja a rotina-exemplo em 13_Exemplo_Cursor_Atualizacao.
Oracle 9i Fundamental
162
Capítulo 14 – EXCEÇÕES OBJETIVOS • • • •
Compreender o conceito de Exceção; Identificar situações em que o tratamento de Exceções melhora a interatividade; Diferenciar os tipos de Exceção trabalhados pelo Oracle; Implementar o código tratador de Exceção.
ARQUIVOS NECESSÁRIOS • • • • •
14_Retorna_Info_Curso_Tratada.sql; 14_Insere_Instrutor_Tratada.sql; 14_Matricula_Aluno_com_Raise; 14_Matricula_com_Raise_App_Error; 14_Matricula_com_Bloco_Anonimo.
PRÉ-REQUISITOS • • •
Utilizar comandos SQL do tipo DML (Select, Insert, Delete, Update) em Unidades de Programa; Resolver problemas envolvendo processamento condicional ou repetitivo; Identificar tipos de erro possíveis: compilação, ambiente e lógica.
TEORIA 14.1 - Fundamentos Uma exceção representa uma interrupção anormal no processamento de uma procedure ou função. Por exemplo, caso tente-se inserir uma chave duplicada em uma tabela ou dividir um número por zero, o Oracle não permitirá que a execução continue e ainda emitirá mensagens nada amistosas. Felizmente, podem-se tratar esses erros, identificando-os e produzindo mensagens mais compreensíveis ao usuário. Ao tratar exceções, além de tornar as Unidades de Programa mais amigáveis, a execução não é interrompida! Oracle 9i Fundamental
163
Existem três tipos de exceção: Predefinidas
Uma vintena de erros que de tão comuns, ganharam nome;
Não predefinidas
Demais erros Oracle;
Definidas pelo usuário
Úteis para tratar regras de negócio.
Toda exceção é tratada na seção exception de um bloco: [declare] . . declarações . . begin . . comandos . . EXCEPTION WHEN exc1 [or exc2 ... or excn] THEN comandos que tratam as exceções identificadas pelos nomes exc1, exc2,...,excn. WHEN exc3 [or exc4 ... or excn] THEN . . comandos tratadores de outras exceções . ... WHEN others . . comandos que tratam erros não mencionados anteriormente . . END;
14.2 - Exceções Predefinidas Erros mais freqüentes têm nomes. A tabela seguinte mostra alguns dos existentes25.
25
Erro
Nome
Observações
ORA-00001
DUP_VAL_ON_INDEX
valor de índice duplicado (chaves primárias) ou campos indexados como unique
Para conhecer todos os erros, investigue a visão all_source. O comando seguinte pode fazer isto: select substr(text,1,60) from all_source where name = 'STANDARD' AND lower(TEXT) LIKE '%exception%'
Oracle 9i Fundamental
164
ORA-01403
NO_DATA_FOUND
select/into não retornou linha alguma
ORA-01012
NOT_LOGGED_ON
Tentativa de execução de um comando fora de uma sessão
ORA-01422
TOO_MANY_ROWS
select/into retornou mais de uma linha
ORA-01476
ZERO_DIVIDE
Divisão por zero
O exemplo seguinte, extraído do arquivo 14_Retorna_Info_Curso_Tratada.sql, reescreve a rotina Retorna_Info_Curso com tratamento de erros: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24.
create or replace function Retorna_Info_Curso_Tratada (v_ch in cursos.carga_horaria%type) return varchar2 Is v_nome cursos.nome_curso%type; v_preco cursos.preco%type; msg varchar2(60); Begin select nome_curso, preço into v_nome, v_preco from cursos where carga_horaria = v_ch; return ('curso: '|| v_nome || chr(10) || 'preço: '|| to_char(v_preco)); Exception when no_data_found then return ('Nenhum curso possui carga horária especificada'); when too_many_rows then return ('Muitos cursos possuem carga horária especificada'); when others then msg := 'Erro desconhecido: ' || to_char(sqlcode); return (msg); end;
Exemplo de ativação e saída no SQL*Plus Worksheet pode ser: variable texto varchar2(60) exec :texto := Retorna_Info_Curso_Tratada(32); print texto
Saída: TEXTO -----------------------------------------------------Muitos cursos possuem carga horária especificada
Outro exemplo: exec :texto := Retorna_Info_Curso_Tratada(0); print texto
Saída: TEXTO
Oracle 9i Fundamental
165
-----------------------------------------------------Nenhum curso possui carga horária especificada
Observações •
• •
sqlcode e sqlerrm são duas funções embutidas (uma numérica e outra textual) que retornam o código de erro gerado e a respectiva mensagem; A função chr(10) provoca salto de linha; Podemos realizar a ativação por meio do SQL Navigator também:
BEGIN DBMS_OUTPUT.PUT_LINE(Retorna_Info_Curso_Tratada(48)); END;
e a saída: Nenhum curso possui Carga Horária especificada
•
Caso uma rotina não tenha tratamento de exceções, o Oracle verifica a rotina chamadora.
14.3 - Exceções não Predefinidas Para tratar das outras milhares de exceções, devem-se conhecer de antemão os números dos prováveis erros que podem ocorrer. Caso não sejam conhecidos, podem ser utilizadas as funções sqlcode e sqlerrm, como visto no último exemplo. A rotina seguinte, extraída do arquivo 14_Insere_Instrutor_Tratada.sql é uma versão melhorada da procedure Insere_Instrutor: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
create or replace function Insere_Instrutor_Tratada (v_nome in instrutores.nome_instrutor%type, v_tel in instrutores.tel_instrutor%type, v_adm in instrutores.admissao%type) RETURN varchar2 IS nome_nulo exception; pragma exception_init (nome_nulo, -1400); BEGIN insert into instrutores values (Gera_Cod_instrutor.Nextval, v_nome, v_tel,v_adm); commit; return ('Inclusão OK!'); EXCEPTION when nome_nulo then return ('Não foi possível incluir: nome nulo.'); when others then return ('Erro desconhecido: ' || to_char(sqlcode)); END;
Cuidado A função apresentada anteriormente mostra um erro de compilação, Oracle 9i Fundamental
166
caso tenha sido concluído o quarto exercício do capítulo anterior, que inseria uma nova coluna (OBSOLECENCIA) na tabela de instrutores. Para corrigi-la, basta especi-ficar um valor para esse campo na linha 11;
Vejamos uma provável ativação pelo SQL*Plus Worksheet: var texto char(50) exec :texto := Insere_Instrutor_Tratada(null,'455-7877',sysdate); print texto TEXTO --------------------------------------------------------------Não foi possível incluir: nome nulo.
Observações Veja a variável nome_nulo do tipo exceção; Na linha 8 realizamos a conexão entre a variável previamente declarada e o número do erro (negativo) que se deseja tratar; Caso não se conheça o erro, ele será capturado pela cláusula when others. Por exemplo: TEXTO ----------------------------Erro desconhecido: -nnnn
14.4 - Exceções Definidas pelo Usuário O tratamento de exceções não está limitado aos erros nativos do Oracle. Regras de Negócio também podem ser tratadas em stored procedures. Por exemplo, suponha que seja decidido um limite para a quantidade de alunos por turma, digamos, dez. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
create or replace function Matricula_Aluno_com_Raise (v_turma in historico.cod_turma%type, v_matricula in historico.matricula%type, v_nota in historico.nota%type default null) RETURN varchar2 IS MAX_ALUNOS constant integer := 10; v_alunos_na_turma integer; turma_cheia exception; BEGIN select count(matricula) Into v_alunos_na_turma From historic where cod_turma = v_turma; if v_alunos_na_turma = MAX_ALUNOS then raise turma_cheia; Else insert into historico values (v_turma, v_matricula, v_nota); commit; return ('Inclusão OK!');
Oracle 9i Fundamental
167
23. 24. 25. 26. 27. 28. 29.
end if; EXCEPTION When turma_cheia then return ('Não foi possível incluir: turma_cheia.'); When others then return ('Erro desconhecido: ' || to_char(sqlcode)); END;
E uma ativação no SQL*Plus Worksheet : var texto varchar2(80) exec :texto := Matricula_Aluno_com_Raise(1,20); print texto
Assumindo que a turma de código 1 já tivesse dez alunos, teríamos como saída: TEXTO -----------------------------------------------------Não foi possível incluir: turma_cheia.
Observações Esta função encontra-se no arquivo 14_Matricula_Aluno_com_Raise.sql; Assuma que o código de turma e a matrícula fornecidos estejam corretos; Note como a exceção foi declarada, provocada e tratada. Veja em seguida uma forma mais compacta de tratamento de exceções de usuário: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
create or replace function Matricula_com_Raise_App_Error (v_turma in historico.cod_turma%type, v_matricula in historico.matricula%type, v_nota in historico.nota%type default null) RETURN varchar2 IS MAX_ALUNOS constant integer := 10; v_alunos_na_turma integer; BEGIN select count(matricula) into v_alunos_na_turma from historico where cod_turma = v_turma; if v_alunos_na_turma >= MAX_ALUNOS then raise_application_error (-20500, 'Turma_cheia'); Else insert into historico values (v_turma, v_matricula, v_nota); commit; return ('Inclusão OK!'); end if; END;
E uma ativação: exec :texto := Matricula_com_Raise_App_Error(10,21);
Oracle 9i Fundamental
168
Saída: begin :texto := Matricula_com_Raise_App_Error(10,21); end; * ERROR at line 1: ORA-20500: Turma_cheia ORA-06512: at "MORELLI.MATRICULA_COM_RAISE_APP_ERROR", line 14 ORA-06512: at line 1
Observações A função apresentada encontra-se no arquivo 14_Matricula_com_Raise_App_Error.sql; O número do erro fornecido deve ser maior que 20.000 (último erro Oracle); Se por um lado a saída não foi muito elegante, note que não houve necessidade de declaração da exceção, nem de tratamento.
14.5 - Exceções em Blocos Anônimos À medida que o corpo das rotinas cresce, percebe-se a necessidade de realizar tratamento de erros de uma forma mais localizada, ou seja, mais próximo à causa do problema. A rotina seguinte, extraída do arquivo 14_Matricula_com_Bloco_Anonimo.sql, evita a inclusão de uma linha cuja chave primária já exista: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
create or replace function MATRICULA_COM_BLOCO_ANONIMO (v_turma in historico.cod_turma%type, v_matricula in historico.matricula%type, v_nota in historico.nota%type default 0) RETURN varchar2 IS MAX_ALUNOS constant integer := 10; v_alunos_na_turma integer; turma_cheia exception; BEGIN select count(matricula) into v_alunos_na_turma from historico where cod_turma = v_turma; if v_alunos_na_turma = MAX_ALUNOS then raise turma_cheia; else begin insert into historico values (v_turma, v_matricula,v_nota); commit; exception when DUP_VAL_ON_INDEX then update historico set nota = v_nota where matricula = v_matricula
Oracle 9i Fundamental
169
27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37.
and cod_turma = v_turma; end; return ('Operação OK!'); end if; EXCEPTION when turma_cheia then return ('Não foi possível incluir: turma_cheia.'); when others then return ('Erro desconhecido: ' || to_char(sqlcode)); END;
Observações •
A função anterior objetiva inserir linhas na tabela HISTORICO, entretanto, caso a dupla matrícula-código da turma já exista, assume-se que se deseja simplesmente atualizar uma linha previamente carregada.
EXERCÍCIOS 1. Faça uma procedure que exclua um determinado aluno, mas impeça a operação, caso o aluno esteja matriculado em alguma turma. • O código gerado por violações de integridade referencial é –2292. 2. Construa uma procedure que cancele a matrícula de um determinado aluno. Caso ele não exista na turma especificada, emitir uma mensagem. • Lembre-se que o comando DELETE não provoca erro, caso nenhum registro tenha sido excluído. 3. Trate a procedure Atualiza_Precos_Com_Cursor de forma a emitir uma mensagem amigável, caso a tabela esteja bloqueada. 4. Construa a função Matricula_Aluno_com_Raise mais robusta, prevendo turma ou aluno inexistentes. 5. Reflita: convém pulverizar o tratamento de erros em todas as Unidades de Programa do Banco, ou será melhor criar uma procedure especial que seria invocada sempre que acontecesse um erro? 6. Outra reflexão: de que maneira poderíamos utilizar os conhecimentos adquiridos neste capítulo para "acompanhar" a execução de uma longa rotina? Imagine uma procedure com umas cem linhas; não seria interessante incluir a cada fim de funcionalidade um bloco anônimo que emitisse "raises" para avisar que o processamento chegou em um determinado ponto em um dado instante? Desta forma, poderíamos rapidamente identificar "gargalos" na execução, ou seja, trechos de código cuja execução estaria demorando mais do que o razoável. Isto nos permitira "atacar" porções menores de código com intuito de melhorar-lhe a performance.
Oracle 9i Fundamental
170
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Identificar o código de erro
Execute a rotina sem tratamento de exceções e anote os erros que ocorrem. Uma forma alternativa é utilizar a cláusula when others na seção EXCEPTION.
Tratar uma exceção pre-definida pelo Oracle
Após identificar o erro predefinido que aconteceu, na seção EXCEPTION, utilize a cláusula when nome_erro seguida de algum comando informativo. Veja um exemplo na função: Retorna_Info_Curso_Tratada.
Tratar uma exceção que não seja predefinida pelo Oracle
Siga o roteiro: Declare uma variável do tipo exception; Associe essa variável ao código do erro que se deseja tratar; Crie uma entrada na seção EXCEPTION com o nome da exceção criada. Veja um exemplo na função: Insere_Instrutor_Tratada.
Tratar exceções que representem Regras de Negócio do Banco
Siga o roteiro: Declare uma variável do tipo exception; Quando o erro acontecer, utilize o comando raise nome_exceção; Crie uma entrada na seção EXCEPTION com o nome da exceção criada. Veja um exemplo na função: Matricula_Aluno_com_Raise.
Oracle 9i Fundamental
171
ANOTAÇÕES
Oracle 9i Fundamental
172
Capítulo 15 – PACKAGES OBJETIVOS • • • • • • •
Compreender o conceito de Package; Identificar situações em que a utilização de Packages melhora a administração de Unidades de Programa; Construir um Package: especificação e corpo; Ativar membros de um Package; Avaliar os riscos de alterar objetos manipulados por membros de um Package; Diferenciar os tipos de Packages; Utilizar alguns Packages embutidos, tais como DBMS_JOB e DBMS_LOB.
ARQUIVOS NECESSÁRIOS • • • • • • • • • • • • •
15_Especifica_Pack_Inst.sql; 15_Especifica_Pack_Body_Inst.sql; 15_Lista_Status.sql; 15_Mostra_Dependencias.sql; Utldtree.sql; 15_Exemplos_DBMS_JOB.sql 15_Prepara_para_DBMS_LOB.sql; 15_Testa_DBMS_LOB_WRITE.sql; 15_Testa_DBMS_LOB_READ.sql; 15_Testa_DBMS_LOB_SUBSTR.sql; 15_Testa_DBMS_LOB_INSTR.sql; 15_Testa_DBMS_LOB_WRITEAPPEND.sql; 15_Testa_DBMS_LOB_ERASE.sql.
PRÉ-REQUISITOS • • •
Utilizar comandos SQL do tipo DML (Select, Insert, Delete, Update) em Unidades de Programa; Resolver problemas envolvendo processamento condicional ou repetitivo; Diferenciar procedure de function. Oracle 9i Fundamental
173
TEORIA 15.1 - Fundamentos À medida que avançamos na produção de procedures e functions, constatamos que muitas mantêm algum tipo de relacionamento entre si. Por exemplo, nos exercícios do capítulo 11, foram desenvolvidas três rotinas que manipulavam a tabela Alunos: inserção, alteração de cidade e exclusão26. Ora, seria muito mais interessante se pudéssemos, de alguma forma, "agrupá-las" fisicamente. Esse empacotamento é comum em outras linguagens. Por exemplo, a C++ oferece dois tipos de arquivos: um para declarações (extensão .H) e outro para imple-mentações (.CPP). Já a Object Pascal possui arquivos únicos (units), porém divididos em duas seções: interface e implementation. PL/SQL possui os Packages que representam Unidades de Programa, contendo uma coleção de procedures, functions, exceções, estruturas de dados (vetores, registros, tipos, objetos), cursores ou declarações de variáveis comuns. Todo package divide-se em dois objetos de Banco: Especificação (Package)
Determina o que o Package oferece ao mundo exterior. Consiste em diversas declarações.
Corpo (Package Body)
Informa como o Package interage com o mundo exterior, isto é, possui os códigos das procedures e functions públicas (declaradas na Especificação) ou privativas (não declaradas).
As vantagens obtidas na utilização de Packages são várias: 1. Simplifica-se a gerência de código, já que, em vez de cinco, seis rotinas que manipulam uma tabela, teremos apenas dois objetos: uma Especificação e um Corpo; 2. O agrupamento de rotinas e variáveis em torno de uma tabela transforma o Projeto Físico, tornando-o mais intuitivo, mais próximo dos Projetos Conceitual e Lógico; 3. A manutenção é facilitada, já que as conseqüências de mudanças em tabelas podem ser facilmente "isoláveis"; 4. O encapsulamento ganho ao "esconder" a implementação do mundo exterior proporciona mais flexibilidade ao desenvolvimento do código, já que mudanças no Corpo são imperceptíveis externamente; 5. Ganha-se em performance, já que a ativação de qualquer membro do package faz com que todo o conjunto seja carregado em memória, ou seja, subseqüentes chamadas a componentes não causam idas a disco.
26
Consulte a seção Exercícios do capítulo 11, números 3, 4 e 6.
Oracle 9i Fundamental
174
Antes de criar um package, devemos reunir os elementos que manipulam uma determinada tabela (procedures, functions, cursores, etc.). Depois, há que se determinar quais poderão ser vistos externamente e quais não. Muito cuidado deve-se tomar quanto ao tamanho do package. Caso sejam muito grandes, a SGA será sobrecarregada desnecessariamente. Existem três tipos de Packages: criados, embutidos (STANDARD, DBMS_STANDARD, DBMS_OUTPUT, DBMS_JOB, etc.) e os fornecidos, que dependem do ambiente de trabalho. Por exemplo, o Procedure Builder, antiga ferramenta gráfica semelhante ao SQL Navigator, disponibilizava o TEXT_IO, que permite realizar operações de entrada/saída (PUT_LINE mostra um texto na tela).
15.2 - Criação 15.2.1 - Especificação Após identificar os elementos que farão parte do Package, deve-se, inicialmente, criar a Especificação. O exemplo seguinte, presente no arquivo 15_Especifica_Pack_Inst, constrói a de Pack_Instrutores, um pacote que reunirá as manipulações à tabela Instrutores. 1. 2. 3. 4. 5. 6. 7. 8. 9.
create or replace package pack_instrutores is procedure elimina_instrutores_sem_turmas; function insere_instrutor_tratada (v_nome in instrutores.nome_instrutor%type, v_tel in instrutores.tel_instrutor%type, v_adm in instrutores.admissao%type) return varchar2; end pack_instrutores;
Observações •
•
A criação no SQL*Plus Worksheet requer a presença das palavras reservadas create or replace antes do nome do Package. Caso ocorram erros, emita o comando show errors; Pelo SQL Navigator, uma estrutura genérica pode ser arrastada para uma janela do SQL Editor a partir do Code Assistant (menu View, comando Code Assistant), abrindo as pastas Syntax and Web Catalog, PL/SQL Syntax, Blocks and Subprograms e Package.
O resultado deve ser algo assim: PACKAGE package_name IS -- Enter package declarations as shown below PROCEDURE procedure_name ( param1 IN datatype, param2 IN OUT datatype DEFAULT default_value); FUNCTION function_name ( param1 IN datatype, param2 IN OUT datatype DEFAULT default_value)
Oracle 9i Fundamental
175
RETURN datatype; END package_name ;
•
Para confirmar a criação do objeto anterior, investigue a visão USER_OBJECTS:
select object_name from user_objects where object_type = 'PACKAGE';
Além de procedures e functions, também podem existir declarações de cursores, exceções ou variáveis (simples ou compostas); • O nome do Package após o end é opcional; Para eliminar a especificação apresentada, emitimos o comando: •
drop package pack_instrutores;
15.2.2 - Corpo Uma vez criada a especificação, pode-se construir o corpo do Package. O exemplo seguinte, presente no arquivo 15_Especifica_Pack_Body_Inst, constrói o corpo de Pack_Instrutores. 1. 2. 3. … 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. … 28. 29.
create or replace package body pack_instrutores is procedure elimina_instrutores_sem_turmas is Begin end; function insere_instrutor_tratada (v_nome in instrutores.nome_instrutor%type, v_tel in instrutores.tel_instrutor%type, v_adm in instrutores.admissao%type) return varchar2 Is nome_nulo exception; pragma exception_init (nome_nulo, -1400); Begin end; end;
Observações • •
•
O nome de um PACKAGE BODY deve coincidir com o de um PACKAGE (especificação) já criado; A criação no SQL*Plus Worksheet requer a presença das palavras reservadas create or replace antes da palavra PACKAGE. Caso ocorram erros, emita o comando show errors; Pelo SQL Navigator, uma estrutura genérica pode ser arrastada para uma janela do SQL Editor a partir do Code Assistant (menu View, comando Code Assistant), abrindo as pastas Syntax and Oracle 9i Fundamental
176
•
Web Catalog, PL/SQL Syntax, Blocks and Subprograms e Package Body. Para confirmar a criação deste objeto, investigue a visão USER_OBJECTS:
select object_name from user_objects where object_type = 'PACKAGE BODY';
Além de procedures e functions previamente declaradas, também podem existir outras implementações, estas privativas, além de declarações de cursores, exceções ou variáveis. Elas seriam locais; • O nome do Package após o end é opcional; Para eliminar a especificação apresentada, emitimos o comando: •
drop package body pack_instrutores;
Uma vez criado o Corpo do Package, as rotinas que o constituem podem ser eliminadas; Após o end da última rotina e antes do end do Package, podemos inserir um bloco de comandos iniciado por begin. Ele será executado quando algum membro do Package for ativado pela primeira vez.
15.3 - Ativação Criados os objetos referentes à Especificação e ao Corpo, os membros do Package já podem ser ativados normalmente, porém deve-se referenciar o nome do Package. Vejamos um exemplo para o SQL*Plus Worksheet: var resposta varchar2(80) exec :resposta := pack_Instrutores.Insere_Instrutor_Tratada ('Novo','222',sysdate); print resposta
E a saída: RESPOSTA -----------------------------------------------------Inclusão OK!
Outro: exec pack_Instrutores.Elimina_Instrutores_Sem_Turmas; select nome_instrutor from instrutores;
E a saída: NOME_INSTRUTOR -----------------------------Maria Carolina Sírio Pedro Paulo Canopo Augusto Lemos Vega Mônica Silveira Capela
Oracle 9i Fundamental
177
Almir Altair Leonardo Guimarães Rigel Beatriz Bellatrix Carlos Regulos Joana Aldebaran
Poderíamos desfazer o efeito das últimas exclusões: rollback;
Observe que o instrutor Novo não consta na listagem anterior, já que, como acabou de ser cadastrado, não ministrou curso algum. Não se esqueça que a chamada a qualquer membro causa a transferência de todo o package para a memória.
15.4 - Dependências As Unidades de Programa, exceto Triggers, podem estar em dois estados: VALID ou INVALID. No primeiro caso, não existem erros de compilação. Imagine que tivés-semos gravado a função Calcula_Total_Arrecadado com um erro de compilação proposital. O script seguinte, que consta no arquivo 15_Lista_Status, informa quem estaria com problemas: column object_name format a30 heading 'OBJETO' select object_name, object_type TIPO, status from user_objects where object_type in ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY') order by 3,2,1;
E o resultado: OBJETO -----------------------------CALCULA_TOTAL_ARRECADADO ATUALIZAGENERICO CLASSIFICA_ARRECADADO ... PACK_INSTRUTORES PACK_INSTRUTORES ALIMENTAHISTORICO ALIMENTA_HISTORICO_FOR ... LIMPAHISTORICO RETORNA_INFO_CURSO
TIPO -----------------FUNCTION FUNCTION FUNCTION
STATUS ------INVALID VALID VALID
PACKAGE PACKAGE BODY PROCEDURE PROCEDURE
VALID VALID VALID VALID
PROCEDURE PROCEDURE
VALID VALID
30 linhas selecionadas.
O SQL Navigator destaca as rotinas inválidas, apresentando-as em outra cor. Pelo DB Navigator, confira em My Schema, Procedures, ou Functions, ou Packages, ou Package Bodies. O fato de um objeto estar inválido pode significar que existem erros de compilação ou que um objeto (tabela, visão) referenciado teve sua estrutura alterada (inclusão de um campo, exclusão, etc.). Esta relação entre objetos Oracle 9i Fundamental
178
denomina-se dependência que pode ser direta ou indireta (referência a um objeto que referencia a tabela). O SQL Navigator mostra a quem a rotina faz referência (Depends On) e quem depende dela, isto é, a invoca (Dependent Objects). No caso específico de Packages, existem três situações interessantes: 1. Apenas o Corpo muda: as rotinas que invocam seus membros permanecem válidas; 2. Apenas a Especificação muda: rotinas que invocarem quaisquer membros são invalidadas; 3. Muda algum objeto referenciado por qualquer membro: todo o package fica inválido. Toda vez que uma Unidade de Programa inválida for executada, o Oracle tenta recompilá-la. Recomenda-se, entretanto, que este mecanismo seja explicitado via comandos do tipo: ALTER tipo_objeto nome_objeto COMPILE
Por exemplo, imagine que a rotina seguinte tivesse sido desenvolvida com a ancens-tral Procedure Builder, que apresenta um package específico (text_io): alter procedure retorna_info_curso compile;
E o erro: Warning: Procedure altered with compilation errors.
Mostrando erros: show errors
Saída: Errors for PROCEDURE RETORNA_INFO_CURSO: LINE/COL ERROR -------- -------------------------------------------------12/2 PLS-00201: identifier 'TEXT_IO.PUT_LINE' must be declared 12/2 PL/SQL: Statement ignored 13/2 PLS-00201: identifier 'TEXT_IO.PUT_LINE' must be declared 13/2 PL/SQL: Statement ignored
O script seguinte fornece uma relação de objetos referenciados (dependências) a partir de um objeto/tipo: rem rem rem rem rem rem rem rem
***************************************************** Nome: Uso: Exemplo: Descrição:
15_mostra_dependencias.sql @15_mostra_dependencias nome_objeto tipo_objeto @15_mostra_dependencias pack_instrutores package body Mostra dependências para uma Unidade de Programa (exceto trigger)
*****************************************************
Oracle 9i Fundamental
179
set verify off clear break break on tipo_referenciado on nome column nome format a30 column referenciado format a30 column tipo_referenciado format a20 SELECT TYPE tipo, NAME nome, REFERENCED_NAME referenciado, REFERENCED_TYPE tipo_referenciado FROM USER_DEPENDENCIES WHERE NAME = UPPER('&1') AND TYPE = UPPER('&2') AND REFERENCED_TYPE IN ('PACKAGE','TABLE','VIEW') ORDER BY 1,2,3;
E uma execução: @15_mostra_dependencias pack_instrutores package body TIPO ---PACKAGE PACKAGE
NOME ---------------PACK_INSTRUTORES PACK_INSTRUTORES
REFERENCIADO -----------INSTRUTORES STANDARD
TIPO_REFERENCIADO -----------------TABLE PACKAGE
15.5 - Packages Embutidos Neste tópico serão comentados alguns Packages embutidos, que ilustram de que maneira podem ser úteis no dia a dia. Muitos outros ainda serão vistos nos próximos capítulos. DBMS_JOB
Automatiza tarefas permitindo implementar verdadeiros procedimentos pró-ativos, ou seja, que se antecipem a problemas em potencial. Mais detalhes em 15.5.1
DBMS_LOB
Permite a manipulação de grandes estruturas de dados (LOB Large Object). Mais detalhes em 15.5.2
DBMS_ALERT
Emite avisos quando dá-se uma determinada situação. Como trabalha em base a Triggers, veremos exemplos de utilização no próximo capítulo.
15.5.1 - DBMS_JOB Como já citado, este package oferece diversos recursos que permitem automatizar tarefas. Antes que sejam analisados seus procedimentos, convém definir três conceitos muito importantes: Job
Tarefa a ser executada em um momento específico ou de forma recorrente.
Job Queue
Conjunto de jobs executáveis.
Agenda
Momento em que o job será executado e, caso exista, intervalo de recorrência. Oracle 9i Fundamental
180
Segue a lista de rotinas oferecidas por DBMS_JOB: Submit
Cria um job, isto é, insere-o na Job Queue.
Remove
Exclui um job.
Change
Altera função ou agenda de um job. Opcionalmente pode-se apenas alterar a função (what), próxima ocorrência (next_date) ou recorrência (interval).
Broken
Desativa ou ativa um job.
Run
Executa um job.
Imagine que seja necessário registrar diariamente a quantidade de alunos matricu-lada, ou seja, quantas linhas possuiria a tabela HISTORICO. Seria criado um job que todos os dias, digamos às 17:00, gravasse um número em uma dada tabela. Em seguida resolve-se a questão a partir de exemplos extraídos do arquivo 15_Exemplos_DBMS_JOB. Criando a tabela de registros com dois campos: CREATE TABLE log_matriculas (Data_registro Linhas
DATE DEFAULT sysdate NOT NULL, NUMBER(4) DEFAULT 0 NOT NULL);
Criando Procedure que gravará a tabela: PROCEDURE GRAVA_LOG_MATRICULAS IS v_linhas integer; BEGIN select count(*) into v_linhas from historico; insert into log_matriculas values (sysdate,v_linhas); commit; END; -- Procedure
Antes que quaisquer jobs possam ser executados, é preciso informar ao sistema que será possível disparar tarefas mediante agenda prévia. Isto acontece graças ao comando: alter system set job_queue_processes = 20;
Esta instrução informa que, a partir de agora, até vinte jobs poderão acontecer simultaneamente. Inclusive, se houve disparos prévios, as execuções acontecerão também neste momento. Criando o job: VARIABLE jobno NUMBER; BEGIN DBMS_JOB.SUBMIT(:jobno, 'GRAVA_LOG_MATRICULAS;', trunc(sysdate, 'month') + 29 + 17/24, 'sysdate+1'); COMMIT; END;
Oracle 9i Fundamental
181
Observações: •
•
•
A procedure submit devolve um parâmetro representando a identificação do job. Este número será utilizado posteriormente para quaisquer operações sobre o job; O segundo argumento representa o que deverá ser executado. Pode ser qualquer comando SQL, sempre terminado por ponto-evírgula. Nesse caso em particular, vemos que a procedure GRAVA_LOG_MATRICULAS será executada; O terceiro argumento informa quando acontecerá a primeira execução. O conteúdo revela que será no dia 30 do mês corrente, às 17 horas;
Finalmente, informa-se a recorrência, ou seja, quando ocorrerá a próxima execução. Neste exemplo, determinou-se que será exatamente um dia após a última execução. Observe que a expressão aparece entre aspas simples e, caso houvesse um literal, ele também viria cercado. Por exemplo, a expressão: 'NEXT_DAY(TRUNC(SYSDATE), ''FRIDAY'') + 10/24'
Significa que a próxima execução será na sexta-feira seguinte à ultima execução, às dez da manhã. Uma vez criado o job, poderíamos investigar seu histórico. Por exemplo: select job, schema_user, to_char(next_date, interval, what from dba_jobs
'dd/mm/yy
hh24:mi')
"PRÓXIMA
VEZ",
Nada impede que um job seja executado de forma independente de sua agenda: begin dbms_job.run(27); end;
Após algumas execuções, poderíamos investigar o conteúdo da tabela de registros: select to_char(data_registro, 'dd/mm/yy hh24:mi') Instante , Linhas from log_matriculas;
E uma possível saída: INSTANTE LINHAS -------------- ---------30/03/02 17:25 104 30/03/02 17:28 104
Finalmente, para eliminar um job: Oracle 9i Fundamental
182
begin dbms_job.remove(26); commit; end;
15.5.2 - DBMS_LOB Como já visto nos Capítulos 2 (Tabelas) e 10 (Variáveis), o Oracle oferece uma série de tipos destinados ao tratamento de grandes volumes de dados. Genericamente conhecidos por LOB Datatypes, eles permitem que campos de tabelas ou variáveis armazenem conteúdos tão heterogêneos quanto filmes, fotos ou grandes textos. Este tópico explora o package embutido DBMS_LOB exemplificando várias de suas rotinas. Os scripts fornecidos tratam todos de uma tabela (TEXTUAL) com um campo de tipo CLOB. Serão vistas as seguintes rotinas: Write
Grava (bytes em BLOBs e NBLOBs e caracteres em CLOBs e NCLOBs). Especificam-se uma posição inicial e um tamanho, além, claro, da sequência a ser inserida.
Getlength
Função que retorna o tamanho de um LOB.
Writeappend
Grava ao final do LOB.
Read
Recupera dados gravados previamente em LOBs.
Open
Abre um LOB. Ainda que não obrigatória, recomenda-se esta operação para conferir mais robustez ao código.
Close
Fecha um LOB previamente aberto.
IsOpen
Função numérica que verifica se um dado LOB já foi aberto.
Substr
Retorna parte de um LOB.
Instr
Realiza uma pesquisa em um LOB.
Erase
Apaga parcial ou totalmente um LOB.
Antes de mostrar exemplos destas rotinas, convém preparar o terreno. Será criada uma tabela: create table Textual ( cod_item integer not null , nome_item varchar2(20) not null , detalhe_item clob null );
Nenhum procedimento pode ser utilizado caso o campo LOB possua valor nulo, assim, convém iniciá-lo na inserção da linha: insert into textual values (1, 'Tabelas', empty_clob());
Oracle 9i Fundamental
183
Em vez da função empty_clob, também poderia ter sido utilizado um valor qualquer. O código seguinte foi extraído do arquivo 15_Testa_DBMS_LOB_WRITE e mostra como gravar caracteres em um CLOB: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34.
create or replace PROCEDURE GRAVA_EM_CLOB IS v_clob CLOB; v_texto VARCHAR2(32767); v_buffer VARCHAR2(80); v_qtde BINARY_INTEGER := 20; v_posicao INTEGER := 1; v_tamanho integer; BEGIN /* Localiza o CLOB: */ SELECT detalhe_item INTO v_clob from textual where cod_item = 1 FOR UPDATE; /* Abertura é opcional */ DBMS_LOB.OPEN (v_clob, DBMS_LOB.LOB_READWRITE); /* Texto v_texto v_texto v_texto v_texto v_texto
a ser inserido */ := 'A especificação de um tipo de campo deve ser ... := v_texto || 'valores candidatos ao ... := v_texto || 'entrada de códigos de condomínio ... := v_texto || 'Integridade de Dados. Esta proteção ... := v_texto || 'domingos de sol enclausurados, sábados ...;
v_tamanho := length(v_texto); while (v_posicao + v_qtde) 1200 then raise_application_error(-20500, 'Tentativa exagerada de aumento!'); end if; end;
Oracle 9i Fundamental
194
Observação •
Pelo SQL Navigator, após conectado, abra o menu Object, ative Open DB Object e selecione o Trigger em questão. Observe que o Trigger Editor apresenta cinco guias: Details (especifica as características do Trigger), Trigger Body (mostrado em seguida), Columns (caso se limite o escopo do Trigger a poucas colunas da tabela), When e Dependencies (de quem o Trigger depende, ou seja, qual ou quais objetos não podem ser eliminados ou mesmo alterados sem afetar o Trigger).
Para confirmar a criação do Trigger, investigue a visão USER_TRIGGERS: select trigger_name from user_triggers;
Para eliminar um Trigger, emitiríamos o comando: drop trigger t_aft_upd_row_aumentaprecos;
Para desabilitar/habilitar temporariamente um ou todos os Triggers de uma tabela: alter alter alter alter
table cursos disable all triggers; table cursos enable all triggers; trigger t_aft_upd_row_aumentaprecos disable; trigger t_aft_upd_row_aumentaprecos enable;
O nome de um Trigger deve deixar claro as características dele. Analise a lei de formação do exemplo anterior. Veja em seguida uma possível execução: update cursos set preco = preco * 2;
E a resposta: update cursos set preco = preco * 2 * ERROR at line 1: ORA-20500: Tentativa exagerada de aumento! ORA-06512: at "MORELLI.T_AFT_UPD_ROW_AUMENTAPRECOS", line 3 ORA-04088: error during execution of trigger 'MORELLI.T_AFT_UPD_ROW_AUMENTAPRECOS'
Oracle 9i Fundamental
195
Perceba que mesmo que algumas linhas possam ser alteradas, toda a execução é cancelada.
16.3 - DML 16.3.1 - INSERT Segue o exemplo de um Trigger de inserção disparado previamente ao comando e fazendo distinção em cada linha. O código encontra-se no arquivo 16_Trigger_Bef_Ins_Row_InsereAluno.sql. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
create or replace trigger t_bef_ins_row_InsereAluno before insert on alunos for each row Declare nova_matricula number; Begin select Gera_Matr_aluno.Nextval into nova_matricula from dual; :new.matricula := nova_matricula; end;
Uma vez criado, o Trigger anterior permitiria inserções como esta: insert into alunos (nome_aluno) values ('Francisco Musca');
Comprovando: select max(matricula) from alunos;
E a saída: MAX(MATRICULA) -------------40
Observações A seqüência Gera_Cod_aluno deve existir. No script que possui o Trigger há um comando de criação: create sequence gera_matr_aluno start with 40 increment by 1 maxvalue 1000 nocycle;
Note a declaração de uma variável local; Caso seja realizada uma inserção múltipla (com subquery, por exemplo), seriam gerados vários códigos: um para cada linha afetada.
16.3.2 - UPDATE
Oracle 9i Fundamental
196
Segue o exemplo de um Trigger de atualização disparado previamente ao comando e sem fazer distinção em cada linha. O código encontra-se no arquivo 16_Trigger_Bef_Upd_Stm_Registro.sql. 1. 2. 3. 4. 5. 6. 7.
create or replace trigger t_bef_upd_stm_Registro before update on cursos Begin update Tab_Auditoria set atualizacoes = atualizacoes + 1; end;
Uma vez criado, o Trigger anterior permitiria atualizações como esta: update cursos set preco = 100;
Comprovando: select * from tab_auditoria;
E a saída: ATUALIZACOES -----------1
Observações A tabela Tab_Auditoria já deve existir. No script que possui o Trigger há o comando de criação e também o que insere a primeira linha create table tab_auditoria (atualizacoes number); insert into tab_auditoria values(0); commit;
Perceba que o Trigger é executado uma vez apenas, independente da quantidade de linhas afetadas pelo comando.
16.3.3 - Delete Segue o exemplo de um Trigger de exclusão disparado previamente ao comando e fazendo distinção em cada linha. O código encontra-se no arquivo 16_Trigger_Bef_Del_Row_LimpaHist.sql. 1. 2. 3. 4. 5. 6. 7. 8.
create or replace trigger t_bef_del_row_LimpaHist before delete on turmas for each row Begin delete historico where cod_turma = :old.cod_turma; end;
Antes de testar o Trigger recém-criado, deveríamos desabilitar a restrição que impede as exclusões em cascata: alter table historico disable constraint historico_turma_fk;
Oracle 9i Fundamental
197
Supondo que as tabelas TURMAS e HISTORICO estejam preenchidas, o seguinte comando: delete turmas;
além de excluir todas as linhas de TURMAS, também o faria com a de matrículas! Naturalmente, a execução de um rollback restabeleceria as quantidades prévias à exclusão.
Observações Triggers e Constraints são conflitantes entre si, por isto realizou-se a desabilitação; Existe uma notória recomendação da Oracle em não abusar da utilização de Triggers devido às inúmeras possibilidades de interdependências. Ao criá-los em grande número, tende-se a perder o controle sobre as conseqüências de cada comando emitido.
16.3.4 - Múltiplos O mesmo Trigger pode ser disparado por mais de um comando, isto é, um delete provocaria o mesmo Trigger que um update. Suponha que seja proibido atualizar a tabela HISTORICO aos domingos ou inserir uma nota após as 18:30. Veja o exemplo presente em 16_Trigger_Bef_UpdIns_Stm_MultHist.sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
create or replace trigger t_bef_updIns_stm_MultHist before insert or update on historico Declare v_hoje number; v_agora number; Begin v_hoje := to_number(to_char(sysdate,'d')); v_agora := to_number(to_char(sysdate,'hh24mi')); if inserting then if v_agora > 1830 then raise_application_error(-20600, 'Hora proibida para inserções'); end if; Else if v_hoje = 1 then raise_application_error(-20700, 'Dia proibido para atualizações'); end if; end if; end;
E possíveis ativações em horários impróprios: insert into historico values (12,12,10);
Resposta: insert into historico values (12,12,10) * ERROR at line 1:
Oracle 9i Fundamental
198
ORA-20600: Hora proibida para inserções ORA-06512: at "MORELLI.T_BEF_UPDINS_STM_MULTHIST", line 9 ORA-04088: error during execution of trigger 'MORELLI.T_BEF_UPDINS_STM_MULTHIST'
Outra: update historico set nota = 10;
Saída: update historico set nota = 10 * ERROR at line 1: ORA-20700: Dia proibido para atualizações ORA-06512: at "MORELLI.T_BEF_UPDINS_STM_MULTHIST", line 13 ORA-04088: error during execution of trigger 'MORELLI.T_BEF_UPDINS_STM_MULTHIST'
16.4 - Atualização de Views No Capítulo 6, item 6.3, Views, foi dito que existe uma série de restrições quanto à possibilidade de emitir comandos insert, update ou delete diretamente sobre Views. Entretanto, com Triggers instead of essas limitações podem ser contornadas. Por exemplo, a visão seguinte não aceitaria comandos de inserção, já que possui um operador union29: create view vPessoas as select nome_aluno as nome, 'a' as tipo from alunos union select nome_instrutor, 'i' from instrutores;
Felizmente, o Trigger seguinte contorna esta limitação: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
create or replace trigger t_io_vPessoas instead of insert On vPessoas declare v_cod_instrutor number; Begin select max(cod_instrutor)+1 into v_cod_instrutor from instrutores; if :new.tipo = 'a' then --aluno! insert into alunos (nome_aluno) values (:new.nome); Else insert into instrutores (cod_instrutor, nome_instrutor) values (v_cod_instrutor, :new.nome); end if; end;
Observações Como não há Trigger que gere um código de instrutor, isto teve que ser feito agora. Testes de inserção: 29
Os códigos seguintes 16_Exemplo_Atualiza_View.sql.
encontram-se
Oracle 9i Fundamental
no
Script
exemplo
199
insert into vPessoas (nome, tipo) values ('Aluno', 'a'); insert into vPessoas (nome, tipo) values ('Instrutor', 'i');
Os comandos anteriores, na prática, inserem uma linha nova nas tabelas ALUNOS e INSTRUTORES, como era de se esperar, já que Views não armazenam dados. Perceba que a inserção somente foi possível graças ao Trigger.
16.5 - Schema Trigger do tipo Schema permite acompanhar o que acontece quando um comando DDL é utilizado. Poderíamos criar um registro de todos os CREATEs ocorrido, ou talvez evitar que tabelas sejam truncadas, ou ainda criar um log detalhado sobre permissões concedidas30. Normalmente, Triggers tipo Schema utilizam um tipo especial de função dita de evento, ou seja, elas retornam informações sobre acontecimentos correntes. O exem-plo seguinte registra a ocorrência de comandos truncate table (os comandos que seguem foram extraídos do arquivo exemplo 16_Exemplo_Trigger_Schema.sql). Inicialmente cria-se a tabela: create table GuardaTruncates (quando date default sysdate, quem varchar2(20) default user, onde varchar2(20));
A seguir, cria-se o Trigger: create or replace trigger t_registra_truncates after truncate on schema begin insert into GuardaTruncates (onde) values (ora_dict_obj_name); end;
Observe a presença da função de evento ora_dict_obj_name. Ela informa o nome do objeto que sofreu o comando que, por sua vez, disparou o Trigger. Assim como ela, há diversas outras. Veja algumas:
30
ora_database_name
nome do Banco de Dados corrente
ora_dict_obj_owner
dono do objeto que sofreu o comando
ora_dict_obj_type
tipo do objeto
ora_sysevent
nome do evento corrente
ora_is_alter_column( column_name IN VARCHAR2)
retorna TRUE caso o nome passado coincida com o de uma coluna sendo alterada.
ora_is_drop_column( column_name IN VARCHAR2)
Retorna TRUE caso o nome passado coincida com o de uma coluna sendo eliminada.
O assunto "permissões" será visto em detalhes no Capítulo 24, Segurança.
Oracle 9i Fundamental
200
16.6 - DBMS_ALERT Este Package permite que ocorra um aviso quando uma determinada situação acontecer. Por exemplo, imagine que seja necessária a imediata comunicação de um preço hora instrutor superior a R$ 50. Segue a lista das principais rotinas oferecidas por DBMS_ALERT: Register
Registra um evento em uma sessão.
Remove
Exclui um evento previamente registrado em uma sessão.
Removeall
Exclui todos os eventos previamente registrados em uma sessão.
Set_defaul ts
Ajusta o intervalo de tempo utilizado para verificar se ocorreu uma determinada situação.
Signal
Dispara um alerta.
Waitany
Recebe quaisquer alertas.
Waitone
Recebe um alerta específico.
Atenção
Caso as procedures de DBMS_ALERT não estejam disponíveis, isto é, as unidades de programa que as invocarem apresentem erros informando que elas precisam ser declaradas, deve-se executar o script dbmsalrt.sql que está localizado sob o diretório de instalação, em \rdbms\admin\.
Para que seja possível realizar tal notificação, inicialmente criaremos um Trigger sobre a tabela de turmas, depois abre-se uma sessão cuja única função será "esperar" a ocorrência e finalmente provoca-se a inserção de um instrutor cuja hora aula passe da meia centena de reais. O código mostrado em seguida consta no arquivo 16_Exemplo_DBMS_Alert.sql. Criando o Trigger: 1. 2. 3. 4. 5. 6. 7. 8.
create or replace trigger t_aft_iu_row_Checa_pco_Hora After insert or update on Turmas For each row When (new.preco_hora_instrutor > 50) Begin dbms_alert.signal ('Instrutor_Caro', 'Valor preço hora: ' || to_char (:new.preco_hora_instrutor)); end;
Observações Note a presença da cláusula when. Ela impede que o Trigger em questão seja disparado quando ocorrerem inserções e/ou atualizações que não estejam de acordo com a condição especificada;
Oracle 9i Fundamental
201
Perceba também que o identificador new.preco_hora_instrutor não aparece precedido por dois pontos, como está no corpo do Trigger (linha 7); A procedure signal mandará um aviso a todas as sessões que estiverem esperando por notificações. Criando uma procedure que prepara uma sessão para que ela possa ser notificada: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
create or replace procedure Prepara_espera Is status number; mensagem char(40); timeout number; nome varchar2(20); Begin timeout := 60; nome := 'Instrutor_Caro'; dbms_alert.register (nome); dbms_alert.waitany (nome, mensagem, status); if status = 0 then dbms_output.put_line ('Recebida: '|| mensagem); end if; dbms_alert.remove (nome); end;
Observações A procedure waitany necessita de três argumentos: o nome do alerta, uma variável que receberá a mensagem de signal e um estado que acusará o recebimento. Agora basta abrir duas conexões. Na primeira será executada a procedure de espera e na segunda, uma inserção na tabela TURMAS. Se em um minuto acontecer uma inserção, a sessão que estiver "aguardando" emitirá uma mensagem do tipo: Recebida: Valor preço hora: 60
EXERCÍCIOS 1. Substitua os constraints historico_turma_fk e historico_aluno_fk por um Trigger de inserção prévia, verificando cada linha. • Tanto o código da turma quanto a matrícula já devem existir para que a inserção se concretize. • Qual é a vantagem desta solução em detrimento da que utiliza constraints? 2. Desabilite o Trigger recém-criado, insira uma linha em HISTORICO com aluno inexistente e depois reabilite o Trigger. • Você conseguirá! Como resolver este problema? Oracle 9i Fundamental
202
3. Expanda Tab_Auditoria para que registre inserções e exclusões. Permita que sejam gravados também usuário e data/horário correntes. • A função user retorna o usuário corrente. • A função sysdate retorna data/horário correntes. 4. Partindo da uma lista de presenças criada no sétimo exercício do capítulo sexto, crie um Trigger que permita inserir um curso por meio da view. 5. Crie um Trigger que registre cada create em uma tabela contendo data, usuário e nome de objeto. • No Trigger do tipo SCHEMA criado, utilize os eventos ora_dict_obj_name (nome do objeto corrente) e ora_dict_obj_type (tipo de objeto criado - tabela, view, procedure, etc.). 6. Elabore um alerta que avise sempre que houver um truncate table. 7. Reflita sobre a importância dos Triggers para melhorar a segurança de um Banco de Dados. 8. Como Triggers poderiam fazer parte de uma política de proteção aos dados?
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Criar um Trigger
Pelo SQL*Plus Worksheet execute um script que contenha o comando create or replace Trigger. Já pelo SQL Navigator, expanda My Schema, dê um clique direito em Triggers e ative Create. Forneça nome, tabela base, ação, escopo, tempo e código.
Eliminar um Trigger
Utilize o comando drop trigger nome.
Desabilitar um Trigger
alter table nome disable all triggers;
Podem-se desabilitar todos os Triggers de uma tabela: ou fazê-lo para apenas um Trigger: alter trigger nome disable; Podem-se habilitar todos os Triggers de uma tabela:
Habilitar um Trigger
alter table nome enable all Triggers;
ou fazê-lo para apenas um Trigger: alter trigger nome enable;
Listar Triggers
Investigue a visão USER_TRIGGERS.
Criar um esquema de notificações
Utilize o Package embutido DBMS_ALERT. Veja exemplo em 16.6.
Oracle 9i Fundamental
203
ANOTAÇÕES
Oracle 9i Fundamental
204
Capítulo 17 – OBJETOS OBJETIVOS • • • • • • • •
Apresentar os conceitos primordiais que sustentam o Paradigma da Orien-tação por Objetos; Constatar como os conceitos do POO são aplicados no Oracle9i; Criar uma classe; Criar outra classe utilizando o mecanismo da herança; Instanciar objetos de uma classe; Criar uma tabela de objetos; Criar referências entre objetos; Criar coleções de tamanho variável com NESTED TABLES e fixo com VARRAYS.
ARQUIVOS NECESSÁRIOS • • • • • • • • • •
17_Cria_Classe_Funcionario.sql; 17_Cria_Classe_Funcionario_Body.sql; 17_Instancia_Funcionario.sql; 17_Cria_Classe_Herdada_Gerente.sql; 17_Cria_Tabela_Funcionarios.sql; 17_Trata_Classe_Projetos.sql; 17_Cria_Classe_Funcionario_com_Dependentes.sql; 17_Cria_Tabela_Funcionarios_com_Dependentes.sql; 17_Cria_Classe_Funcionario_completa.sql; 17_Cria_Tabela_Funcionarios_completa.sql.
PRÉ-REQUISITOS • •
Utilizar comandos SQL do tipo DML (Select, Insert, Delete, Update) em Unidades de Programa; Resolver problemas envolvendo processamentos condicional ou repetitivo.
Oracle 9i Fundamental
205
MOTIVAÇÃO O Paradigma da orientação por Objetos31 O conceito de programação orientada por objetos não é novo. No final da década de 60, a linguagem Simula67, desenvolvida na Noruega, introduzia conceitos hoje encontrados nas linguagens orientadas a objetos. Em meados de 1970, o Centro de Pesquisa da Xerox (PARC) desenvolveu a linguagem Smalltalk, a primeira totalmente orientada a objetos. No início da década de 80, a AT&T lançaria a Linguagem C++, uma evolução da linguagem C em direção à orientação a objetos. Atualmente, a grande maioria das linguagens incorpora características de OO, como Java e Object Pascal. Além das linguagens de programação, é possível encontrar o conceito de OO em sistemas operacionais, como no caso do Windows 2000, e em banco de dados, como no Oracle a partir da versão 8 e, principalmente, Jasmine da CA. A programação orientada a objetos tem como principais objetivos reduzir a complexidade no desenvolvimento de software e aumentar sua produtividade. A análise, projeto e programação orientadas a objetos são as respostas para o aumento da complexidade dos ambientes computacionais que se caracterizam por sistemas heterogêneos, distribuídos em redes, em camadas e baseados em interfaces gráficas. A programação orientada a objetos não tem a intenção de substituir a programação estruturada tradicional. Podemos considerar que a programação OO é uma evolução de práticas que são recomendadas na programação estruturada, mas não formalizadas, como o uso de variáveis locais, visibilidade e escopo. O modelo de obje-tos permite a criação de bibliotecas que tornam efetivos o compartilhamento e a reutilização de código, reduzindo o tempo de desenvolvimento e, principalmente, simplificando o processo de manutenção das aplicações. A grande dificuldade para compreender a programação OO é a diferença de abordagem do problema. Enquanto a programação estruturada tem como principal foco as ações (procedimentos e funções), a programação OO se preocupa com os objetos e seus relacionamentos. Além do conceito de objeto, a programação OO tem como alicerces os conceitos de encapsulamento, classe, herança e polimorfismo. Programação Orientada a Objetos
Programação Estruturada
Métodos
Procedimentos e funções
Instâncias de variáveis
Variáveis
31
Este artigo foi escrito por Luiz Paulo Maia. Revisão: Eduardo T. Morelli.
Oracle 9i Fundamental
206
Programação Orientada a Objetos
Programação Estruturada
Mensagens
Chamadas a procedimentos e funções
Classes
Tipos de dados definidos pelo usuário que criam estruturas de dados mais procedimentos que as manipulam
Herança
-
Polimorfismo
-
Um objeto é uma abstração de software que pode representar algo real ou virtual. Um objeto é formado por um conjunto de propriedades (variáveis) e procedimentos (métodos). As variáveis possuem um tipo, que define os possíveis valores que a variável pode representar, como um número inteiro, número real ou string. Os métodos são rotinas que, quando executadas, realizam alguma tarefa, como alterar o conteúdo de uma variável do objeto. Um exemplo de objeto poderia ser um automóvel. O objeto automóvel possui propriedades, como velocidade, número de portas e limite de passageiros. O objeto automóvel também possui procedimentos, como ligar, desligar, acelerar e parar. Um exemplo menos concreto de um objeto poderia ser um processo em um sistema operacional. Um processo tem propriedades, como identificação, prioridade, privilé-gios e quotas. Um processo possui procedimentos associados, como criar, eliminar, alterar a prioridade e visualizar suas características. Os objetos se comunicam apenas por meio de mensagens. Quando um objeto deseja alguma tarefa de um outro objeto, ele envia uma mensagem contendo o nome do objeto-origem, nome do objeto-destino, nome do método a ser ativado no objeto-destino e, se necessário, parâmetros que permitem especificar alguma função especial a ser executada pelo método. Este conceito se assemelha à chamada de uma rotina em uma linguagem tradicional. O conjunto de mensagens que um objeto pode responder é definido como protocolo de comunicação. As variáveis de um objeto só podem ser alteradas por métodos definidos na própria classe. A única maneira de um objeto alterar as variáveis de um outro objeto seria pela ativação de um de seus métodos por uma mensagem. Este conceito, em que variáveis e métodos são visíveis apenas por meio de mensagens, é conhecido como encapsulamento. O encapsulamento funciona como uma proteção para as variáveis e métodos, além de tornar explícito qualquer tipo de comunicação com o objeto. Geralmente, objetos são criados e eliminados em função da execução do programa. Um objeto pode ser instanciado (criado) por um certo período de tempo e depois destruído, liberando o espaço de memória ocupado, em um processo automático conhecido como "garbage collection" (coleta de lixo). É possível, porém, criar objetos persistentes, que continuam existindo mesmo depois do término do pro-grama que os criou. Um claro exemplo de Oracle 9i Fundamental
207
objetos persistentes seriam os armaze-nados em Bancos de Dados Orientados a Objetos. Uma classe consiste de variáveis e métodos que representam características de um conjunto de objetos semelhantes. O conceito de classe é um dos pilares da programação orientada a objetos, por permitir a reutilização efetiva de código. A declaração de classe é similar à dos tipos definidos pelo usuário nas linguagens de programação de alto nível. Nessas linguagens, é possível definir um novo tipo de dado e declarar uma variável deste tipo. No caso de objetos, primeiro definimos uma classe com suas variáveis e métodos e, depois, declaramos um objeto dessa nova classe. Um objeto é definido como sendo uma instância de uma determinada classe. A classe é estática, enquanto o objeto é dinâmico. No exemplo seguinte, escrito em C++, estamos definindo uma classe T_Ponto, em que as variáveis x e y representam a posição de um ponto na tela. Posteriormente declaramos um objeto p da classe T_Ponto. class T_Ponto /* Define a classe Ponto */ { int x; int y; public void altera_xy (int a, int b) { x=a; y=b; } int obtem_x () { return x; } int obtem_y () { return y; } }; T_Ponto p; /* Declara o objeto p da classe Ponto */
No mesmo exemplo, para alterarmos o valor das variáveis x e y, é necessário o envio de uma mensagem para o objeto p, especificando o método altera_xy e passando os novos valores como parâmetros. Da mesma forma, para consultar os valores de x e y, é preciso acionar os métodos obtem_x e obtem_y respectivamente. Os métodos que permitem a comunicação do objeto com o mundo exterior são conhecidos como interfaces públicas. Ainda sobre o exemplo anterior, nada impediria que as variáveis fossem instâncias, assim, poderia existir uma classe denominada T_Círculo com dois atributos: raio (inteiro) e centro (T_Ponto). O conceito de herança permite definir uma nova classe, com base em uma já existente. A classe criada (subclasse ou classe derivada) automaticamente herda todas as variáveis e métodos da classe já existente (superclasse). O mecanismo de herança permite ainda que a subclasse inclua ou sobreponha novas variáveis e métodos da superclasse. No exemplo anterior, em que criamos a classe T_Círculo, poderíamos adotar uma solução alternativa: em vez de duas variáveis (raio e centro), definiríamos apenas um (raio) e o outro seria herdado de T_Ponto. Oracle 9i Fundamental
208
O conceito de herança da POO assemelha-se ao utilizado pela biologia. Lá os seres vivos são classificados segundo a complexidade de seus organismos. Assim, existem dos mais rudimentares (protozoários), até os mais sofisticados (aves, répteis, mamíferos). Como no caso da POO, cada classe criada a partir do mecanismo da herança representa uma especialização da anterior. O mecanismo de herança é recursivo, permitindo criar uma hierarquia de classes. Nos níveis mais altos da hierarquia estão características comuns a todos os objetos desta classe, enquanto nos níveis inferiores estão especializações das classes superiores. As subclasses herdam as características comuns, além de definirem suas propriedades específicas. Existem dois tipos de mecanismos de implementação de herança: simples e múltipla. Na herança simples, a subclasse pode herdar variáveis e métodos apenas de uma classe, enquanto na herança múltipla, a subclasse pode herdar variáveis e métodos de mais de uma classe. Uma das grandes vantagens da programação OO consiste na utilização de bibliotecas de classes que lembram as bibliotecas de código (procedimentos e funções), utilizadas na programação modular. As bibliotecas de classes permitem uma capacidade muito maior de compartilhamento e reutilização de código, pois é possível criar subclasses para atender novas necessidades, em função das classes já existentes. Muitas bibliotecas são oferecidas juntamente com as ferramentas de desenvolvimento para reduzir o tempo e a complexidade de projetos de software, como a Microsoft Foundation Class (MFC) e a Visual Component Library (VCL) do Delphi. Inclusive, hoje existe uma crescente indústria de componentes, isto é, empresas que se dedicam a criar classes que servirão para que outros literalmente montem suas aplicações finais. Uma analogia para esta dicotomia poderia ser o surgimento de dois novos profis-sionais: o "tijolista" e o "murista". O primeiro cria pequenos blocos e não possui a menor idéia de onde serão utilizados, enquanto o segundo tem a enorme vantagem de não se preocupar com detalhes internos de implementação do código adquirido. O termo polimorfismo é utilizado em biologia para definir variações em forma e função de membros de uma mesma espécie. Utilizando a mesma analogia, o mecanismo de polimorfismo permite tratar objetos semelhantes de uma maneira uniforme. Neste caso, é possível que se envie uma mesma mensagem para um conjunto de objetos e cada objeto responda de maneira diferente em função da mensagem recebida. O polimorfismo, para ser implementado, exige a utilização do conceito de herança e aplica-se apenas aos métodos da classe. O protocolo de comunicação é estabelecido na classe mais alta da hierarquia, que será herdada por todas as subclasses definidas posteriormente. Este mecanismo cria um protocolo padrão de comunicação com um conjunto de objetos, permitindo uma grande flexibilidade na agregação de objetos semelhantes, mas não idênticos. Oracle 9i Fundamental
209
Em programas que não utilizam orientação por objetos, sempre que uma nova funcionalidade deve ser acrescentada, a aplicação deve ser alterada e recompilada. Com o conceito de polimorfismo, é possível acrescentar novos métodos a classes já existentes sem a necessidade de recompilar a aplicação. Isto é possível por meio da técnica de "late binding" ou "dynamic binding", que permite que novos métodos sejam carregados e ligados (binding) à aplicação em tempo de execução. Concluindo, o paradigma da OO representa uma forma evolucionária de pensar a programação. Baseado em cinco conceitos: objeto, classe, encapsulamento, herança e polimorfismo, traz inúmeros benefícios à criação de programas, dentre os quais o mais notável é a reutilização de código, que reduz drasticamente os tempos de desenvolvimento e manutenção de programas. Referências: Object-Oriented Programming: An Introduction Greg Voss McGraw-Hill, 1991.
Object-Oriented Software Ann L. Winblad, Samuel D. Edwards & David R. King Addison-Wesley, 1990.
TEORIA 17.1 - Fundamentos Uma das grandes novidades introduzidas na versão 8 do Oracle consistiu na possibilidade de utilização de Classes e Objetos. Agora, além de tabelas, também é possível criar novas estruturas de dados, mais à feição da realidade que cerca o Banco, baseadas no Paradigma da Orientação por Objetos. Alguns termos foram introduzidos: Tipo Objeto (Object Type)
Classe
Instância (Object Instance)
Instância de uma classe, ou seja, um objeto
Herança (Object-type inheritance)
Mecanismo que permite criar uma classe aproveitando uma já existente. Este recurso apareceu apenas na versão 9i.
Atributo (Attribute)
Propriedade de um objeto. Pode ser de algum tipo fornecido ou mesmo uma classe.
Método (Method)
Rotina incorporada ao Objeto Oracle 9i Fundamental
210
Os metadados referentes a POO estão nas seguintes views: ALL_COLL_TYPES ALL_METHOD_PARAMS ALL_METHOD_RESULTS ALL_OBJECT_TABLES ALL_TYPES ALL_TYPE_ATTRS ALL_TYPE_METHODS DBA_COLL_TYPES DBA_METHOD_PARAMS DBA_METHOD_RESULTS DBA_OBJECT_TABLES
DBA_TYPES DBA_TYPE_ATTRS DBA_TYPE_METHODS USER_COLL_TYPES USER_METHOD_PARAMS USER_METHOD_RESULTS USER_OBJECT_TABLES USER_TYPES USER_TYPE_ATTRS USER_TYPE_METHODS
Vale lembrar que a visão USER_OBJECTS permanece listando tabelas, visões, Packages, etc. Apesar de não mostrar os objetos criados a partir de classes (instâncias), ela também revela as especificações e corpos de classes criadas.
17.2 - Tipos Objeto Uma classe, ou tipo objeto, deve ser criada em duas etapas: primeiro a especificação e depois o corpo. Para criar a especificação de uma classe no SQL*Plus Worksheet, devemos editar um arquivo texto contendo a seguinte estrutura: CREATE OR REPLACE TYPE nome_classe AS OBJECT (lista atributos, lista métodos)
O exemplo seguinte encontra-se no script 17_Cria_Classe_Funcionario.sql: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
create or replace type funcionario_t as object( -- atributos: matricula varchar2(10), nome varchar2(60), data_nascimento date, --metodos de acesso a dados: member procedure set_matricula (new_matricula in varchar2), member procedure set_nome (new_nome in varchar2), member procedure set_data_nascimento (new_data_nascimento in date), --demais metodos: member function retorna_idade return integer, member procedure mostre) not final;
Observações
Oracle 9i Fundamental
211
•
• •
•
A cláusula not final (linha 14) indica que a classe em questão pode vir a ter classes derivadas, ou seja, outras classes podem vir a ser criadas via herança e tendo-a como base; A criação no SQL*Plus Worksheet requer a presença das palavras reservadas create or replace antes do nome da classe; Vê-se claramente que o conceito de Package foi estendido para que seja possível implementar classes; aliás, um Package pode ser visto como um projeto de classe; Para confirmar a criação da classe anterior, investigue a visão USER_TYPES:
select type_name, attributes, methods from user_types; TYPE_NAME ATTRIBUTES METHODS ----------------- ---------- --------FUNCIONARIO_T 3 5
• •
Vale a pena criar uma convenção própria para denominação de classes. Neste caso, acrescentou-se o sufixo _t ao nome da classe; Para eliminar uma classe, emitiríamos o comando:
drop type funcionario_t;
Naturalmente, resulta impossível eliminar classes que façam parte de definições de tabelas ou de outras classes. A especificação do corpo da classe funcionario_t encontra-se no arquivo 17_Cria_Classe_Funcionario_Body.sql: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
create or replace type body Funcionario_t as --metodos de acesso a dados: member procedure set_matricula (new_matricula in varchar2) Is Begin matricula := new_matricula ; end; member procedure set_nome (new_nome in varchar2) Is Begin self.nome := new_nome ; end; member procedure set_data_nascimento (new_data_nascimento in date) Is Begin self.data_nascimento := new_data_nascimento ; end; -- mostra atributos member procedure mostre Is Begin dbms_output.put_line ('matricula: '|| matricula); dbms_output.put_line ('nome: '|| nome); dbms_output.put_line ('data nascimento: '|| to_char(data_nascimento)); end;
Oracle 9i Fundamental
212
27. 28. 29. 30. 31. 32. 33. 34.
-- calcula a idade member function retorna_idade return integer Is Begin return trunc(sysdate-data_nascimento)/365; end; end;
Observações •
A visão USER_OBJECTS revela também as classes criadas:
column object_name format a20 select object_name, object_type from user_objects where object_name like '%FUNCIONARIO%'; OBJECT_NAME -------------------FUNCIONARIO_T FUNCIONARIO_T
•
OBJECT_TYPE --------------TYPE TYPE BODY
Note a presença da palavra reservada self nos métodos set_nome e set_data_nascimento (linhas 11 e 17 respectivamente). Ela representa a instância que estiver utilizando este código. Apesar de dispensável, recomenda-se utilizá-la para aumentar a clareza do código.
A rotina seguinte instancia um objeto da classe recém-criada: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
create or replace procedure cria_funcionario Is p funcionario_t; /* declaração de uma variável objeto */ Begin /* Instanciando... */ p := funcionario_t ('0001', 'Leonardo', to_date('17/10/98')); /* Invocando métodos... */ p.mostre; dbms_output.put_line(' alterando...'); p.set_nome('Leonardo Guimarães Terra'); p.mostre; /* existe um argumento "in out" implícito: self */ dbms_output.put_line('idade: ' || p.retorna_idade); end;
Uma possível execução: set serveroutput on exec cria_funcionario
E a saída: matricula: 0001 nome: Leonardo data nascimento:
17/10/98
alterando... matricula: 0001 nome: Leonardo Guimarães Terra data nascimento: 17/10/98 idade: 3
Oracle 9i Fundamental
213
17.3 - Herança Como visto no texto introdutório deste capítulo, uma das grandes vantagens da POO consiste em reutilizar código que já esteja pronto. Esta característica implementa-se basicamente pelo mecanismo de herança, ou, mais formalmente, Object Type Inheritance. As porções de código seguintes foram extraídas do arquivo exemplo 17_Cria_Classe_Herdada_Gerente.sql. Será criada uma nova classe, Gerente_t, a partir de outra já existente, Funcionario_t: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
create or replace type Gerente_t under Funcionario_t ( -- atributos: departamento varchar2(20), nivel number(1), -- 1, 2 ou 3 --metodos de acesso a dados: member procedure set_departamento (new_departamento in varchar2), member procedure set_nivel (new_nivel in number), --demais metodos: overriding member procedure mostre );
Observações •
•
•
A herança acontece graças à cláusula under (linha 1), porém a classe da qual está-se derivando deve ter sido criada com a cláusula not final; Quando ocorrer polimorfismo, isto é, um método de uma classe derivada substituir o homônimo da classe base, deve-se utilizar a cláusula overriding (linha 10); A nova classe Gerente_t possuirá cinco atributos: matricula, nome, data_nascimento (herdados de Funcionario_t), departamento e nível. Terá também sete métodos (quatro herdados e três próprios).
A criação do corpo da nova classe não oferece surpresas: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
create or replace type body Gerente_t as --metodos de acesso a dados: member procedure set_departamento (new_departamento is begin departamento := new_departamento; end;
in varchar2)
member procedure set_nivel (new_nivel in number) is begin self.nivel := new_nivel ; end; -- mostra atributos overriding member procedure mostre is begin dbms_output.put_line ('Matricula: '|| matricula);
Oracle 9i Fundamental
214
19. 20. 21. 22. 23. 24.
dbms_output.put_line dbms_output.put_line to_char(data_nascimento)); dbms_output.put_line dbms_output.put_line end; end;
('Nome: '|| nome); ('Data nascimento: '|| ('Departamento: '|| departamento); ('Nivel: '|| to_char(nivel));
Observação •
Note a presença da cláusula overriding na definição do método polimórfico.
Finalmente, a procedure seguir instancia um objeto da classe recémcriada: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
create or replace procedure cria_gerente Is p gerente_t; /* declaração de uma variável objeto */ Begin /* Instanciando... */ p := gerente_t ('0002', 'Mariana Terra', to_date('6/12/60'), 'Biblioteca', 1); /* Invocando métodos... */ p.mostre; dbms_output.put_line('
alterando...');
p.set_nivel(3); p.mostre; dbms_output.put_line('idade: ' || p.retorna_idade); end;
E a saída: Matricula: 0002 Nome: Mariana Terra Data nascimento: 06/12/60 Departamento: Biblioteca Nivel: 1 alterando... Matricula: 0002 Nome: Mariana Terra Data nascimento: 06/12/60 Departamento: Biblioteca Nivel: 3 idade: 41
17.4 - Tabelas de Objetos Uma vez criada a classe, podemos construir tabelas cujos campos sejam, na verdade, instâncias. Por exemplo: create table funcionarios of funcionario_t (primary key (matricula));
Oracle 9i Fundamental
215
Uma linha seria alimentada assim32: insert into funcionarios values (funcionario_t('001','Alvaro Alpheratz',to_date('12/09/1968')));
Para listar parte de um campo objeto, ou seja, apenas alguns atributos de um objeto que faz parte da definição da tabela, teríamos o seguinte comando: select matricula, nome from funcionarios; MATRICULA ---------001 002 003 004 005 006 007 008 009 010
NOME -----------------------------------Alvaro Alpheratz Bernardo Beid Carla Caph Daniel Dheneb Efraim Eltanin Francisca Fomalhaut Guilherme Gomeisa Horácio Hyadum Inácio Izar João Jabbah
Uma tabela de objetos pode possuir um campo que seja uma referência a uma instância que conste de uma tabela de objetos. Isto, em tese, seria uma chave estrangeira e viabilizaria, por exemplo, o fato de que um funcionário pudesse coordenar vários projetos. A nova classe teria uma especificação assim33: create or replace type projeto_t as object( -- atributos: cod_projeto varchar2(10), descricao varchar2(60), urgencia number(2), -- inteiro que classifica o projeto ref_responsavel ref funcionario_t, --metodos de acesso a dados: member procedure set_cod_projeto (new_cod_projeto in varchar2), member procedure set_descricao (new_descricao in varchar2), member procedure set_urgencia (new_urgencia in number), --demais metodos: member procedure mostre );
Após definir o corpo, a tabela seria criada: create table projetos of projeto_t (primary key (cod_projeto));
E para alimentá-la: insert into projetos select projeto_t('001','Exportação de sapatos para Ásia',9, ref(f)) from funcionarios f where matricula = '001';
32
33
Os comandos que criam a tabela Funcionarios e a arquivo exemplo 17_Cria_Tabela_Funcionarios.sql. Os comandos seguintes encontram-se no 17_Trata_Classe_Projetos.sql
Oracle 9i Fundamental
alimentam arquivo
estão
no
exemplo:
216
Observações •
•
Caso a tabela não tivesse sido criada com auxílio do operador ref, que na verdade trata-se de um ponteiro, teríamos uma redundância enorme, já que, caso um funcionário coordenasse dez projetos, seus dados estariam repetidos dez vezes; O comando seguinte mostraria nomes de projetos e respectivos responsáveis:
select descricao, f.nome from projetos p, funcionarios f where p.ref_responsavel = ref(f); DESCRICAO ----------------------------------Exportação de sapatos para Ásia Fabricação de solas de borracha Vendas no mercado interno
•
•
NOME -----------------Alvaro Alpheratz Bernardo Beid Alvaro Alpheratz
As boas normas de programação recomendam que exista um método de retorno para cada atributo. Desta forma, praticaríamos o encapsulamento; Infelizmente, o Oracle não proíbe que objetos referenciados possam ser eliminados. O comando seguinte contornaria tal problema:
update projetos set ref_responsavel = null where ref_responsavel is dangling;
17.5 - Tabelas Aninhadas Como já vimos, campos de tabelas não precisam ser mais variáveis de tipos primitivos, que comportam apenas um valor. Além de poderem ser objetos, pode-se também criar um campo-lista, ou seja, um repositório homogêneo de elementos. Na verdade, trata-se da possibilidade de fazer de um campo um vetor. O recurso Nested Table permite acrescentar uma coleção esparsa de tamanho variável a uma classe ou mesmo como campo de uma tabela. Como resulta impossível acrescentar novas colunas em "object tables", será alterada a classe Funcionario_t para que comporte uma lista de dependentes. Os comandos necessários encontram-se no script: 17_Cria_Classe_Funcionario_com_ Dependentes.sql. A classe seria reconstruída como: create or replace type dependentes_t as table of varchar2(20);
Oracle 9i Fundamental
217
Observe que, antes de emitir o comando seguinte, tabelas e tipos previamente criados que tenham a classe Funcionario_t como base devem ser destruídos para que depois sejam reconstruídos: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
create or replace type funcionario_t as object( -- atributos: matricula varchar2(10), nome varchar2(60), data_nascimento date, dependentes dependentes_t, --metodos de acesso a dados: member procedure set_matricula (new_matricula in varchar2), member procedure set_nome (new_nome in varchar2), member procedure set_data_nascimento (new_data_nascimento in date), --demais metodos: member function retorna_idade return integer, member procedure mostre );
E a tabela: create table funcionarios of funcionario_t (primary key (matricula)) nested table dependentes store as dependentes_st;
Observações • •
• •
A lista pode ser ilimitada e ainda ser esparsa, isto é, conteria "buracos"; A cláusula store as indica o local físico de armazenamento da tabela aninhada. Essa tabela somente pode ser acessada por meio da outer table, ou tabela externa (funcionários); Uma tabela aninhada não pode conter outra; Uma inserção deve considerar a lista:
insert into funcionarios values (funcionario_t('001','Alvaro Alpheratz', to_date('12/09/1968'), dependentes_t('Maria', 'Pedro', 'Hugo'))); insert into funcionarios values (funcionario_t('002','Bernardo Beid', to_date('7/01/1976'),null));
•
Os dependentes poderiam ser listados predefinido column_value e a função the:
utilizando
o
alias
select column_value Dependentes from the (select dependentes from funcionarios where matricula = '001'); DEPENDENTES -------------------Maria Pedro Hugo
Oracle 9i Fundamental
218
17.6 - Vetores Variáveis Assim como tabelas aninhadas, vetores variáveis representam listas de valores de um mesmo tipo. A principal diferença consiste na obrigatoriedade de estabelecer limites físicos para eles. A versão definitiva de classe e tabela de funcionários, agora com dependentes e ascendentes, encontra-se nos scripts: 17_Cria_Classe_Funcionario_completa.sql e 17_Cria_Tabela_Funcionarios_completa.sql
A classe seria reconstruída como: create or replace type dependentes_t as table of varchar2(20); -- Esta lista armazenará os nomes dos pais, avós paternos e avós maternos create or replace type ascendentes_t as varray(6) of varchar2(20); create or replace type funcionario_t object( -- atributos: ... dependentes dependentes_t, ascendentes ascendentes_t, --metodos de acesso a dados: ... );
as
Observações • •
Apesar de "variável", a quantidade de elementos não pode ultrapassar o limite preestabelecido; A criação da tabela não exigirá a cláusula store as, já que o varray será armazenado internamente à tabela; entretanto, a inserção de novas linhas deve mudar:
insert into funcionarios values (funcionario_t('001','Alvaro Alpheratz', to_date('12/09/1968'), dependentes_t('Maria', 'Pedro', 'Hugo'), ascendentes_t('Enrique', 'Guillermina', 'Eduardo', 'Marta', 'Alberto', 'Albertina'))); insert into funcionarios values (funcionario_t('002','Bernardo Beid', to_date('7/01/1976'),null, null));
•
Os dependentes poderiam ser listados utilizando predefinido column_value e as funções the e cast:
o
alias
select column_value Ascendentes from the (select cast(ascendentes as dependentes_t) from funcionarios where matricula = '001');
E a saída: ASCENDENTES
Oracle 9i Fundamental
219
-------------------Enrique Guillermina Eduardo Marta Alberto Albertina 6 rows selected.
EXERCÍCIOS 1. Liste pelo menos três diferenças entre tabelas relacionais e as "Object Tables". • Quais seriam as vantagens ou inconvenientes de existir uma tabela que tivesse alguns campos primitivos e outros oriundos de classes? 2. A partir do modelo relacional utilizado até aqui, realize sua migração para um modelo de objetos. • Inicialmente, identifique as classes (Alunos, Cursos, Instrutores, Turmas), em seguida liste os atributos e finalmente relacione os métodos para cada classe. • Como seria caracterizado o fato de um aluno ser matriculado em uma dada turma? • Crie também uma nova classe, ASSUNTOS, que será base de CURSOS. 3. Com base no modelo criado no exercício anterior, implemente as classes Assunto_t e Curso_t. Atributos de assuntos: COD_ASSUNTO, NOME_ASUNTO e PRECO. Atributos de cursos: COD_CURSO, NOME_CURSO e CH. Observe que todos os cursos do mesmo assunto terão o mesmo preço. Crie uma lista variável para armazenar os pré-requisitos de cada curso. Além dos métodos de acesso a dados, implemente outro que revele a lista dos pré-requisitos. • Cada membro da lista de pré-requisitos deve ser uma referência a um objeto. 4. Crie a tabela CURSOS baseada no tipo Curso_t. • Uma vez criada, insira nela algumas linhas. 5. Localize no Dicionário de Dados as classes e a tabela criadas. Investigue as visões: USER_TYPES, USER_OBJECT_TABLES, USER_TYPES_ATTRS e USER_TYPES_METHODS. Oracle 9i Fundamental
220
6. No arquivo exemplo 13_Exemplo_Cursor_Implicito_2.sql, capítulo 13, aparece a seguinte linha de código:
visto
no
type lista_instrutores is table of number; instrutores lista_instrutores:= lista_instrutores (1, 2, 5, 6); ...
Explique de que forma a POO foi utilizada.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Criar uma Especificação de Classe
Pelo SQL*Plus Worksheet execute um script que contenha o comando create or replace type nome as object (declarações). Podem constar da definição de uma classe atributos de tipos primitivos, instâncias de outras classes, listas de tamanho variável (nested tables) ou fixo (varray), além de métodos (member procedure e member function). Veja um exemplo em 17_Cria_Tabela_Funcionarios_completa.
Criar um Classe
Pelo SQL*Plus Worksheet execute um script que contenha o comando create or replace type body nome as, implementações de métodos. Veja um exemplo no arquivo fornecido: 17_Cria_Classe_Funcionario_Body.
Corpo
de
Utilizar o mecanismo de Herança
Na classe base, deve-se utilizar a cláusula not final. Já nas derivadas, substitui-se as object por under classe_base. Métodos polimórficos devem ser precedidos pela cláusula overriding.
Instanciar um objeto de alguma classe previamente criada
Deve-se implementar um procedimento que declare uma variável do tipo classe, aloque espaço em memória e ative seus métodos. Veja um exemplo em 17_Instancia_Funcionario.
Eliminar uma classe
Utilize o comando drop type nome. Não se pode eliminar uma classe que seja base de tabelas ou classes.
Criar uma Objetos
Tabela
de
Utilize o comando: create table nome of classe (primary key (campo));
Criar uma referência entre objetos
Utilize o modificador REF. Veja um exemplo em 17_Trata_Classe_Projetos.
Listar Classes
Investigue a visão USER_TYPES.
Listar Tabelas Objeto
Investigue a visão USER_OBJECT_TABLES.
Oracle 9i Fundamental
221
ANOTAÇÕES
Oracle 9i Fundamental
222
Capítulo 18 – INTRODUÇÃO À ADMINISTRAÇÃO OBJETIVOS • • •
Compreender a importância do Administrador de Bancos de Dados (Database Administrator - DBA); Ter noções sobre a organização de um Banco de Dados Oracle, tanto física como logicamente; Situar objetos já conhecidos (tabela, índice, etc.) na organização interna de um Banco de Dados Oracle.
ARQUIVOS NECESSÁRIOS •
Nenhum.
PRÉ-REQUISITOS • • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Conhecer principais objetos Oracle: tabela, índice, constraint, visão, seqüên-cia, function, stored procedure e trigger; Estado de espírito para enfrentar situações tensas; Criatividade e iniciativa para resolver grandes problemas em pouco tempo.
Oracle 9i Fundamental
223
MOTIVAÇÃO Um Dia na Vida de Daniel Barbosa Alves (DBA) Como todo DBA, Daniel Barbosa Alves é um sujeito meticuloso e com espírito detetivesco. Sua missão: manter o Banco de Dados de sua empresa "vivo" e "voando baixo". O Banco não é pequeno; existem tabelas com 500.000 registros e vários arquivos estendem-se além de um giga byte. Certo dia, D.B.A. acordou com um mau pressentimento. Chegou mais cedo do que de costume e praticou a rotina diária: a) Constatou que o backup noturno havia sido concluído com sucesso; b) Verificou a existência de arquivos de "trace" (não havia); c) Investigou as novas entradas no arquivo de alertas (nada novo); d) Conferiu os gargalos por usuário e arquivo (tudo bem); e) Checou o tamanho dos arquivos e suas taxas de ocupação (a maior tabela ocupava 50% do espaço disponível); f) Realizou testes de memória (o tempo de resposta estava bom). A manhã transcorria tranqüila, quando, de repente, soou o alarme: NINGUÉM CONSEGUIA SE CONECTAR! Pânico geral. Os estagiários corriam de um lado ao outro absolutamente perdidos. Os gerentes tropeçavam uns nos outros, os diretores berravam impropérios, o presidente desmaiou...só D.B.A. mantinha-se calmo. Antes que alguém se lembrasse dele, o problema foi resolvido. Ora, pensou, não há arquivos de trace, o alerta nada avisa, o espaço está bom, a memória também, não há gargalos e eu estou conectado! Só pode ser algum problema de rede. Dito e feito. Após uma rápida verificação, constatou-se que um dos hubs tinha se apagado...
TEORIA 18.1 - O DBA Um típico Banco de Dados Oracle é quase uma entidade viva, em constante mutação. Se existe algo constante na vida de um Banco, é a mudança. A cada dia surgem fatos novos, problemas inusitados, sintomas inesperados. Trata-se de um quadro que não pode ser relegado ao abandono. Deve existir alguém que constantemente acompanhe a situação e tome as medidas corretivas necessárias nos momentos adequados para que não se entre em estado de crise. A presença do Administrador de Bancos de Dados (Database Administrator - DBA) é imprescindível na vida de um Banco. Sem dúvida, uma figura humana peculiar que sempre deve estar atenta e preparada para o pior. Todo DBA deve ser meio 24x7x365, isto é, estar disponível vinte quatro Oracle 9i Fundamental
224
horas por dia, sete dias por semana e trezentos e sessenta e cinco dias por ano (pelo menos, em anos bissextos, há um descanso!). Nada de férias, feriados ou tranqüilas noites de sono, pois um típico Banco Oracle nunca pára, nunca dorme. O DBA está presente na vida de um Banco desde antes que ele exista, isto é, cabe ao DBA instalar o Oracle, tanto na máquina Servidora quanto nas Clientes. Evidentemente, é responsabilidade do DBA prepará-lo de forma a aproveitar otimamente os recursos de hardware, bem como disponibilizá-lo para que possa ser utilizado por usuários, cujo acesso, aliás, também é viabilizado pelo DBA. Uma vez criado e disponibilizado, o DBA deve acompanhar o constante processo de mudanças que acontece no Banco. E ser altamente pró-ativo, ou seja, ter a habilidade de prever possíveis problemas e tomar medidas que os evitem. Mas para que isto seja possível, o DBA deve ser um profundo conhecedor da organização interna do Banco, tanto em nível físico (memória, processos, arquivos) quanto lógico (distribuição dos dados). E como se ainda fossem poucas as tarefas do DBA, ele também é responsável pela integridade dos dados. Em caso de quaisquer perdas (falha em disco, destruição acidental, etc.), o DBA deve prontamente oferecer uma cópia que restaure o estado dos dados antes da perda. Resumindo, cabe ao DBA: • Instalar; • Criar; • Disponibilizar; • Gerenciar usuários; • Monitorar; • Otimizar desempenho; • Fazer cópias de segurança; • Adequar os recursos disponíveis de forma a atender à crescente demanda por dados. Estar atento aos orçamentos estabelecidos; • Recuperar o estado prévio à perdas do Banco. Finalmente, ainda poderíamos acrescentar mais duas: • Reunir-se periodicamente com Analistas de Dados e Desenvolvedores para obter configurações ótimas para acessos ao Banco; • Intermediar a relação entre o usuário e o Suporte Oracle. Felizmente, hoje a vida de um DBA é muito mais tranqüila do que era há alguns anos. Já existem diversos produtos no mercado que facilitam
Oracle 9i Fundamental
225
bastante seu dia-a-dia. Neste livro, utilizaremos a ferramenta gráfica denominada Enterprise Manager Console34. Por exemplo, a figura seguinte revela quem está conectado em um dado momento:
18.2 - Organização Interna 18.2.1 - Organização Física Um Banco de Dados Oracle pode ser definido como um conjunto de dados tra-balhados por uma ou mais aplicações. Fisicamente, consiste na interrelação de quatro elementos: Arquivos
Áreas em disco em que são armazenados os dados propriamente ditos, informações de controle e os chamados metadados (dados sobre dados).
Memória
Para otimizar o acesso a discos (arquivos), existem diversas estruturas na memória.
Processos 35
Instância
34
35
Pequenos programas que desempenham tarefas específicas. Por exemplo, cada sessão gera, normalmente, um processo (cliente) que se conecta a outro dedicado (Servidor). Este termo provém do ambiente Unix; na plataforma Windows, o equivalente ao processo denomina-se thread. Reunião das estruturas de memória a diversos processos, que viabiliza a utilização do Banco. Para que um Banco possa ser utilizado, deve-se previamente disponibilizar uma Instância. No ambiente Windows NT/2000, cada instância representa um
Esta ferramenta faz parte de um grupo mais amplo denominado Oracle Enterprise Manager (OEM). Dele faz parte a já bastante utilizada SQL*Plus Worksheet, entretanto existem diversas outras que agilizam diversas tarefas do DBA. Infelizmente, os demais membros do OEM fogem ao escopo proposto neste livro. Apenas para simplificar a nomenclatura, em plataforma Windows, quando se mencionar processo, entenda que se trata de um thread.
Oracle 9i Fundamental
226
processo, que pode ser acompanhado a partir da guia Processes do Task Manager.
Veja o capítulo 19 para maiores detalhes.
18.2.2 - Organização Lógica Para que um Banco de Dados exista, devem ser cumpridas várias etapas. Tudo começa no Projeto Conceitual em que se transforma um problema/necessidade em um Modelo que revele o relacionamento entre entidades. Segue-se o Projeto Lógico em que já existe uma preocupação em eliminar redundâncias (normalização) e proporcionar um enfoque mais próximo à realidade das ferramentas SGDBR (Oracle, por exemplo). Finalmente, obtém-se um conjunto de tabelas que podem ser criadas fisicamente. O trabalho consistindo em derivar um Banco de Dados a partir de um problema, passando pelas etapas anteriormente descritas, geralmente não cabe ao DBA. Existe um profissional específico incumbido de tal tarefa, o Analista de Dados. No Apêndice C, Bibliografia Comentada, veja referências a livros que tratam sobre o processo de modelagem de dados. Mas, antes que uma tabela possa existir fisicamente, deve-se organizar logicamente o Banco em Tablespaces. Por exemplo, o banco nativo do Windows2000, dependendo do número de recursos instalados, já vem com várias. Vejamos as mais importantes: SYSTEM
Primeira a ser criada e única absolutamente imprescindível. Nela estará o Dicionário de Dados (metadados).
UNDOTBS
Os dados somente são gravados efetivamente ao concluir com sucesso uma transação (COMMIT). Enquanto esta ratificação não acontece, valores antigos devem ser guardados em áreas especiais ditas de rollback, que constam nesta tablespace.
TEMP
Área de trabalho utilizada durante operações de ordenação ou busca que excedam os recursos em Memória.
USERS
Destina-se aos dados propriamente ditos.
Ao criar uma Tablespace, informam-se os arquivos constituintes36. Veja o capítulo 20 para maiores detalhes.
18.3 - Objetos de um Banco de Dados Um Banco de Dados Oracle também pode ser visto, logicamente, como um conjunto de Schemas que, por sua vez, representam grupos de objetos. Vejamos os de maior destaque37: 36
Isto somente não acontece para os OMF (Oracle Manged Files), recurso introduzido pela versão 9i, que permite omitir os nomes físicos dos arquivos que constituem a Tablespace. Mais detalhes no capítulo 20.
Oracle 9i Fundamental
227
Objeto 1. 2. 3. 4.
Observações Repositório de dados; dividido em colunas, e possui Tabela constraints (restrições). Estruturas auxiliares que aceleram acesso a campos muito Índice procurados. Reunião física de uma ou mais tabelas que tenham campos em Cluster comum. Diminui tempos de consultas, mas piora os de atualizações (inserção, alteração, exclusão). Forma alternativa de armazenamento de dados em que uma Hash Cluster linha é encontrada a partir de um algoritmo (hash).
5. View 6. Materialized View 7. Sequence 8. Procedure 9. Function 10. Package 11. Type 12. Trigger 13. Synonym 14. Link
Database
15. Dimension
Pseudotabela obtida por um comando SELECT préarmazenado. Trata-se de uma View, porém possui dados armazenados. Utilizadas para otimizar consultas. Mecanismo que permite gerar números automaticamente. Bloco de código PL/SQL tratado como comando. Bloco de código PL/SQL que retorna um valor. Reunião física de procedures e functions. Na verdade, são dois: Especificação e Corpo. Estrutura de dados representando uma classe. Também divide-se em especificação e um corpo. Veja capítulo 17. Bloco PL/SQL ativado automaticamente após alguma alteração em tabela. Nome alternativo dado a um objeto, visando facilitar a manipulação. Representa uma conexão com outro Banco de Dados Oracle. Forma alternativa de armazenamento de dados em que os membros obedecem a uma organização hierárquica. Utilizada em Bases OLAP (Data Warehouses).
Os objetos de um Schema podem ser listados a partir da visão USER_OBJECTS.
37
O leque de objetos disponíveis dependerá da maneira como foi conduzida a criação do Banco, entretanto, para ter-se uma idéia da variedade disponível, conecte-se com um usuário possuindo privilégios de DBA e execute a seguinte consulta: select distinct object_type from dba_objects;
Oracle 9i Fundamental
228
EXERCÍCIOS Antes de começar, verifique se você possui uma conta com privilégios de DBA. Neste grupo de exercícios você trabalhará basicamente com a ferramenta Enterprise Manager Console. 1. Localize a Enterprise Manager Console e realize uma conexão independente, ou seja, não vinculada ao Oracle Management Server38. 2. Conecte-se ao Banco de Dados disponível. • Expanda o item Rede e depois Banco de Dados. Assim como no SQL*Plus Worksheet, serão pedidas uma identificação e a senha. • Expanda o item Armazenamento. Verifique as Tablespaces, seus tamanhos e quanto espaço há disponível em cada uma. • Ainda sob o item Armazenamento, liste os arquivos associados a cada Tablespace. • Expanda o item Esquema. Liste as tabelas do usuário Scott. Quantos constraints possui a tabela Dept de Scott? • Expanda o item Segurança. Liste os privilégios de sistema e os papéis atribuídos ao seu usuário.
38
Faríamos uma conexão via OMS caso tivéssemos vários ambientes por administrar. Veja mais detalhes sobre o funcionamento do Oracle Enterprise Manger (do qual o OMS faz parte), no guia Oracle Enterprise Manager Concepts Guide, presente na documentação do Oracle 9i.
Oracle 9i Fundamental
229
Capítulo 19 – ORGANIZAÇÃO FÍSICA OBJETIVOS • • • • • • •
Identificar os arquivos relevantes de um Banco de Dados Oracle; Conhecer a organização da memória em estruturas; Diferenciar os processos que desempenham papéis imprescindíveis ou de apoio; Analisar criticamente um Arquivo de Parâmetros (INIT.ORA); Disponibilizar ou não um Banco ou Instância para utilização; Compreender o que ocorre durante a execução de comandos DML; Destacar as características próprias de um Banco instalado sob Windows 2000.
NOVIDADES •
•
•
•
•
39
39
A ferramenta Server Manager foi descontinuada. O que era feito com ela, agora acontece no SQL*Plus em sua versão gráfica (SQL*Plus Worksheet) ou de linha de comando; Não existe mais a possibilidade de realizar uma conexão interna (CONNECT INTERNAL/senha). Agora deve-se especificar a conta como especial (CONNECT SYS/senha AS SYSDBA); Diversas tarefas que lidam com arquivos (criação de uma Tablespace, por exemplo) podem ser simplificadas graças aos OMF (Oracle Managed Files); Além do tradicional INIT.ORA, agora existe um arquivo binário capaz de armazenar parâmetros, o SPFILE.ORA. Ele permite alterar parâmetros dinamicamente, fazendo com que as modificações já valham na próxima abertura do Banco. Aliás, o número de parâmetros que podem ser alterados sem necessidade de fechar e abrir o Banco, aumentou consideravelmente; O tamanho do bloco que constitui os arquivos e a Database Buffer Cache é variável. Isto é, podem existir tabelas com tamanho de bloco 2 KB e outras com 8 KB. Como conseqüência disto, o famoso parâmetro DB_BLOCK_BUFFERS ficou obsoleto;
A partir deste capítulo haverá uma nova seção, Novidades. Nela serão destacadas as inovações da versão 9i em relação às anteriores (8i, 8, 7, etc.).
Oracle 9i Fundamental
230
•
A funcionalidade MTS (Multithreaded server) agora denomina-se SS (Shared Server) e vem instalado por default.
ARQUIVOS NECESSÁRIOS • • •
Init.ora; 19_HitRatioPorUsuario.sql; 19_HitRatioPorArquivo.sql.
PRÉ-REQUISITOS • • • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Conhecer principais objetos Oracle: tabela, índice, constraint, visão e seqüên-cia; Saber o que é uma Transação, quando começa, quando termina; Definir Arquivo, Memória, Processo e Instância; Identificar as Tablespaces de um Banco.
TEORIA 19.1 - Arquivos Qualquer dado, seja de controle ou não, que deva ser armazenado permanentemente reside em um arquivo. Um típico Banco de Dados Oracle contém dezenas de arquivos que guardam, além de dados, informações de controle ou de acompanhamento. Há seis tipos detalhados em seguida. Antes de analisar os arquivos propriamente ditos, convém fazer um breve comentário sobre diretórios. A instalação do Oracle cria vários, porém vale destacar dois: o ORACLE_HOME e o ORACLE_BASE. Enquanto o primeiro armazena toda a infra-estrutura necessária para que os programas que constituem o Oracle possam ser executados, o segundo contém, além do primeiro, um diretório de administração e outro de dados. Por exemplo, sob o Windows 2000, teríamos a seguinte estrutura:
Oracle 9i Fundamental
231
Nesta figura ORACLE_BASE estaria representado pelo diretório \oracle, enquanto ORACLE_HOME seria \oracle\ora92.
19.1.1 - Data Files Contêm os dados ou metadados que constam em tabelas, índices, áreas temporárias ou de rollback. Estão necessariamente ligados a uma Tablespace. As visões dinâmicas V$DBFILE (apenas dois campos) e V$DATAFILE (mais completa) listam os arquivos do Banco corrente: select * from v$dbfile order by file#;
E o resultado: FILE# ---------1 2 3 4 5 6 7 8 9 10
NAME -------------------------------------------------E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF E:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF E:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF E:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF E:\ORACLE\ORADATA\ACAD9\INDX01.DBF E:\ORACLE\ORADATA\ACAD9\ODM01.DBF E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF E:\ORACLE\ORADATA\ACAD9\USERS01.DBF E:\ORACLE\ORADATA\ACAD9\XDB01.DBF
Freqüentemente, uma Tablespace possui vários arquivos. O inverso nunca ocorre, isto é, um arquivo não pertence a mais de uma Tablespace. Outra visão que contém informações sobre arquivos é DBA_DATA_FILES. Ela possui, entre outros campos, o número relativo do arquivo (RELATIVE_FNO). Em conjunto com o número físico (FILE_ID) permite o aumento significativo de arquivos por Banco. select column_name Campo, data_type Tipo from dba_tab_columns where table_name = 'DBA_DATA_FILES';
E o resultado: CAMPO TIPO ------------------------------ -----------
Oracle 9i Fundamental
232
FILE_NAME FILE_ID TABLESPACE_NAME BYTES BLOCKS STATUS RELATIVE_FNO AUTOEXTENSIBLE MAXBYTES MAXBLOCKS INCREMENT_BY USER_BYTES USER_BLOCKS
VARCHAR2 NUMBER VARCHAR2 NUMBER NUMBER VARCHAR2 NUMBER VARCHAR2 NUMBER NUMBER NUMBER NUMBER NUMBER
19.1.2 - Control Files Pequenos arquivos binários, atualizados constantemente pelo Oracle, guardam a estrutura do Banco e são responsáveis pelo sincronismo entre todos os arquivos. Se, durante a disponibilização do Banco, constar em um Control File uma informação que não seja consistente40, o Banco não poderá ser utilizado. A visão V$CONTROLFILE traz informações interessantes: select name from v$controlfile; NAME -------------------------------------------------E:\ORACLE\ORADATA\ACAD9\CONTROL01.CTL E:\ORACLE\ORADATA\ACAD9\CONTROL02.CTL E:\ORACLE\ORADATA\ACAD9\CONTROL03.CTL
Na verdade, bastaria apenas um arquivo de controle, porém, dada sua importância, recomenda-se que existam vários (idênticos entre si) e, de preferência, em discos diferentes.
19.1.3 - Redo Log Files Mantêm um histórico das transações efetuadas. Úteis em caso de perda de dados, já que as operações poderão ser refeitas. No mínimo existem dois e são gravados de forma cíclica, ou seja, quando se esgota o espaço em um, começa-se a gravar no outro. Dá-se o nome de log switch a esta mudança entre arquivos. Analogias: extrato bancário ou prontuário de um paciente. Claro que nestes casos não há como "refazer" as operações. A visão V$LOGFILE revela esses arquivos: select * from v$logfile;
Saída: 40
Por exemplo, enquanto o banco estava fechado, qualquer ou substituiu-se inadvertidamente.
Oracle 9i Fundamental
apagou-se
um
arquivo
233
GROUP# STATUS TYPE -------- ------- ------3 ONLINE 2 STALE ONLINE 1 STALE ONLINE
MEMBER ---------------------------------------E:\ORACLE\ORADATA\ACAD9\REDO03.LOG E:\ORACLE\ORADATA\ACAD9\REDO02.LOG E:\ORACLE\ORADATA\ACAD9\REDO01.LOG
O termo stale indica que o arquivo em questão não está sendo utilizado. Como já citado, os Redo Log Files são gravados ciclicamente, ou seja, uma vez preenchido o primeiro, vai-se ao segundo; uma vez ocupado o segundo, vai-se ao terceiro e assim por diante. Ao completar o último, volta-se a utilizar o primeiro, perdendo-se o registro das transações que lá estavam. Felizmente, o Oracle oferece um mecanismo para resguardar os conteúdos dos Redo Log Files: trata-se do recurso Archiving. Caso o Banco esteja em modo Archiving, uma vez preenchido um Redo Log File, acontecerá uma cópia dele (Archived Redo Log File), de preferência em outro disco ou para fita. Isto terá um papel fundamental no caso de ocorrerem perdas e seja necessário recuperar um Backup. Voltaremos a este interessante recurso no capítulo 25. É bastante comum a existência dos arquivos multiplexados, isto é, em vez de existir um arquivo, existem vários membros e atualizados em simultâneo, preferen-cialmente, em discos diferentes. Quando ocorre o log switch, há uma mudança de grupo. Esta prática proporciona mais segurança, já que, caso se perca um disco contendo esses arquivos, resta outro capaz de prosseguir os trabalhos. O comando seguinte acrescenta um novo Redo Log File: alter database add logfile group 4 ('E:\ORACLE\ORADATA\ACAD9\REDO04.LOG') size 100 M;
Pode-se confirmar o sucesso deste comando consultando V$LOGFILE, ou por meio de outra visão, mais detalhada, V$LOG: select group#, members, status, first_change#, to_char(first_time, 'dd/mm/yy hh24:mi:ss') "PRIMEIRA VEZ"
from v$log
Saída: GROUP# MEMBERS STATUS FIRST_CHANGE# PRIMEIRA VEZ ---------- ---------- ---------------- ------------- ----------------1 1 INACTIVE 291346 20/04/02 21:32:23 2 1 CURRENT 311618 21/04/02 07:08:51 3 1 INACTIVE 267824 20/04/02 19:57:11 4 1 UNUSED 0
O conteúdo do campo members maior que um indica que há multiplexação. Um Redo Log File pode ser excluído sempre e quando não esteja sendo utilizado, ou seja, o campo Status em V$LOG não pode ser igual a CURRENT ou ACTIVE: alter database drop logfile group 1;
Oracle 9i Fundamental
234
Vale notar que este comando não exclui fisicamente o arquivo associado ao Redo Log File. Isto deve ser feito manualmente, a não ser que o arquivo em questão tenha sido criado via OMF (Oracle Managed File). Trata-se de uma facilidade introduzida na versão 9i que facilita bastante a gerência de arquivos. Para caracterizar um Redo Log File como OMF, inicialmente devemos informar ao Oracle o destino41: alter system set db_create_online_log_dest_1 = 'E:\ORACLE\ORADATA\ACAD9';
A criação agora ficou mais simples: alter database add logfile group 1;
Este comando cria um Redo Log File com 100 MB no diretório especificado no parâmetro de sistema previamente preenchido (db_create_online_log_dest_1). Como não se especificou o nome do arquivo, o Oracle fará isto: select member from v$logfile where group# = 1
Saída: MEMBER --------------------------------------------E:\ORACLE\ORADATA\ACAD9\ORA_1_YD58S200.LOG
Outra vantagem dos OMF consiste na exclusão automática do arquivo físico. Assim, caso o comando seguinte possa acontecer, a eliminação manual posterior não será mais necessária: alter database drop logfile group 1;
19.1.4 - Arquivos SPFILE.ORA)
de
Parâmetros
(INIT.ORA
e
Esses arquivos possuem todas as informações necessárias para que uma Instância seja disponibilizada (etapa prévia à abertura do Banco). O nome deles pode trazer embutido o nome da Instância à qual se refere. Assim, o arquivo texto INITACAD9.ORA denominaria o arquivo de parâmetros da instância ACAD9 (Controle Acadêmico). Este nome também é conhecido por SID (System Identifier). Em plataformas Windows NT/2000, os arquivos de parâmetros geralmente encontram-se no diretório DATABASE sob ORACLE_HOME; já em ambientes Unix, estão em dbs, também sob ORACLE_HOME. Uma importante novidade introduzida na versão 9i foi o arquivo de parâmetros binário, o SPFILE.ORA. Ganha-se em praticidade, já que alterações em parâmetros dinâmicos (aqueles que podem ser alterados 41
Parâmetros do Banco, tais como: db_create_online_log_dest_1, serão vistos em seguida no item 19.1.4.
Oracle 9i Fundamental
235
enquanto o Banco estiver aberto), via comandos alter system ou alter session, podem ser gravadas de forma permanente, sem necessidade de editar o arquivo texto INIT.ORA, como ocorria até a versão 8i. Apenas um arquivo de parâmetros será lido na abertura do Banco. Veja adiante, no item 19.4.4, como se faz para especificar ou o arquivo texto ou o binário. A visão V$PARAMETER informa todos os parâmetros com os respectivos valores. select name, value from v$parameter order by 1; NAME VALUE ------------------------------------------------------------- -------------active_instance_count aq_tm_processes 0 archive_lag_target 0 audit_trail NONE background_core_dump partial background_dump_dest E:\oracle\admin\Acad9\bdump backup_tape_io_slaves FALSE bitmap_merge_area_size 1048576 blank_trimming FALSE buffer_pool_keep buffer_pool_recycle ... undo_management AUTO undo_retention 900 undo_suppress_errors FALSE undo_tablespace UNDOTBS use_indirect_data_buffers FALSE user_dump_dest E:\oracle\admin\Acad9\udump utl_file_dir workarea_size_policy MANUAL
250 linhas selecionadas.
Uma forma mais prática de listar parâmetros consiste em utilizar o comando show parameters, que aceita subcadeias de nomes de parâmetros. Por exemplo: show parameters spf
E a saída: NAME TYPE VALUE ------------------------------------ ----------- -----------------------------spfile string %ORACLE_HOME%\DATABASE\SPFILE% ORACLE_SID%.ORA
Observe na listagem anterior que o conteúdo do parâmetro spfile não é nulo. Infelizmente, o referido arquivo não pode ser aberto para inspeção. Para isto, conectados como SYS, pode-se criar uma versão texto através do comando CREATE PFILE, como revela o exemplo seguinte: create pfile = 'initAcad9.ora' from spfile = 'spfileAcad9.ora';
19.1.5 - Arquivos de Acompanhamento Oracle 9i Fundamental
236
Uma tarefa crucial do DBA consiste em acompanhar o que se passa em um Banco de Dados Oracle. Em particular, o DBA deve ter o costume de regularmente consultar o diretório que possua o arquivo de alertas e os de trace, estes produzidos quando acontecem situações anormais. Para descobrir onde estão esses arquivos, deve-se verificar o conteúdo do parâmetro background_dump_dest: show parameters DUMP_DEST NAME -----------------------------------background_dump_dest core_dump_dest user_dump_dest
TYPE ----------string string string
VALUE --------------------E:\oracle\admin\ACAD9\bdump E:\oracle\admin\ACAD9\cdump E:\oracle\admin\ACAD9\udump
O arquivo de alertas da instância ACAD9 denomina-se acad9ALRT.txt. Nele são registrados os eventos relevantes que ocorreram à instância em questão e os indicativos de erros. Quando estes forem graves, geram-se então os arquivos de trace que, dependendo da gravidade, deverão ser enviados ao Suporte Técnico da Oracle.
19.1.6 - Arquivo de Senhas Como veremos no capítulo que trata sobre segurança (24), uma conexão ao Oracle com plenos direitos (SYSDBA) pode acontecer sempre e quando o usuário constar em um arquivo especial, dito Password File. Criado no momento da criação do Banco, em plataformas Windows encontra-se em ORACLE_HOME\database. Já em ambientes Unix, ele reside sob ORACLE_HOME no diretório dbs.
19.2 - Memória A Memória tem papel fundamental no funcionamento do Banco. Seja para melhorar a performance geral, já que os acessos a disco não precisam ser tão numerosos ou freqüentes, seja para facilitar a gerência de recursos compartilhados entre os usuários; com pouca memória, o Banco literalmente pára. A Memória divide-se em duas estruturas básicas detalhadas em seguida.
19.2.1 - Program Global Area (PGA) Região privativa de cada sessão na qual são armazenados dados temporários, tais como: variáveis, endereços de rotinas ou ordenações. Cada conexão provoca a criação de uma pequena área na PGA.
19.2.2 - System Global Area (SGA) Região compartilhada pela qual passam todos os dados que serão lidos ou alterados, e comandos SQL emitidos a partir de clientes ou pelo próprio Oracle 9i Fundamental
237
Oracle Server. Também possui um registro de todas as transações que ocorrerem no Banco. Divide-se em cinco áreas: 11. Database Buffer Cache: conjunto de blocos (data block buffers) que armazena dados a serem lidos ou alterados. Bloco representa a menor unidade mani-pulável42 para o Banco. Cada bloco pode estar em quatro estados: o Livre: ainda não foi preenchido com algum dado proveniente de disco. No instante imediatamente posterior à abertura do Banco, só há blocos livres. o Ocupado: já foi preenchido. A ocupação acontece segundo um algoritmo de LRU (least recently used), isto é, os mais acessados ficam por mais tempo. o Sujo: já foi preenchido e alterado, portanto deve ser gravado em disco brevemente. o Rollback: possui um dado que poderá ser reaproveitado caso a transação que o alterou seja encerrada sem gravação. Graças à nova característica da versão 9i que permite a criação de Tablespaces com diferentes tamanhos de bloco, a DBC subdivide-se em várias áreas, cada uma representando um tamanho de bloco diferente. Tamanhos de blocos são em KB e podem ser de 2, 4, 6, 8, 16 e 32KB. A decisão quanto à escolha do melhor tamanho de bloco está relacionada à natureza do objeto a ser criado. Por exemplo, uma Tablespace que conterá tabelas cujas consultas pedirão poucas linhas, pede um bloco menor do que outra armazenando tabelas que possuam muitos dados por consultar a cada requisição. 12. Redo Log Buffer: registro de todas as transações comutadas. Trata-se de uma lista circular, cujo conteúdo é gravado periodicamente nos Redo Log Files. As transações ainda não encerradas residem em áreas de Rollback (memória ou disco). 13. Shared Pool Area: armazena comandos SQL e o Dicionário de Dados. Divide-se em duas áreas: Shared SQL Area: guarda comandos SQL "compilados". Isto permite que a segunda execução de um comando idêntico seja mais rápida que a primeira. Dictionary Cache: metadados. A ocupação é controlada pelo Oracle Server e também ocorre segundo algoritmo de LRU. 14. Large Pool Area: ocupada pela funcionalidade SS (Shared Server, ex-Multithreaded Server), quando presente (veja ítem 19.3.2.1, adiante) e pela ferramenta RMAN (Recovery 42
Por menor unidade manipulável entende-se a menor quantidade de bytes transferível do disco para a memória e vice-versa.
Oracle 9i Fundamental
238
Manager) como área de trabalho para operações de backup e restaurações de dados (mais detalhes no capítulo 25). 15. Java Pool Area: utilizada por conexões que contiverem porções de códigos escritos em linguagem Java para interação com o Banco. A visão V$SGA revela diversos aspectos sobre a configuração da SGA: select * from v$sga; NAME VALUE -------------------- ---------Fixed Size 282216 Variable Size 33554432 Database Buffers 8388608 Redo Buffers 532480
As medidas apresentadas estão em bytes. Assim, podemos concluir que são necessários 275 KB como ponto de partida (área fixa); os data block buffers ocupam 8 MB, a área de Redo Log Buffer compreende 520 KB e as demais estruturas (Shared, Large e Java Pool Area) estão distribuídas por uma área de 32 MB.
19.3 - Processos43 Um processo representa um pequeno programa que executa tarefas bastante específicas: integração entre as estruturas de memória e os arquivos em disco, conexão ao Servidor, etc. Existem três tipos de processo detalhados em seguida.
19.3.1 - Processo Usuário Cada vez que ocorre uma conexão, dispara-se um processo usuário executado na estação cliente. Eles têm a função de encaminhar ao Servidor as requisições do Cliente.
19.3.2 - Processo Servidor Recebe as requisições de processos usuários e as encaminha ao Oracle Server. Podem ser dedicados (um para cada cliente) ou não. Neste caso, implementa-se o recurso SS (Shared Server). 19.3.2.1 - SS - Shared Server Normalmente, para cada processo usuário existente, há um processo Servidor dedicado. Isto pode causar ociosidade de processamento, caso haja muito tempo inativo nas conexões. Uma melhoria consiste em empregar a técnica SS (Shared Server, ex-Multithreaded server) que 43
Na plataforma Windows, os processos descritos neste capítulo equivalem aos threads.
Oracle 9i Fundamental
239
permite compartilhar os processos servidores com vários usuários pela utilização de processos especiais chamados dispatchers (roteadores). Além de menos processos servidores, com conseqüente economia de memória, o SS causa o registro de informações de cada usuário em SGA, isto é, alivia-se a PGA. Tecnicamente, SS é um processo do tipo network listener que conecta processos clientes a um ou mais processos roteadores e a um ou mais processos servidores. A tabela seguinte apresenta os principais parâmetros responsáveis pela imple-mentação de SS com os valores típicos e comentários. Parâmetro
Valor Típico
Observações
dispatchers
(PROTOCOL=TCP)
Identifica o número inicial de roteadores que haverá por protocolo de rede e o protocolo a ser obedecido. O SS decidirá quando novos roteadores serão necessários.
max_dispatchers
10
Número máximo de roteadores.
shared_servers
2
Número mínimo servidores.
de
processos
max_shared_servers 10
Número máximo de processos servidores. A variação entre o mínimo e máximo é automá-tica.
service_names
Nome da instância acessada pelo SS.
Acad9
19.3.3 - Processo Background Existem diversos processos cuja principal finalidade consiste em integrar as estruturas de memória aos arquivos em disco. Eles são executados em segundo plano, daí a classificação Background. Existem cinco imprescindíveis ao funcionamento do Banco: DBWR (Database Writer)
Transfere blocos desde o Database Buffer Cache e Dictionary Cache para os Data Files. Quando não houver blocos livres, ele entra em ação, e não necessariamente após um commit.
LGWR (Log Writer)
Descarrega o Redo Buffer Cache no Redo Log File corrente. Executado após um commit ou quando o Redo Buffer Cache estiver cheio.
Responsável pelos processos cliente, organiza a Memória após PMON ope-rações desastradas de usuários. Entre outras tarefas, (Process Monitor) libera tabelas pre-sas e desfaz transações inacabadas. SMON Responsável pela Instância como um todo, entra em ação (System Monitor) durante operações de recuperação do Banco.
Oracle 9i Fundamental
240
CKPT (Checkpoint)
Alivia o trabalho de LGWR, já que grava marcas especiais (System Change Number - SCN) nos Data Files, garantindo que todos estão sincronizados. Após um checkpoint, garantese que todos os blocos sujos foram gravados. O último checkpoint pode ser verificado em V$DATABASE.
Veja como listar o checkpoint corrente e alterá-lo: select name, checkpoint_change# from v$database; NAME CHECKPOINT_CHANGE# --------- -----------------ACAD9 311907
Forçando um checkpoint: alter system checkpoint;
Repetindo a última consulta, teremos: NAME CHECKPOINT_CHANGE# --------- -----------------ACAD9 312161
Observe que a geração de checkpoints constitui tarefa extremamente dinâmica. O processo seguinte, apesar de não ser imprescindível, é bastante recomendável.
ARCH (Archiver)
Copia o conteúdo de Redo Log Files para outro lugar, geralmente em fita. Como a gravação nos Redo Log Files é cíclica, esse processo impede que algum registro de transação se perca; portanto, caso se queira manter um histórico de operações, o ARCH torna-se indispensável.
Ainda podem existir outros processos do tipo background: Útil em operações distribuídas (envolvendo mais de um Banco de Dados), recupera transações inacabadas. Estas operações RECO (Recoverer) somente serão possíveis, caso se instale a extensão Distributed Options. Dnnn (Dispatchers)
Roteadores presentes quando funcionalidade SS (Shared Server).
estiver
configurada
a
CJQ0
Representa o Coordinator Job Queue. Ele gerencia os jobs que foram disparados por meio do package DBMS_JOB (veja item 15.2.1 para obter mais detalhes sobre jobs).
Apesar de não ser propriamente um processo de Background, vale a pena mencionar o Listener. Ele capta tentativas de conexão remota e as informa ao Oracle Server. Geralmente sua ativação é automática, pois caso não esteja disponível, ninguém poderá conectar-se. Diferente dos outros, este Oracle 9i Fundamental
241
processo é ativado de forma independente. No caso do Windows 2000/NT, trata-se de um serviço.
19.4 - Instância À união de estruturas de memória e processos Background dá-se o nome de Instância. Uma vez criada, pode-se iniciar a comunicação: Processo Usuário → Processo Servidor → Instância
Algumas informações podem ser obtidas a partir da visão V$INSTANCE: select instance_name, shutdown_pending, to_char(startup_time, 'dd/mm/yy hh24:mm:ss') tempo from v$instance; INSTANCE_NAME SHU TEMPO ---------------- --- ----------------acad9 NO 21/04/02 07:04:17
A consulta apresentada em seguida informa a quantas horas a instância corrente está aberta: select (SYSDATE-logon_time)*24 "Horas" from sys.v_$session where sid=1 ;
E uma possível resposta: Horas ---------8,91944444
19.4.1 - Parâmetros O funcionamento de uma Instância é determinado por parâmetros que constam nos arquivos INITsid.ORA (texto) ou SPsid.ORA (binário). Alguns parâmetros, ditos dinâmicos, podem ser alterados com o banco aberto. Já outros, os estáticos, não. Esta caracterização pode ser consultada pelo Enterprise Manager Console; uma vez conectado ao Banco, expanda o item Instância e ative Configuração. No painel à direita, clique em Todos os Parâmetros de Inicialização:
Oracle 9i Fundamental
242
Veja uma relação contendo os mais importantes: Valor Típico
Observações
4.096
Representa o tamanho padrão do Bloco, menor uni-dade transportável entre arquivos de dados e memória e vice-versa. Durante a criação de uma Tablespace, caso nenhum tamanho de bloco seja informado, este valor será utilizado.
DB_CACHE_SIZE
8.388.608
Tamanho em bytes do Database Buffer Cache com-posto por blocos de tamanho padrão. O valor típico ao lado informa que 8 MB foram destinados a tal propósito.
DB_xxK_CACHE_SI ZE
valor em bytes ou MB
Antes que Tablespaces com tamanho de bloco dife-rente do padrão possam ser criadas, deve-se reser-var áreas na SGA para outros possíveis tamanhos de bloco. xx pode ser 2, 4, 6, 8, 16 ou 32.
SHARED_POOL_ SIZE
20.971.520
Tamanho em bytes da Shared Pool Area. Vemos aqui um valor igual a 20 MB.
Parâmetro
DB_BLOCK_SIZE
LARGE_POOL_SIZE 1.048.576
Tamanho em bytes da Large Pool Area.
JAVA_POOL_SIZE
Tamanho em bytes da Java Pool Area.
8.388.608
Oracle 9i Fundamental
243
Valor Típico
Observações
SORT_AREA_SIZE
524.288
Área alocada na PGA cada vez que algum usuário requisitar uma ordenação. Caso esta precise mais do que o inicialmente alocado, transfere-se o conteúdo corrente para disco (arquivo pertencente à Tablespace Temporária) e nova alocação em me-mória acontece. Ao final, os blocos ordenados são reunidos e o resultado final enviado ao requerente.
LOG_BUFFER
8192
Tamanho em bytes do Redo Log Buffer.
DB_CREATE_FILE_D EST
algum diretório válido
Local onde serão gravados os arquivos de dados OMF. A conta responsável pelo Oracle deve ter permissões de gravação no destino.
DB_CREATE_ONLI NE_LOG_DESTn
algum diretório válido
Local onde serão gravados os Redo Log Files de dados OMF. Vale a mesma observação anterior.
CONTROL_FILES
nomes de arquivos válidos
Relação de Control Files do Banco. Devem estar localizados em discos diferentes para que o risco de perda seja mínimo.
SGA_MAX_SIZE
Tamanho máximo, em bytes, alocável para a SGA. Perceba que antes que seja possível alocar memória para blocos com tamanho 42.757.736 diferente do padrão, deve-se verificar que o valor de SGA_MAX_SIZE não seja extrapolado. Parâmetro estático.
JOB_QUEUE_ PROCESSES
10
Indica a quantidade de jobs que pode ser disparada simultaneamente. Veja uma utilização dele no Capítulo 15, item 15.2.1
SPFILE
nome de arquivo
Quando a instância tiver sido aberta via arquivo binário de parâmetros (SPFILE.ORA), indica a locali-zação deste arquivo.
IFILE
nome de arquivo
Quando a instância tiver sido aberta via arquivo tex-to de parâmetros (INIT.ORA), indica a localização do arquivo texto contendo mais parâmetros.
Parâmetro
Parâmetros dinâmicos podem ser alterados via comandos alter system ou alter session. A vantagem de abrir uma instância via SPFILE reside na praticidade de não ter que realizar as mesmas alterações nos parâmetros que constem no arquivo texto de parâmetros. Por exemplo, o comando: alter system set open_cursors = 100 scope = both;
altera o parâmetro OPEN_CURSORS e já determina que, na próxima vez que a instância for aberta, ele terá esse valor. A cláusula both indica que a Oracle 9i Fundamental
244
modificação deve ser aplicada imediatamente e também ser gravada no SPFILE. Caso desejás-semos realizar uma alteração temporária, deveríamos fazer: alter system set open_cursors = 80 scope = memory;
Não é raro que existam diversos Arquivos de Parâmetros para um mesmo Banco, porém executa-se um por vez. Pode existir um para o funcionamento diurno, mais adequado para muitas conexões, e outro para a noite, quando prevalecem os trabalhos em lote.
19.4.2 - Etapas Antes que uma instância esteja disponível e um Banco de Dados aberto, devem passar por alguns estágios intermediários:
As três operações, representadas pelas barras verticais, são comentadas em seguida: Nomounting: ativam-se os processos Background e aloca-se memória para a SGA. Após essa operação pode-se criar um Banco de Dados ou consertar Control Files. Mounting: lêem-se os Control Files e determina-se a localização dos demais arquivos. Recuperações e mudança da forma de arquivamento (processo ARCH) acontecem após essa operação. Opening: abrem-se os Data Files e Redo Log Files. Usuários que não sejam DBA podem se conectar. Para realizar estas operações descritas, deve-se utilizar uma variação da SQL*Plus Worksheet. Trata-se da SQL*Plus utilizada no modo linha de comando: C:\>sqlplus /nolog SQL*Plus: Release 9.2.0.1.0 - Production on Dom Ago 4 18:08:55 2002 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. SQL>
Oracle 9i Fundamental
245
Neste momento, carregou-se o programa SQL*Plus em memória, porém sem realizar nenhuma conexão. Recomenda-se esta modalidade quando houver necessidade de fechar ou abrir uma instância manualmente. Para que isto seja possível, deve-se realizar uma conexão utilizando uma conta com privilégios de administração plenos44: SQL> connect sys/ as sysdba Conectado. SQL>
19.4.3 - Fechando: Shutdown Para fechar uma Instância/Banco, emite-se o comando SHUTDOWN cuja forma está representada em seguida: SHUTDOWN [NORMAL | IMMEDIATE | TRANSACTIONAL | ABORT]
As diferenças entre as quatro modalidades estão descritas abaixo: Parâmetro
Observações
Analogia
Normal
Forma pré-assumida, aguarda o término de "Menino, todas as conexões correntes e impede cama". novas.
vá
Transaction Espera que transações correntes sejam "Menino, vá concluí-das e encerra conexões. cama, AGORA!" al Immediate
Abort
Desfaz transações conexões.
correntes
e
pra
pra
encerra Desliga a televisão e agride verbalmente.
Não desfaz transações. Isto acontecerá na próxi-ma inicialização. Encerra conexões. Agride fisicamente Utilizar esta opção apenas em casos extremos.
Uma vez emitido o comando shutdown, não acontecem novas conexões. Os encerramentos "violentos" deixam diversos blocos "perdidos". Eles serão recons-truídos na próxima inicialização, a partir dos Redo Log Files. Vê-se que transações não concluídas têm suas modificações perdidas. Exemplo: SQL> connect sys/ as sysdba Conectado. SQL> shutdown Banco de dados fechado. Banco de dados desmontado. Instância ORACLE desativada. SQL>
44
No capítulo que trata sobre segurança, voltaremos a discutir o tópico "permissões".
Oracle 9i Fundamental
246
Observe que não é possível passar do estado Open para Mount ou Mount para Nomount. Sempre acaba em Shutdown.
19.4.4 - Abrindo: Startup Para abrir uma Instância/Banco, emite-se o comando startup cuja forma está representada em seguida: STARTUP [FORCE] [RESTRICT] [PFILE = arquivo de parâmetros] [OPEN | MOUNT | NOMOUNT] [database]
Os parâmetros estão detalhados em seguida: Force Restrict
Pfile
Open
Mount Nomount Database
Fecha instância corrente (SHUTDOWN ABORT) antes de proceder à nova abertura. Apenas quem possuir privilégio RESTRICTED SESSION pode conectar-se ao Banco. Normalmente, só o DBA o possui. Indica o nome do Arquivo texto de Parâmetros (INIT.ORA). Se for omitido e houver um arquivo em ORACLE_HOME\database (plataforma Windows) ou ORACLE_HOME/dbs (Unix) denominado SPFILEsid.ORA, este será utilizado. Caso se deseje abrir a instância com um arquivo binário de parâmetros e talvez localizado em outro diretório, deve-se utilizar um arquivo texto, utilizado na cláusula PFILE, com apenas um parâmetro, SPFILE. Este parâmetro deve indicar o nome e localização do arquivo binário de parâmetros. O nome do Banco deve coincidir com o parâmetro DB_NAME e o nome que constar nos Control Files. Deixa Instância/Banco abertos. Opção pré-assumida. Especificando esta cláu-sula, pode-se ainda utilizar: READ ONLY (nenhuma alteração será permitida) ou RECOVER (dispara o processo de recuperação. Mais detalhes no Capítulo 25). Estado Mount Estado Nomount Informa-se o nome da variável de ambiente que representa o Banco, caso não tenha sido especificado o nome do Banco no Arquivo de Parâmetros. Geralmente isto não acontece.
Exemplo: SQL> startup Instância ORACLE iniciada. Total System Global Area Fixed Size Variable Size Database Buffers Redo Buffers Banco de dados montado. Banco de dados aberto.
42757736 282216 33554432 8388608 532480
bytes bytes bytes bytes bytes
Oracle 9i Fundamental
247
SQL>
Para mudar do estado Nomount para Mount e Mount para Open, deve-se utilizar o comando ALTER DATABASE cuja sintaxe simplificada é: ALTER DATABASE [OPEN | MOUNT]
Exemplos: SQL> shutdown Banco de dados fechado. Banco de dados desmontado. Instância ORACLE desativada. SQL> startup nomount Instância ORACLE iniciada. Total System Global Area Fixed Size Variable Size Database Buffers Redo Buffers
42757736 282216 33554432 8388608 532480
bytes bytes bytes bytes bytes
SQL> alter database mount; Banco de dados alterado. SQL> alter database open; Banco de dados alterado. SQL>
Vale observar que tanto STARTUP quanto SHUTDOWN são comandos da ferramenta SQL*Plus.
19.5 - Visão Geral
A área quadriculada representa a Database Buffer Cache.
19.6 - O Que Ocorre Durante um SELECT Oracle 9i Fundamental
248
Conhecer o que realmente acontece durante o processamento de um comando select ajuda bastante em caso de ocorrerem problemas. Suponha que tenha sido emitido o seguinte comando: select * from alunos;
Algumas etapas devem ser cumpridas: Requisição
Processo Cliente notifica processo Roteador que mandará um comando SQL. Roteador avisa processo Servidor que virá um comando.
Alocação de Memória
Reserva-se espaço suficiente na Shared SQL Area para que seja possível armazenar o comando SQL e dados relacionados (versão parseada e não parseada, Plano de Execução e ponteiro para a primeira linha).
Parse
Realiza-se a verificação sintática (comando obedece às regras da SQL) e semântica (objetos podem ser manipulados pelo usuário); verifica-se se já não existe comando idêntico na Shared SQL Area; buscam-se informações sobre objetos manipulados e transferidos, ou não, para a Library Cache; determina-se o Plano de Execução (quais índices deverão ser utilizados); armazena-se a versão "compilada" (ou parseada) do comando.
Execução
Aplica-se o Plano de Execução, realizando leituras lógicas (blocos contendo linhas já estão em memória - cache hit) e físicas (blocos contendo linhas não estão em memória - cache miss). Neste último caso, o DBWR entra em ação para trazer os blocos dos Data Files.
Fetch
Cria-se um conjunto de linhas (a partir dos data block buffers) que são retornadas pelo processo Servidor para o processo Cliente requisitante por meio do Roteador.
A razão entre leituras lógicas e físicas recebe a denominação de hit ratio, e quanto mais alta for, melhor o desempenho do Banco. A fórmula que calcula esta razão é: (L - F) / L Note que, para cada leitura física, existirá pelo menos uma lógica, já que o bloco deve ser transferido para a memória e depois lido da memória.
19.7 - O Que Ocorre Durante um UPDATE Suponha agora que seja emitido o comando seguinte: update cursos set preco = preco * 1.1;
Assuma que cada linha da tabela ocupe 80 bytes e que existam dez linhas, portanto apenas um bloco, B, será afetado. Etapas por cumprir:
Oracle 9i Fundamental
249
Requisição
Idem.
Alocação de Memória
Idem.
Parse
Idem.
Leitura
Verifica-se se B já consta no Database Buffer Cache. Caso não esteja, realiza-se uma leitura física.
Reserva
Reserva-se um bloco para o caso de a transação corrente ser desfeita (área de rollback).
Bloqueio
As linhas que serão alteradas sofrem bloqueio. Isto impedirá que outro usuário modifique essas mesmas linhas.
Cópia para Reserva
Realiza-se uma cópia de B para uma área de rollback, que, dependendo da utilização no momento, pode estar em memória ou disco.
Log para valores antigos
Valores prestes a mudar das linhas afetadas são gravados no Redo Log Buffer.
Atualiza
Modificam-se as linhas em B.
Log para valores novos
Novos valores também são gravados no Redo Log Buffer.
Notificação
Processo Servidor informa ao processo Cliente via Roteador que as alterações obtiveram sucesso.
Quando for emitido o comando commit, as linhas afetadas serão liberadas. O bloco contendo os novos valores está sujo e somente será gravado em disco quando ocorrer o próximo checkpoint. Caso seja emitido um rollback, a tabela também é liberada, porém os valores antigos são copiados sobre os novos.
19.8 - Notas sobre o Oracle sob Windows 2000 Um dos grandes objetivos da Oracle, desde que lançou o Oracle Server, foi a portabilidade. Hoje existem versões do carro-chefe da empresa em inúmeros Sistemas Operacionais: desde o pioneiro VMS, passando por quase todas as variações UNIX, até o emergente Windows 2000 Server. Os conceitos vistos até aqui aplicam-se a todas as plataformas, entretanto sempre há detalhes específicos para cada uma. Neste tópico, serão comentadas as peculiari-dades do Windows 2000. O Oracle Server é executado ocupando um processo e os processos propriamente ditos são implementados via threads. Isto permite implementar a SGA em uma área de memória privativa ao processo do Oracle Server, isto é, ao contrário de implementações UNIX, a SGA não é exatamente compartilhada por vários processos, mas por threads.
Oracle 9i Fundamental
250
Cada Banco de Dados criado será representado por um serviço. Na figura seguinte, vemos que OracleServiceACAD9 representa o Banco utilizado neste livro:
Observe também a presença de OracleOraHome92TNSListener captando tentativas de conexão em máquinas clientes. Este último serviço substitui o processo Listener das plataformas UNIX. Um cuidado importante a ser tomado sob Windows2000 consiste na escolha da conta responsável pelo serviço do Banco. Ela deve ter permissão de gravação nos diretórios em que residem os arquivos do Banco e, quiçá, em outras máquinas, caso decida-se copiar Archived Redo Log Files pela rede. Caso deseje-se simplesmente abir o Banco, note que, a rigor, não é necessário emitir o comando STARTUP pelo SQL*Plus, já que a disponibilização é realizada automaticamente. Alguns fatos interessantes acontecem: • Emitir o comando STARTUP com os serviços desligados resulta inútil; • Emitindo SHUTDOWN, não interrompe a execução dos serviços. Ao desligar o Servidor Windows 2000, os serviços são automaticamente fechados. Infelizmente, desligá-los equivale a emitir um comando shutdown immediate. Finalmente, convém lembrar onde são gravadas as localizações de ORACLE_HOME e ORACLE_BASE. Execute o utilitário regedit e localize a chave HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0. Interessante observar que, a partir da versão 8.0.4, permite-se a criação de vários ORACLE_HOMES.
Oracle 9i Fundamental
251
EXERCÍCIOS Antes de começar, verifique se você possui uma conta com privilégios de DBA. Caso não a possua, utilize a SYSTEM cuja senha definida na instalação normalmente é MANAGER. Para abrir ou fechar uma instância, você deve conhecer a senha de um usuário caracterizável como SYSDBA. Logo após a instalação, esse usuário chama-se SYS e sua senha normalmente é CHANGE_ON_INSTALL. Cuidado Evite fazer os exercícios seguintes em um Banco de Dados de produção. O ideal seria ter um Servidor de testes exclusivamente destinado a tarefas como as que seguem. Somente quando você adquirir confiança suficiente, utilize um Banco que não seja de testes.
1. Conecte-se ao SQL*Plus Worksheet e pesquise estrutura e conteúdo das seguintes visões: • • • • •
V$CONTROLFILE V$DATABASE V$DATAFILE V$DBFILE V$INSTANCE
• • • • •
V$LOGFILE V$LOG V$PARAMETER V$SGA V$SGASTAT
2. Conecte-se ao Enterprise Manager Console. Responda: a) Qual é o tempo máximo de blocos sujos em memória? • Em outras palavras, qual seria o intervalo máximo de tempo sem que ocorra um checkpoint. Expanda Instância e depois Configuração; Pressione em Todos os Parâmetros de Inicialização e procure algum parâmetro que tenha log e timeout em seu nome. Será que ele é dinâmico? b) Qual é o tamanho total do Database Buffer Cache? Inclua blocos de todos os tamanhos possíveis. c) Quantos bytes estão destinados em memória às operações de ordenação? d) O modo Archiving está ligado? 3. Localize em seu Servidor os diretórios ORACLE_BASE e ORACLE_HOME. Encontre também os Data Files, Redo Log Files, Control Files, Arquivos de Parâmetros (existe o binário?), Arquivos de Alertas (existe algum trace?). Tente achar também o arquivo de senhas (Password File). Será que você conseguiria editá-lo? 4. Analise o arquivo INIT.ORA fornecido. Oracle 9i Fundamental
252
Responda: a) Qual é o nome da Instância? b) Quantos arquivos de controle existem? Onde estão? c) Quantos tamanhos de bloco existem? d) Utilizou-se a facilidade OMF (Oracle Managed File)? e) Qual é o tamanho das áreas destinadas a programas Java e para o SS? Por que ainda não podemos utilizar esse arquivo? 5. Encontre o arquivo de parâmetros da instância corrente. • O que significa parâmetro IFILE? 6. Conheça um pouco mais de seu Banco de Dados investigando a visão database_properties. Ela possui apenas três colunas e uma vintena de linhas. 7. Neste exercício você será guiado na criação de um trigger especial que será disparado no momento imediatamente seguinte à abertura da instância. Acompanhe o seguinte roteiro: a) Conectado como algum usuário que tenha privilégios de SYSDBA, crie a tabela: create table registros (quem varchar2(20), banco varchar2(30), instancia number, quando date default sysdate);
b) Crie o trigger a ser disparado após a abertura da instância. Aqui se supõe que o dono da tabela e do trigger será MORELLI: CREATE OR REPLACE TRIGGER t_Abertura AFTER STARTUP ON DATABASE BEGIN insert into morelli.registros (quem, banco, instancia) values (ora_login_user, ora_database_name, ora_instance_num); END;
c) Feche o banco; d) Abra o Banco; e) Consulte o conteúdo da tabela de registros. Os próximos dois exercícios assumem que o arquivo de parâmetros corrente é o binário. 8. Acrescente outro Control File. Acompanhe o seguinte roteiro: Oracle 9i Fundamental
253
a) Crie um arquivo de parâmetros do tipo texto; b) Feche Banco/Instância; c) Edite o arquivo de parâmetros texto contendo o parâmetro control_files para que conste mais um arquivo, de preferência, em outro disco; d) Copie fisicamente o arquivo de controle existente para um novo arquivo e dê-lhe o nome que consta no Arquivo de Parâmetros recém editado; e) Abra o Banco utilizando o arquivo de parâmetros texto Comprove a presença do novo Control File, investigando V$CONTROLFILE. 9. Elimine um Control File antigo. Acompanhe o seguinte roteiro: a) Feche Banco/Instância; b) Edite o arquivo de parâmetros texto contendo o parâmetro control_files para que não conste referência ao arquivo por eliminar; c) Abra o Banco utilizando o arquivo de parâmetros texto; d) Elimine fisicamente o arquivo excluído. Comprove a alteração, investigando V$CONTROLFILE. Como seria para mover um Control File? e) Atualize o arquivo de parâmetros binário; 10. Conecte-se ao Enterprise Manager Console como usuário com prerrogativas de SYSDBA. Feche o Banco. Comprove o sucesso da operação, depois volte a abri-lo. Note que será utilizado o arquivo de parâmetros binário recém atualizado. 11.
Repita o último exercício pelo SQL*Plus. • Aproveite para conhecer a visão V$DATABASE.
12. Mova um Redo Log File. Acompanhe o seguinte roteiro: a) Feche Banco/Instância; b) Movimente o arquivo fisicamente; c) Abra o Banco em estado mount; d) Emita o comando alter database rename file ... to ... Nomes de arquivos devem aparecer entre aspas simples. e) Abra o Banco.
Oracle 9i Fundamental
254
13.
Mova um Data File. • O roteiro é idêntico ao do exercício 12.
14.
Veja a quantas anda a razão entre leituras lógicas e físicas. • Analise e depois execute os scripts dos arquivos: 19_HitRatioPorArquivo e 19_HitRatioPorUsuario.
Oracle 9i Fundamental
255
REFERÊNCIA RÁPIDA Tarefa Listar Data Files
Como fazer Visões V$DATAFILE ou V$DBFILE. Esta informação está disponível no Enterprise Manager Console.
Listar Control Files
Visão V$CONTROLFILE CONTROL_FILES.
Listar Files
Visão V$LOGLFILE ou V$LOG.
Redo
Control
ou
parâmetro
Utilize comando: alter database add logfile group N ('nome_arquivo') size inteiro M;
Criar Redo
Eliminar Redo
Listar parâmetros
Criar SPFILE
O nome do arquivo pode ser omitido caso se tenha utilizado a facilidade OMF, ou seja, exista conteúdo no parâmetro: db_create_online_log_dest_n (em que n varia de 1 a 5). O tamanho default é 100 MB. Utilize o comando: alter database drop logfile group 1;
Caso não se tenha utilizado a facilidade OMF, o arquivo físico será excluído. Visão V$PARAMETER ou comando show parameters. Esta informação está disponível no Enterprise Manager Console. Utilize o comando: create spfile = 'nome_arquivo' from pfile = 'nome_arquivo'
Gravações no arquivo binário de parâmetros somente valerão na próxima abertura da instância. Utilize o comando: Criar PFILE Alterar parâmetro Verificar ocupação de memória Obter informações sobre instância corrente
Abrir instância
create pfile = 'nome_arquivo' from spfile = 'nome_arquivo'
ALTER SYSTEM SET =valor SCOPE = escopo. Onde escopo seria MEMORY ou SPFILE ou BOTH. Visões V$SGA ou V$SGASTAT. Esta informação está disponível no Instance Manager. Visão V$INSTANCE. Esta informação está disponível no Enterprise Manager Console. Pelo SQL*Plus, comando: startup nomount. A rigor, também é possível utilizar o SQL*Plus Worksheet, porém, caso a instância esteja fechada, não será possível realizar uma conexão. Neste caso, devemos fazer: sqlplus /nolog
Oracle 9i Fundamental
256
Tarefa Abrir parcialmente o Banco Abrir Banco Fechar Banco/Instância Verificar estado de servi-ços responsáveis pelo funcionamento do Banco
Como fazer Pelo SQL*Plus modo linha, comando: alter database mount. Pelo SQL*Plus modo linha, comando: alter database open; ou caso esteja fechado: startup. Pelo SQL*Plus modo linha, comando: shutdown.
Start, Administrative Tools, Services.
Oracle 9i Fundamental
257
Capítulo 20 – ORGANIZAÇÃO LÓGICA: TABLESPACES OBJETIVOS • • • • •
Definir Tablespace como uma entidade lógica; Diferenciar os três tipos de Tablespace disponíveis: permanente, temporária e undo; Compreender a necessidade de criar várias Tablespaces e com características próprias; Criar, alterar ou eliminar Tablespaces tanto pelo SQL*Plus Worksheet, como pelo Enterprise Manager Console; Ajustar parâmetros de armazenamento para que a utilização de uma Tablespace seja ótima.
NOVIDADES •
•
Como será detalhado no próximo capítulo, agora é possível automatizar todo o tratamento de Segmentos de Rollback. Uma das conseqüências deste fato é a presença de um terceiro tipo de Tablespace: Undo; Em vez de especificar a Tablespace temporária toda vez que se cria um usuário, agora pode-se caracterizar uma dada Tablespace como default temporary. Daí em diante, todo usuário criado vai tê-la como área temporária padrão.
ARQUIVOS NECESSÁRIOS • • •
20_Ex_Cria_Tablespaces.sql; 20_Ex_Altera_Tablespaces.sql; 20_Espaco_disponivel.sql.
PRÉ-REQUISITOS • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Conhecer principais objetos Oracle: tabela, índice, constraint, visão e seqüência; Identificar as Tablespaces de um Banco. Oracle 9i Fundamental
258
TEORIA 20.1 - Fundamentos Como já mencionado, uma Tablespace representa uma entidade lógica capaz de reunir dados (de controle, temporários ou dados propriamente ditos) que guardem semelhanças entre si. O diagrama apresentado em seguida contextualiza as Tablespaces em um Banco:
Diagrama simplificado demonstrando a relação entre entidades.
Observações A figura revela que um Banco de Dados constitui um grupo de Tablespaces que, por sua vez, são compostas por Data Files, cuja estrutura mostra um conjunto de blocos (menor unidade manipulável pelo Oracle); • Por outro lado, um Banco de Dados também constitui um grupo de Usuários. Cada Usuário pode possuir um Schema que, por sua vez, é composto por Segmentos (tabelas, índices, etc. Veja capítulos 21-23.). Finalmente, um Segmento é composto por Extents que, por sua vez, são conjuntos de blocos; • Os elementos anteriores não podem "espalhar-se" por outros, isto é, um bloco não pertence a mais de um Extent ou Data File; um Data File não pertence a mais de uma Tablespace; etc.; • Uma curiosidade: supondo que o tamanho do bloco seja 2.048, um arquivo de 10M teria 4.999 blocos, já que o primeiro é reservado. O primeiro bloco de cada Segmento também é guardado para controle. Além do mais, perdem--se, em média, 80 bytes por bloco com informações internas. O Banco de Dados nativo do Windows 2000 já vem com várias Tablespaces, das quais destacam-se: Users, Undotbs, Temp e System. Esta última é a mais importante, pois nela residem os objetos do Dicionário de Dados. •
Oracle 9i Fundamental
259
Recomenda-se deixá-la com 50 e 70% de espaço livre e gravar objetos de usuários em outras Tablespaces.
20.2 - OFA (Optimal Flexible Architecture) OFA representa um conjunto de diretrizes que visa facilitar a manutenção de um banco de dados. Não se trata de um grupo de regras mandatórias, mas conselhos. Um banco de dados deve ter uma configuração lógica (distribuição de Tablespaces) e outra física (discos). Segundo o renomado autor Kevin Loney, a organização lógica compreende: • System • Data (tabelas) • Index (índices) • Tools (tabelas criadas por ferramentas: Delphi, por exemplo) • Undotbs (segmentos de rollback) • Temp (área destinada a objetos temporários) • Users (objetos criados por usuários)
A distribuição de discos deve seguir um processo de refinamento que ajuste um desempenho ótimo à disponibilidade de discos. O mesmo Kevin Loney parte de uma configuração "ideal" em que constariam 22 discos. Obviamente, isto não é razoável. Após vários refinamentos chega à seguinte configuração: Disco
Conteúdo
1
Oracle
2
System, Primeiro Arquivo de Controle (Control File)
3
Undotbs, Temp, Tools, Segundo Arquivo de Controle
4
Data, Terceiro Arquivo de Controle
5
Index
6
Redo Log Files, Arquivos de exportação
7
Aplicação, Archived Redo Logs, Users
Observe que: • Tablespaces com características de ocupação semelhantes estão no mesmo disco. Arquivos temporários têm grande tendência à fragmentação, enquanto arquivos de dados não.
Oracle 9i Fundamental
260
Tablespaces cujos arquivos são gravados simultaneamente estão em discos diferentes. Isto ocorre com Dados x Índices; Arquivos de Controle; Redo Log Files x Archived Redo Logs. • Os três processos que acessam disco constantemente são: DBWR (aleatoriamente), LGWR e ARCH (seqüencialmente). Observe que eles atuam em discos diferentes, o que minimiza as disputas por tempo de gravação (contenção). • Os arquivos de uma mesma Tablespace devem ser posicionados no mesmo disco. • Os Redo Log Files poderiam estar cada um em um disco diferente. Isto evita-ria o conflito entre LGWR (gravação) e ARCH (leitura). • Campos do tipo LOB (CLOB, BLOB, NCLOB, NBLOB) podem ser gravados em Tablespaces próprias. É possível até gravar índices de LOBs também em separado. Para que a contenção seja mínima, além de os discos serem diferentes, as contro-ladoras também devem ser. •
20.3 - Criação O comando create tablespace, cuja sintaxe simplificada aparece em seguida, permite criar Tablespaces. CREATE [UNDO] TABLESPACE nome DATAFILE caminho_completo_1 SIZE inteiro [K | M] [REUSE] [AUTOEXTEND OFF | ON NEXT inteiro [K | M] MAXSIZE inteiro [K | M] | UNLIMITED] [DATAFILE caminho_completo_2 ...] [BLOCKSIZE inteiro] [LOGGING | NOLOGGING] [DEFAULT STORAGE INITIAL inteiro [K | M] NEXT inteiro [K | M] MINEXTENTS inteiro MAXEXTENTS inteiro PCTINCREASE inteiro entre 0 e 100] [ONLINE | OFFLINE] [EXTENT MANAGEMENT DICTIONNARY | LOCAL] [PERMANENT | TEMPORARY]
As palavras-chave e os parâmetros estão detalhados em seguida:
Oracle 9i Fundamental
261
Cláusula
UNDO
nome
DATAFILE
AUTOEXTEND
BLOCKSIZE
LOGGING
DEFAULT STORAGE
Descrição
Caracteriza a Tablespace sendo criada como do tipo Undo. Como será visto no capítulo 21, caso a gerência de segmentos de rollback seja automatizada, a presença de pelo menos uma Tablespace deste tipo resulta obrigatória. Apenas duas cláusulas podem ser utilizadas na criação desse tipo de Tablespace: datafile e extent management. As demais, ou serão ignoradas, ou recusadas. Nome da Tablespace Indica um ou mais arquivos que constituirão a Tablespace. Será obrigatória caso não estejam sendo utilizados arquivos OMF (veja exemplo em seguida). Devem-se especificar, além do caminho completo, o tamanho (em KB ou MB) e a possibilidade de reaproveitar um arquivo existente (reuse). Raramente uma Tablespace ocupará menos de 1 MB. Os nomes devem ser especificados entre aspas simples. Recomenda-se que somente seja acrescentado um segundo arquivo, quando o primeiro atingir o tamanho máximo permitido pelo SO. Cuidado: o Oracle aloca mais espaço do que o especificado, portanto, antes de acrescentar um arquivo, verifique se existe espaço disponível no disco suficiente para uma vez e meia o tamanho dele. Um arquivo pode ser automaticamente expandido por um valor fixo até um limite ou indefinidamente. Esta cláusula não é recomendada. Determina o tamanho do bloco (diferente do padrão) a ser utilizado pelos segmentos a serem criados. Observe que o parâmetro DB_xxK_CACHE_SIZE correspondente deve ter sido especificado. Os valores possíveis são 2K, 4K, 8K, 16K e 32K. Informa-se a criação dos segmentos na Tablespace, que serão registrados no Redo Log por default. A opção NOLOGGING realiza o contrário. Ainda que o não-registro proporcione mais velocidade, deve-se preferir sempre o registro em log. Parâmetros de Armazenamento padrão utilizados quando a gerência de Extents for baseada no Dicionário de Dados (cláusula EXTENT MANAGEMENT igual a DICTIONARY): INITIAL: tamanho do primeiro Extent alocado (em bytes). Default: cinco vezes o tamanho do bloco. NEXT: quantos bytes serão alocados no momento da expansão. Não há garantias de que serão contíguos aos primeiros. Default: cinco vezes o tamanho do bloco. MINEXTENTS: quantos Extents deverão ser alocados na criação de um Segmento. Default: 1.
Oracle 9i Fundamental
262
Cláusula
ONLINE
PERMANENT
EXTENT MANAGEMENT
Descrição
MAXEXTENTS: quantidade máxima de Extents alocados por Segmento. Recomenda-se que não passe de 10. O valor default será determinado pelo tamanho do bloco. PCTINCREASE: porcentagem de crescimento aplicada na expansão. Caso seja zero, o SMON não fará compactações que aumentam áreas livres contíguas, por isto, em vez de deixá-lo como zero, recomenda-se atribuir um valor pequeno (1, por exemplo). Default: 50. Determina se a Tablespace estará disponível imediatamente após a criação ou não (OFFLINE). Caracteriza a natureza dos dados que constarão nos arquivos da Tablespace: ou permanentes ou temporários (neste caso, serão dados transitórios, resultados de agrupamentos ou ordenações). Desde a versão 8i existe uma alternativa à gerência de Extents com os parâmetros descritos na cláusula DEFAULT STORAGE. Trata-se da gerência local à Tablespace, ou seja, durante operações de alocação de dados há menos acessos ao Dicionário de Dados em busca de espaços livres. A cláusula EXTENT MANAGEMENT aceita dois valores: DICTIONARY ou LOCAL. O primeiro será default caso o parâmetro COMPATIBLE seja menor que 9.0.0; caso contrário, valerá o segundo. Ao especificar LOCAL, ainda deve-se determinar uma das duas modalidades: AUTOALLOCATE ou UNIFORM. No primeiro caso deixa-se a cargo do Oracle a alocação de Extents, que poderão ser de tamanhos variáveis. Já no segundo, todos os Extents terão obrigatoriamente o mesmo tamanho.
Observações • •
•
Os parâmetros de armazenamento serão utilizados no momento da criação de Segmentos. Cuidado: para Tablespaces temporárias com gerência de Extents baseada no Dicionário, um valor grande de INITIAL pode levar ao erro ORA-1652 (tentativa frustrada de alocação de espaço). Isto aconteceria caso muitos usuários requeressem espaços temporários simultaneamente. Ao criar um usuário45, podem-se especificar Tablespaces de dados e temporárias defaults. Isto é altamente recomendável, pois ajuda bastante quando for necessário exportar uma Tablespace para eliminar fragmentação ou exportar objetos. Por exemplo: create user novo identified by senha
45
Mais detalhes sobre criação de usuários no capítulo 24.
Oracle 9i Fundamental
263
default tablespace USERS temporary tablespace TEMP;
Uma importante novidade introduzida pela versão 9i consiste na Default Temporary Tablespace. Uma vez especificada, todo usuário que venha a ser criado vai tê-la como default para áreas temporárias. Isto evita o clássico erro de atribuir uma Tablespace permanente como sendo a temporária default de um usuário. Utilizar uma Tablespace permanente como sendo a temporária default traz alguns problemas de performance. Isto porque segmentos temporários criados em Tablespaces permanentes são imediatamente destruídos após utilização, o que não acontece em Tablespaces temporárias. Para caracterizar uma Tablespace temporária como a Default Temporary Tablespace, utilizamos o comando alter database: •
alter database default temporary tablespace temp;
Para descobrir a Default Temporary Tablespace vigente, fazemos: select property_value from database_properties where property_name = 'DEFAULT_TEMP_TABLESPACE';
•
Para criar uma Tablespace Temporária com gerência de Extents local, deve-se utilizar o comando create temporary tablespace (veja exemplo em seguida). Os arquivos criados por este comando não aparecem ao listar V$DBFILE e sim V$TEMPFILE. Voltaremos a este assunto no capítulo 25.
•
Existe uma tendência natural em passar a criar novas Tablespaces utilizando a gerência de Extents Local, já que esta forma alivia o fardo de acompanhar a alocação de espaço, além de ser mais eficiente. Caso se insista na gerência de Extents do tipo Dicionário, tipicamente, existirá uma Tablespace contendo todas as tabelas de dados do Banco. Normalmente, existem poucas grandes e muitas pequenas, portanto, ao criar esta Tablespace, recomendase utilizar valores pequenos para os Parâmetros de Armazenamento (Default Storage) e deixar para cada tabela (segmento) grande os valores específicos. Os valores dos Parâmetros de Armazenamento (INITIAL, NEXT, etc.) devem ser obtidos após análise dos scripts de criação das tabelas. A partir dos tamanhos de cada registro e previsão de volume de dados, pode-se especificar o tamanho máximo que uma tabela com seus índices alcançará. Recomenda-se superestimar esses valores. Outro conselho: que os discos que
•
•
Oracle 9i Fundamental
264
conterão Tablespaces com dados tenham entre 20 e 25% de espaço livre. O exemplo seguinte mostra a evolução do tamanho de uma tabela criada com INITIAL = 100K, NEXT 50K e PCTINCREASE 100.
INITIAL (em blocos) NEXT (em blocos) PCT BLOCO
em bytes 102,400 51,200
50 25 100% 2
Extents
2048 em KB expande
tamanho 1 2 3 4 5 6
100 100 150 250 450 850
0 50 100 200 400 800
novo
em blocos
100 150 250 450 850 1,650
50 75 125 225 425 825
Note que não importa o valor de MINEXTENTS. A tabela anterior aplica-se no momento da expansão. Altos valores de PCTINCREASE podem levar a um crescimento descontrolado de uma tabela. Sugere-se criá-la com INITIAL realista, NEXT pequeno e PCTINCREASE igual a um (devido à ação de compactação do SMON).
Primeiro exemplo46: Tablespace com um arquivo CREATE TABLESPACE TABELAS DATAFILE 'E:\ORACLE\ORADATA\ACAD9\ACADTAB.ORA' SIZE 10 M AUTOEXTEND ON NEXT 1 M MAXSIZE 20 M DEFAULT STORAGE (INITIAL 200 K NEXT 200 K MINEXTENTS 2 MAXEXTENTS 10 PCTINCREASE 100) EXTENT MANAGEMENT DICTIONARY;
Observações O diretório destino já deve existir. Para comprovar a criação: select tablespace_name from dba_tablespaces where tablespace_name = 'TABELAS'; TABLESPACE_NAME -----------------------------46
Os exemplos seguintes 20_Ex_Cria_Tablespaces.sql.
constam
no
Oracle 9i Fundamental
arquivo
exemplo
265
TABELAS
E para comprovar o espaço ocupado: select * from dba_free_space where tablespace_name = 'TABELAS'; TABLESPACE_NAME FILE_ID BLOCK_ID BYTES --------------TABELAS
-------- --------9
--------
-------
17
BLOCKS RELATIVE_FNO ------------
10420224
2544
9
Em Tablespaces com gerência de Extents do tipo Dicionário, à medida que Segmentos com seus Extents vão sendo criados e apagados, a tendência é que surjam várias "ilhas" de blocos disponíveis. Quanto mais "ilhas", maior a fragmen-tação e pior a performance.
Segundo exemplo: Undo CREATE UNDO TABLESPACE UNDOTBS2 DATAFILE 'E:\ORACLE\ORADATA\ACAD9\UNDOTBS02.ORA' SIZE 10 M EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
Observações Como se escolheu a gerência de Extents Local, a cláusula default storage não faria sentido. Mesmo na gerência de Extents Local, somente se aceita a forma autoallocate. Obriga-se a utilização da cláusula datafile, mesmo que a facilidade OMF esteja ativa (parâmetro db_create_file_dest com algum diretório válido).
Terceiro exemplo: Temporária CREATE TEMPORARY TABLESPACE TEMP2 TEMPFILE 'E:\ORACLE\ORADATA\ACAD9\TEMP2.ORA' SIZE 10 M EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
Observações •
•
•
O arquivo criado não aparece ao listar V$DBFILE. Ele surge em V$TEMPFILE. Isto não aconteceria caso a Tablespace tivesse sido criada com o comando create tablespace ... temporary, entretanto não poderíamos especifi-car a gerência de Extents Local. Note que a gerência de Extents Local cai como uma luva para o compor-tamento altamente fragmentável das Tablespaces temporárias. O tamanho do bloco deve ser obrigatoriamente igual ao padrão.
Oracle 9i Fundamental
266
Quarto Exemplo: OMF com Uniform Size CREATE TABLESPACE TABELAS2 EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1 M;
Observações •
Para que o comando anterior obtenha pleno êxito, deve-se garantir que o parâmetro db_create_file_dest possua algum diretório válido. Caso não possua, pode-se atribuir-lhe um valor:
alter system set db_create_file_dest = 'E:\ORACLE\ORADATA\ACAD9';
•
O nome do arquivo foi gerado pelo Oracle e seu tamanho será de 100 MB.
20.4 - Alteração O comando alter tablespace, detalhado em seguida, permite alterar Tablespaces. ALTER TABLESPACE nome [LOGGING | NOLOGGING] ADD DATAFILE caminho_completo_1 SIZE inteiro [K | M] [REUSE] [AUTOEXTEND OFF | ON NEXT inteiro [K | M] MAXSIZE inteiro [K | M] | UNLIMITED] DATAFILE caminho_completo_2 ... RENAME DATAFILE arquivo1 TO arquivo2 COALESCE DEFAULT STORAGE NEXT inteiro [K | M] MAXEXTENTS inteiro PCTINCREASE inteiro entre 0 e 100 ONLINE | OFFLINE [NORMAL | TEMPORARY | IMMEDIATE | FOR RECOVER] BEGIN BACKUP END BACKUP READ ONLY | READ WRITE PERMANENT | TEMPORARY
As palavras-chave e os parâmetros estão detalhados em seguida: Cláusula
Descrição
nome
Nome da Tablespace.
LOGGING
idem CREATE TABLESPACE.
ADD DATAFILE
Arquivos a serem acrescentados. Caso se decida por arquivos que cresçam automaticamente, deve-se utilizar a cláusula AUTOEXTEND para cada arquivo.
RENAME DATAFILE
Arquivos a serem renomeados. A Tablespace deve estar em modo offline e o arquivo destino já deve existir.
COALESCE
Compacta espaço nos arquivos. Deve ser especificada sozinha. Perde sentido quando a gerência de Extents for Local. Oracle 9i Fundamental
267
Cláusula
Descrição
DEFAULT STORAGE
Parâmetros de Armazenamento assumidos quando não constarem na criação de segmentos. Os novos valores são utilizados para criações posteriores à emissão do comando ALTER TABLESPACE. Esta cláusula somente será levada em conta se a gerência de Extents for do tipo Dicionário.
ONLINE
Determina se a Tablespace estará disponível imediatamente após a criação ou não (OFFLINE).
OFFLINE
Indisponibiliza a Tablespace. Isto pode ser feito, garantindo que os arquivos estão disponíveis para uso (NORMAL) ou não. Neste caso, podem-se aplicar checkpoints nos arquivos (TEMPORARY) ou não (IMMEDIATE), em que explicitamente "desligam-se" os arquivos que estejam danificados.
BEGIN BACKUP
Indica que a Tablespace está entrando ou saindo (END BACKUP) do estado de cópia (Veja capítulo 25).
READ ONLY
Bloqueia ou não (READ WRITE) alterações aos dados da Tablespace.
PERMANENT
Natureza dos (TEMPORARY)
dados:
permanentes
ou
temporários.
Observações • •
Arquivos podem ser incluídos com o Banco aberto e a Tablespace disponível. Arquivos podem ser desconectados ou alterados via comando alter database, como visto no exemplo em seguida.
Primeiro exemplo47: Tablespace com um arquivo ALTER TABLESPACE TABELAS ADD DATAFILE 'E:\ORACLE\ORADATA\ACAD9\ACADTAB2.ORA' SIZE 10 M AUTOEXTEND ON NEXT 1 M MAXSIZE 20 M;
Observações O diretório destino já deve existir. Para comprovar o espaço ocupado: select * from dba_free_space where tablespace_name = 'TABELAS'; TABLESPACE_NAME FILE_ID --------------- -------TABELAS 13 TABELAS 9
47
BLOCK_ID -------17 17
Os exemplos seguintes 20_Ex_Altera_Tablespaces.sql.
BYTES -----10420224 10420224
BLOCKS --------2544 2544
constam
no
Oracle 9i Fundamental
RELATIVE_FNO -----------13 9
arquivo
exemplo
268
Segundo exemplo: Mudando algum parâmetro de armazenamento ALTER TABLESPACE TABELAS DEFAULT STORAGE (MAXEXTENTS 20
PCTINCREASE 50);
Observações Perceba que o comando anterior teve sucesso, pois o modo de gerenciamento de Extents da Tablespace é do tipo Dicionário. Comprovando a mudança: select tablespace_name, max_extents, pct_increase from dba_tablespaces where tablespace_name = 'TABELAS'; TABLESPACE_NAME MAX_EXTENTS PCT_INCREASE ----------------------------- ----------- -----------TABELAS 20 50
Terceiro exemplo: reduzindo o tamanho de um arquivo ALTER DATABASE DATAFILE 'E:\ORACLE\ORADATA\ACAD9\ACADTAB.ORA' RESIZE 5 M;
Observações • •
O comando anterior somente terá sucesso caso nenhum bloco com dados seja afetado. A cláusula RESIZE também pode ser utilizada para aumentar o tamanho de um arquivo.
20.5 - Eliminação O comando drop tablespace, detalhado em seguida, permite eliminar Tablespaces. DROP TABLESPACE nome [INCLUDING CONTENTS [AND DATAFILES] [ CASCADE CONSTRAINTS]]
As palavras-chave e os parâmetros estão detalhados em seguida: Cláusula
Descrição
nome
Nome da Tablespace.
INCLUDING CONTENTS
Realiza a exclusão mesmo se houver algum Segmento; entretanto, a ope-ração fracassará, caso existam Segmentos de Rollback ou Temporários ativos.
AND DATAFILES
Utilizada em conjunto com a anterior, força a eliminação física dos arquivos que compõem a Tablespace. Desnecessária para arquivos OMF. Oracle 9i Fundamental
269
Cláusula
Descrição
CASCADE CONSTRAINTS
Elimina constraints relacionados a tabelas na Tablespace corrente que estejam em outra Tablespace. Também vale o senão anterior.
Exemplo DROP TABLESPACE TABELAS INCLUDING CONTENTS AND DATAFILES;
Note que os arquivos físicos NÃO precisam ser eliminados via Sistema Operacional.
20.6 - Enterprise Manager Console Pelo EMC torna-se bastante simples gerenciar o estado das Tablespaces de um Banco:
Para criar uma nova Tablespace, clica-se com o botão direito em Tablespaces e seleciona-se Criar:
Oracle 9i Fundamental
270
EXERCÍCIOS 1. Crie uma Tablespace temporária com dois arquivos auto-expansíveis, tendo cada um o tamanho de 500 KB. O próximo tamanho dos arquivos será de 1 MB e o tamanho máximo de 10 MB. O tamanho inicial dos Extents será de 100 KB, os seguintes de 200 KB e crescimento exponencial de 50%. • Elabore um script para criá-la. • Qual será o modo de gerenciamento de Extents utilizado? Será o mais ade-quado? • Verifique o sucesso da operação, comprovando a criação dos arquivos e listando DBA_TABLESPACES. • Outra forma seria pelo Enterprise Manager Console. 2. Mova um dos arquivos para outro diretório. • Acompanhe o seguinte roteiro: a) Indisponibilize a Tablespace. Na claúsula OFFLINE, utilize a opção IMMEDIATE; b) Mova o arquivo fisicamente para a nova localização; c) Emita o comando ALTER TABLESPACE ... RENAME; d) Habilite a Tablespace. • Como será visto mais tarde, o ideal seria, antes de realizar uma operação como esta, fazer um backup completo do Banco. 3. Acrescente outro arquivo com 20 M à Tablespace criada. 4. Altere o tamanho do arquivo recém-criado para 10 M. Oracle 9i Fundamental
271
• •
Utilize o comando ALTER DATABASE. Experimente reduzir o tamanho de um arquivo com dados. Analise a mensagem produzida.
5. Tente eliminar um arquivo da Tablespace criada. • Como resolver este "problema"? 6. Elimine a Tablespace recém-criada sem que seja necessário apagar fisicamente os arquivos. 7. Abra o script 20_espaco_disponivel.sql. Analise-o cuidadosamente, depois execute-o. • O que pode ser concluído quanto ao espaço disponível das Tablespaces? 8. Reflita: qual seria a real importância dos Parâmetros Armazenamento se eles são sobrescritos na criação de Segmentos?
de
9. Investigue as visões V$SORT_SEGMENT e V$SORT_USAGE. Quais informações úteis elas podem proporcionar? 10. Descubra a gerência de Extents utilizada para as Tablespaces de seu Banco. • Investigue as colunas EXTENT_MANAGEMENT e ALLOCATION_TYPE de DBA_TABLESPACES.
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Criar uma Tablespace
Comando CREATE TABLESPACE Para criar uma Tablespace Temporária com gerenciamento Local, utilize o comando CREATE TEMPORARY TABLESPACE. Esta funcionalidade, assim como alterar e excluir, está disponível no Enterprise Manager Console.
Alterar uma Tablespace
Comando ALTER TABLESPACE.
Eliminar uma Tablespace
Comando DROP TABLESPACE.
Verificar a possibilidade de criar uma Tablespace com arquivos OMF
Verifique o conteúdo do parâmetro: DB_CREATE_FILE_DEST.
Oracle 9i Fundamental
272
Tarefa
Listar Tablespaces ou informações afins
Como fazer Visões: DBA_EXTENTS, USER_EXTENTS DBA_SEGMENTS, USER_SEGMENTS DBA_DATA_FILES DBA_TABLESPACES USER_TABLESPACES
Mostrar informações sobre espaço livre em Tablespaces com gerenciamento Local
Visões DBA_LMT_FREE_SPACE e DBA_LMT_USED_EXTENTS
Listar arquivos temporários
Visões DBA_TEMP_FILES e V$TEMPFILE
Alterar tamanho de um arquivo
Comando ALTER RESIZE tamanho.
DATABASE
Oracle 9i Fundamental
DATAFILE
nome
273
Capítulo 21 – SEGMENTOS DE ROLLBACK/UNDO OBJETIVOS • • • • • •
Definir Segmento como uma entidade física; Diferenciar os tipos de Segmento; Compreender a importância dos Segmentos de Rollback/Undo; Diferenciar Segmento de Rollback de Segmento de Undo, este gerenciado automaticamente pelo Oracle; Criar, alterar ou eliminar Segmentos de Rollback tanto pelo SQL*Plus Worksheet, como pelo Enterprise Manager Console; Acompanhar a utilização dos Segmentos de Rollback e antever possíveis problemas.
NOVIDADES •
•
•
A gerência de Segmentos de Rollback foi enormemente facilitada com a SMU (System Managed Undo). Agora, o tempo do DBA gasto com áreas de Rollback tende a cair bastante; Estando ativa a SMU, pode-se implementar o recurso denominado Flashback Queries, que permite recuperar dados que estiveram presentes em algum instante passado; Desaconselha-se enfaticamente a utilização do parâmetro ROLLBACK_SEGMENTS. Assim como DB_BLOCK_BUFFERS, ele continua presente, porém caiu em desuso.
ARQUIVOS NECESSÁRIOS • • • •
21_Mostra_RBS.sql; 21_Monta_Tabelas.sql; 21_Recupera_Alunos; 21_Alimenta_Historico.sql.
PRÉ-REQUISITOS • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Conhecer o conceito de Tablespace e sua composição; Criar, alterar, excluir ou listar Tablespaces. Oracle 9i Fundamental
274
TEORIA 21.1 - Introdução aos Segmentos Segmentos ocupam fisicamente os arquivos que constituem a Tablespace na qual estão inseridos. Dividido em Extents e estes em Blocos, um Segmento pode ocupar mais de um arquivo, fato impossível para um Extent. Há quatro grandes tipos de Segmento: Tabela
Índice
Rollback/ Undo
Temporário
Armazena dados residentes em tabelas. Mais detalhes no capítulo 22. Estrutura que prioriza a velocidade de acesso aos dados. Mais detalhes no capítulo 23. Dividem-se em: Índice de Acesso: Árvores B que contêm valoreschaves. Index Cluster: Reunião física de tabelas com campo em comum. Hash Cluster: Reunião de tabelas cujas linhas são localizadas após cálculo. Requisitado por transações que precisem armazenar dados "velhos" que poderão ser reaproveitados. Dá-se o nome de Rollback àqueles criados no modo de gerenciamento manual e Undo quando a SMU (System Managed Undo) estiver ativa. Criado automaticamente em Tablespaces temporárias, quando o espaço requerido superar o especificado em SORT_AREA_SIZE. Ao terminar a operação requerente, o segmento é destruído. Para gerência de Extents baseada em Dicionário48, os Segmentos tempo-rários acompanham obrigatoriamente as especificações da Tablespace na qual residem. Valores recomendados: INITIAL > SORT_AREA_SIZE, NEXT e MAXEXTENTS grandes e PCTINCREASE igual a um (para que entrem nos procedimentos de compactação periódica). Além disto, INITIAL e NEXT devem ser múltiplos do valor estabelecido em SORT_AREA_SIZE. Na visão V$SYSSTAT, existem três valores relacionados a ordenações: sorts (memory), sorts(disk) e sorts(rows). Caso o segundo seja maior que 10% do primeiro, há problemas de mau dimensionamento de áreas temporárias. Para gerência de Extents Local, recomenda-se a modalidade UNIFORM.
O diagrama do capítulo 20 pode ser reescrito para:
48
Para conhecer a diferença entre as duas formas de gerenciar (Dicionário ou Local), consulte o capítulo 20, item 20.3.
Oracle 9i Fundamental
Extents
275
Diagrama demonstrando a relação entre entidades que consideram tipos de segmento.
Observações Nada impede que um segmento espalhe-se por mais de um datafile; Um Extent representa uma alocação contínua de bytes em um Data File, portanto um extent não pode ocupar mais de um Data File; A visão DBA_EXTENTS permite saber a qual extent pertence um bloco e a qual Data File pertence um extent. Este capítulo concentra-se nos Segmentos de Rollback/Undo.
21.2 - Introdução aos Segmentos de Rollback/ Undo Uma importante novidade introduzida na versão 9i é a possibilidade de gerenciar Segmentos de Rollback automaticamente. Historicamente, DBAs costumavam perder um tempo valioso preocupando-se com esta gerência, seja evitando problemas de contenção (muitos pedidos concentrados em poucos segmentos), seja para combater os famigerados erros ORA-1555 (Snapshot too old) e ORA-1562 (Unable to extend Rollback Segment). Para evitar possíveis mal-entendidos, a Oracle convencionou denominar Rollback Segment aqueles Segmentos criados sob gerência manual, Oracle 9i Fundamental
276
presente até a versão 8i e ainda possível na 9i. Já os Undo Segments identificam os criados sob gerência automática. No fundo, tanto um como outro significam o mesmo: uma área especial destinada a guardar conteúdos de blocos alterados por uma transação. Neste capítulo veremos as duas gerências, porém começaremos por um apanhado genérico. Quando uma transação que não seja do tipo READ ONLY começa, reservase uma entrada em um Segmento de Rollback/Undo. Uma transação não ocupa dois segmentos, entretanto um segmento pode conter várias entradas de transações. À medida que mais dados vão sendo modificados, mais extents vão sendo alocados. Na gerência manual, seguem-se os valores especificados nos Parâmetros de Armazenamento (INITIAL, NEXT, MINEXTENTS e MAXEXTENTS. PCTINCREASE não é utilizado). Dentro de um Extent, os blocos são alocados para as transações. Um Extent pode conter blocos de várias transações, entretanto cada bloco somente possui referência a uma transação: Extent Bloco 1
Bloco 2
Bloco 3
Bloco 4
Bloco 5
Transação 1, bloco 1
Transação 1, bloco 2
Transação 2, bloco 1
Transação 1, bloco 3
Transação 2, bloco 2
Disposição de Blocos e Transações em um Extent. Quando uma transação termina, os extents alocados para ela são liberados para que outra possa utilizá-los, isto é, os Extents que estavam ativos passam a estar inativos. Suponha que a Transação 1 tenha sido concluída:
Extent Bloco 1
Bloco 2
Bloco 3
Bloco 4
Bloco 5
Transação 1, bloco 1 Inativo
Transação 1, bloco 2 Inativo
Transação 2, bloco 1
Transação 1, bloco 3 Inativo
Transação 2, bloco 2
Quando a transação termina, o bloco fica inativo. Isto pode causar problemas, caso exista uma grande consulta que começou a ser executada antes da transação e continuou após o término dela. Caso os blocos inativos tenham sido requeridos por outra transação, a sessão executando a grande pesquisa receberá um erro clássico: ORA-1555: snapshot too old (rollback segment too small)
Oracle 9i Fundamental
277
Esse problema tende a não ocorrer quando a SMU estiver presente, já que é possível especificar o tempo que extents inativos devem ser preservados. Mais detalhes em seguida. A organização dos Extents em um Segmento de Rollback/Undo é circular, isto é, ao ser necessário um Extent, verifica-se a disponibilidade contígua. Se não for possível realizar a alocação até o último Extent, verifica-se o primeiro. Se ainda assim não for possível realizar a alocação, ocorre a expansão. Nota-se que, caso o primeiro esteja ocupado, mesmo que o segundo esteja livre, acontece a expansão. No caso da primeira tabela apresentada anteriormente, caso a segunda transação requeresse um bloco, ocorreria a expansão (Blocos 6 a 10), se a Transação 1 não tivesse sido concluída, ou seria utilizado o Bloco 1 (segundo quadro). O tamanho da área destinada a Segmentos de Rollback/Undo deve ser corretamente dimensionada, já que durante uma longa transação, se não for possível alocar um Extent, acontecerá o terrível ORA-1562. Aliás, ele provoca o rollback da transação em questão. As diretrizes que nortearão o quanto deve ser destinado a Segmentos de Rollback/Undo dependem da gerência utilizada. Voltaremos a este importante assunto nos próximos dois itens. Para que um Segmento de Rollback/Undo possa receber requisições de transações, ele deve estar ONLINE: select segment_name, tablespace_name, status from dba_rollback_segs order by 3,2,1;
Saída: SEGMENT_NAME -----------------------------_SYSSMU11$ _SYSSMU12$ _SYSSMU13$ _SYSSMU14$ _SYSSMU15$ _SYSSMU16$ _SYSSMU17$ _SYSSMU18$ _SYSSMU19$ _SYSSMU20$ SYSTEM _SYSSMU1$ _SYSSMU10$ _SYSSMU2$ _SYSSMU3$ _SYSSMU4$ _SYSSMU5$ _SYSSMU6$ _SYSSMU7$ _SYSSMU8$ _SYSSMU9$
TABLESPACE_NAME -----------------------------UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 UNDOTBS2 SYSTEM UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS UNDOTBS
STATUS -------OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE OFFLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE ONLINE
21 linhas selecionadas.
Oracle 9i Fundamental
278
Observações •
•
•
Vê-se pela listagem anterior que, apesar de existirem 21 Segmentos, apenas 11 estão disponíveis: um em SYSTEM e os outros em UNDOTBS. Logo após a criação do Banco de Dados e sua primeira Tablespace, SYSTEM, cria-se um Segmento de Rollback também denominado SYSTEM. Caso nada se diga em contrário, será estabelecida a SMU e criada uma Tablespace do tipo Undo que armazenará Segmentos de Undo. A visão DBA_ROLLBACK_SEGS informa o que for necessário sobre definições de Segmentos de Rollback/Undo: select column_name Campo, data_type Tipo from dba_tab_columns where table_name = 'DBA_ROLLBACK_SEGS'; CAMPO -----------------------------SEGMENT_NAME OWNER TABLESPACE_NAME SEGMENT_ID FILE_ID BLOCK_ID INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE STATUS INSTANCE_NUM RELATIVE_FNO
TIPO ---------VARCHAR2 VARCHAR2 VARCHAR2 NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER VARCHAR2 VARCHAR2 NUMBER
21.3 - Gerência Automática (System Managed Undo) Como já dito, ao criar um Banco de Dados, utilizando o Oracle Database Configuration Assistant (DBCA - assistente composto por várias telas amigáveis que faciltam a criação de um Banco - será discutido no capítulo 26), assume-se a gerência automática e também cria-se uma Tablespace do tipo Undo, cuja existência é obrigatória para que seja possível trabalhar com Undo Segments. Estando a SMU vigente, comandos outrora utilizados para manipulação de Segmentos de Rollback ficam proibidos: create, alter e drop rollback segment e set transaction to segmento de rollback Graças à SMU, Segmentos são criados e destruídos; ativados ou indisponibilizados ao sabor do ambiente. Isto libera o DBA de maçantes tarefas, tais como: criar, dimen-sionar, ativar, redirecionar, acompanhar, etc. Oracle 9i Fundamental
279
Os parâmetros seguintes indicam a presença da SMU: show parameters undo NAME -----------------------------------undo_management undo_retention undo_suppress_errors undo_tablespace
Parâmetro
TYPE ----------string integer boolean string
VALUE ----------AUTO 10800 FALSE UNDOTBS1
Descrição
undo_management
Indica presença da SMU (conteúdo AUTO), ou não (MANUAL). Único estático, ou seja, para que se torne efetivo, deve-se reiniciar a instância.
undo_retention
Tempo em segundos indicando a "vida" de um Extent. Este parâmetro pode ser "desobedecido" caso seja necessário requisitar novos Extents, ou seja, antes da alocação de mais espaço, procuram-se Extents unexpireds.
pode ser TRUE ou FALSE. Faz com que rotinas contendo comandos de gerência manual de Segmentos de Rollback não parem quando a SMU undo_suppress_er estiver ativa. Ao deparar-se com tais comandos, eles serão ignorados e rors simplesmente grava-se um aviso no arquivo de alertas
undo_tablespace
nome da Tablespace do tipo UNDO. Para que a SMU possa existir, deve-se garantir previamente a presença de uma Tablespace do tipo UNDO e que esteja ativa (online).
O tamanho da área destinada a Segmentos do tipo Undo pode ser dimensionada com auxílio da novíssima visão V$UNDOSTAT. Por exemplo, imagine que se tenha emitido a seguinte consulta: select to_char(begin_time, 'DD/MM/YY HH24:MI:SS') Início, to_char(end_time, 'DD/MM/YY HH24:MI:SS') Final, undoblks Blocos, maxconcurrency "Máxima Concorrência" from v$undostat;
Produzindo o resultado: INÍCIO ----------------10/05/02 11:57:52 10/05/02 11:47:52 10/05/02 11:37:52 10/05/02 11:27:52 10/05/02 11:17:52 10/05/02 11:07:52
FINAL BLOCOS Máxima Concorrência ----------------- ---------- ------------------10/05/02 11:59:15 100 3 10/05/02 11:57:52 146 4 10/05/02 11:47:52 95 1 10/05/02 11:37:52 180 5 10/05/02 11:27:52 96 1 10/05/02 11:17:52 105 2
Oracle 9i Fundamental
280
...
A relação anterior mostra o que aconteceu em termos de área de Undo nos últimos cinqüenta minutos. Alimenta-se V$UNDOSTAT automaticamente (estando a SMU ativa ou não) a cada dez minutos e por 24 horas, portanto a quantidade máxima de linhas será de 144. Supondo que o mostrado represente um intervalo típico de utilização do banco, podemos concluir o seguinte: • O pico de utilização foi de 180 blocos. • Supondo que o tempo de retenção (conteúdo de UNDO_RETENTION) seja de três horas (10.800 segundos), precisaríamos de 180 * 4K (tamanho do bloco) * 18 (intervalos de 10 minutos) = 13.271.040 bytes (pouco mais de 12 MB). • Convém utilizar uma boa folga, assim podemos destinar 20 MB à Tablespace de Undo. • Naturalmente, vale a pena checar periodicamente a V$UNDOSTAT para não ser surpreendido.
21.4 - Flashback Queries Estando a SMU ativa, sob determinadas circunstâncias, é possível recuperar o conteúdo de uma tabela cujas linhas tenham sido excluídas acidentalmente. Trata-se do inédito recurso denominado Flashback Queries que aproveita dados coletados nos Extents ainda não expirados. Isto significa que as transações que os utilizaram foram concluídas há menos tempo do que informa o parâmetro undo_retention_size ou seus espaços ainda não foram novamente ocupados. A capacidade de recuperação restringe-se a cinco dias, sempre e quando Extents não tiverem sido reutilizados ou não tiver acontecido algum comando DDL sobre a tabela que se deseja recuperar, ou seja, a tabela não pode ter sofrido nenhum alter table, drop table, truncate table, etc.). Antes de aproveitar esse recurso, deve-se conceder permissão49 de execução no Package embutido DBMS_FLASHBACK ao usuário que deseja utilizá-lo. Conectado como SYS, emite-se o comando: grant execute on dbms_flashback to dbaacad;
Imagine que às 9:00 de uma nefasta manhã qualquer, tenham sido eliminados os conteúdos das tabelas ALUNOS e HISTORICO: delete historico; delete alunos; commit;
E que vinte minutos depois venha-se descobrir tal fatalidade: 49
A concessão Segurança.
de
permissões
voltará
a
ser
abordada
Oracle 9i Fundamental
no
capítulo
24
-
281
select count(*) from alunos; COUNT(*) ---------0
Para "voltar no tempo", utiliza-se a rotina enable_at_time, presente no já citado Package: execute dbms_flashback.enable_at_time (sysdate - 25/1440);
Este comando busca o estado das tabelas como estava há vinte e cinco minutos (um dia possui 1.440 minutos). De fato: select count(*) from alunos; COUNT(*) ---------20
Infelizmente, existem algumas restrições após habilitar uma janela no tempo. Estão proibidos quaisquer comandos DDL, execute e mesmo inserts, updates ou deletes, ou seja, é possível apenas consultar as tabelas. Tantas limitações trazem outro inconveniente: a única forma de recuperar os dados consiste em criar um Script que entre e saia do modo Flashback50: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
50
Declare cursor calunos is select * from alunos; v_linha
alunos%rowtype;
BEGIN delete aux_alunos; -- O recurso Flashback não pode ser ativado em meio a uma transação: commit; -- Entra no modo Flashback (edite a quantidade de minutos por voltar) dbms_flashback.enable_at_time (sysdate - 50/1440); open calunos; dbms_flashback.disable; fetch calunos into v_linha ; while calunos%found loop insert into aux_alunos values (v_linha.matricula, v_linha.nome_aluno, v_linha.tel_aluno, v_linha.endereco_aluno, v_linha.cidade_aluno, v_linha.uf); fetch calunos into v_linha ; end loop; close calunos; commit; END;
O código seguinte encontra-se no arquivo exemplo 21_Recupera_Alunos.sql.
Oracle 9i Fundamental
282
Observações • •
•
A recuperação não precisa acontecer na mesma sessão responsável pela perda; Note como se entrou no modo Flashback apenas para abrir o Cursor e logo depois voltou-se ao estado normal por meio da rotina dbms_flashback.disable; Uma vez concluída a execução dos comandos anteriores, é possível recarregar a tabela ALUNOS: insert into alunos select * from aux_alunos;
21.5 - Gerência Manual Estando o parâmetro undo_management como MANUAL, ganha-se mais controle sobre o que acontece no que diz respeito a rollback. Inclusive, pode-se direcionar a escolha de qual Segmento de Rollback será utilizado por uma determinada Transação: SET TRANSACTION USE ROLLBACK SEGMENT nome
Ainda que não se possa afirmar com toda certeza que o Oracle reservará o Segmento de Rollback pedido, pode ser uma boa medida quando se busca máxima performance para tarefas críticas. O desempenho será melhor, já que não existirá disputa entre transações pelos Extents. Um Segmento de Rollback pode ser classificado, segundo sua utilização. Ele pode ser público, caso possa ser compartilhado entre várias Instâncias (neste caso a opção Parallel Server deve estar ativa), ou pode ser privativo e somente ser acessado por uma única Instância. Para especificar segmentos privativos, o nome do Segmento de Rollback deve aparecer no parâmetro rollback_segments. Ainda existem dois parâmetros relevantes relacionados com Segmentos de Rollback. Veja como listar os três: show parameters rollback_segment NAME ----------------------------------max_rollback_segments rollback_segments transactions_per_rollback_segment
TYPE ------integer string integer
VALUE ---------37 5
Enquanto o primeiro limita a quantidade de Segmentos, o último restringe o número de transações por Segmento. Estes valores devem ser deduzidos após minuciosos estudos sobre o comportamento transacional do banco. O comando create rollback segment, detalhado em seguida, permite criar Segmentos de Rollback. CREATE [PUBLIC] ROLLBACK SEGMENT nome TABLESPACE nome
Oracle 9i Fundamental
283
STORAGE (INITIAL NEXT MINEXTENTS MAXEXTENTS OPTMAL
inteiro [K | M] inteiro [K | M] inteiro inteiro [inteiro [K | M] | NULL)
As palavras-chave e os parâmetros estão detalhados em seguida: Nome
Nome do Segmento de Rollback
PUBLIC
Determina que o SR em questão estará disponível para qualquer instância ativa. Caso seja omitida, ele será privativo e somente disponível às instâncias que o mencionarem no parâmetro rollback_segments.
TABLESPACE
Nome da Tablespace na qual estará inserido. Recomenda-se fortemente que exista uma Tablespace exclusiva, já que uma contendo Segmentos de Rollback ativos não pode ser posta em estado OFFLINE. Parâmetros de Armazenamento (veja mais detalhes em 20.3). INITIAL NEXT
STORAGE MINEXTENTS
No mínimo devem ser dois para caracterizar uma lista circular.
MAXEXTENT S
OPTIMAL
Indica o tamanho final em bytes que o Segmento deve ser contraído quando houver muitos extents inativos. Isto impede que o Segmento de Rollback cresça indefinidamente, ou atinja MAXEXTENTS antes do que se espera.
Note que o parâmetro PCTINCREASE não se aplica a Segmentos de Rollback.
Exemplo create rollback segment rb17 tablespace rbs;
Observações • •
•
Foram seguidos os valores de Parâmetros de Armazenamento da Tablespace RBS, que já deve ter sido criada previamente; Aliás, RBS não pode ter sido criada com gerenciamento de Extents Local. Somente é permitido criar Segmentos de Rollback em Tablespaces cujo gerenciamento de Extents seja do tipo Dicionário; Uma vez criado, o Segmento de Rollback permanece inativo. Deve-se emitir o comando:
Oracle 9i Fundamental
284
alter rollback segment rb17 online;
A sintaxe do comando alter rollback segment é: ALTER ROLLBACK SEGMENT nome [ONLINE | OFFLINE] STORAGE (INITIAL inteiro [K | M] NEXT inteiro [K | M] MINEXTENTS inteiro MAXEXTENTS inteiro OPTIMAL [inteiro [K | M] | NULL) SHRINK TO inteiro [K | M]
A opção shrink permite contrair manualmente o Segmento de Rollback. Isto somente não será possível, caso existam Extents ativos. Para mudar o valor de algum parâmetro de armazenamento, não é necessário que o Segmento de Rollback esteja offline, exceto shrink to. Finalmente, eliminam-se Segmentos de Rollback inativos por meio do comando drop rollback segment: alter rollback segment rb17 offline; drop rollback segment rb17;
Uma das tarefas mais críticas do DBA consiste em acompanhar a evolução dos Segmentos de Rollback. O script seguinte mostra diversos dados sobre Segmentos de Rollback ativos produzindo um SELECT que integra as visões dinâmicas V$ROLLNAME e V$ROLLSTAT com a já conhecida DBA_ROLLBACK_SEGS: set linesize 100 column name format a10 select n.name, r.writes, r.wraps, r.shrinks, r.extends, r.extents, d.max_extents MAX, d.initial_extent "INITIAL", d.next_extent "NEXT" from v$rollname n, v$rollstat r, dba_rollback_segs d where n.usn = r.usn and d.segment_name = n.name;
E uma saída hipotética: NAME WRITES WRAPS -------- -------- -----SYSTEM 3728 0 RB17 54 0
SHRINKS ------0 0
EXTENDS EXTENTS MAX INITIAL NEXT ------- ------- ------ ------------0 7 249 53248 53248 0 2 32765 131072 131072
Alguns termos devem ser esclarecidos: WRITE
Bytes gravados
SHRINK
Contrações automáticas (devido à cláusula OPTIMAL) ou manuais
WRAP
Alocação sem expansão Oracle 9i Fundamental
285
EXTEND Expansões
Vários aspectos podem ser observados, por exemplo, se houve um número exagerado de expansões, o que pode indicar alto grau de fragmentação.
21.6 - Regras de Ouro para Gerência Manual Existem algumas "regras de ouro" que ajudam bastante a gerência de Segmentos de Rollback: 1. Crie Segmentos de Rollback de mesmo tamanho, já que normalmente não se escolhe qual Segmento de Rollback será atribuído a uma transação; 2. Nunca se deve criar apenas um grande Segmento de Rollback devido a problemas de contenção, isto é, há o risco de que várias transações fiquem "esperando" a liberação do Segmento de Rollback; 3. Também não resulta uma boa prática criar muitos Segmentos de Rollback e pequenos. O exagerado número de expansões pode comprometer a performance geral; 4. Evite executar longas consultas em paralelo com extensas atualizações. Há o risco de acontecer o erro ORA-1555; 5. Transações longas e críticas devem utilizar Segmentos de Rollback próprios; 6. Dimensione os Segmentos de Rollback para que um Extent seja capaz de comportar a maior transação. Aliás, esta regra norteia a SMU. Quantifique os Segmentos de Rollback para que sejam tantos quantas forem as transações simultâneas.
21.7 - Enterprise Manager Console Pelo EMC é bastante simples acompanhar o estado dos Segmentos de Rollback de um banco:
Para criar um novo Segmento de Rollback, clica-se com o botão direito do mouse em Segmentos de Rollback e escolhe-se Criar: Oracle 9i Fundamental
286
EXERCÍCIOS Antes de realizar os exercícios deste capítulo, verifique se há um schema que possa abrigar tabelas referentes ao Controle Acadêmico, direcione a Tablespace default para Tabelas (criada no capítulo 20) e execute o script 21_Monta_Tabelas.sql. 1. Imagine o seguinte cenário: a) Começa uma longa consulta C que precisa ler os blocos B1 a B500; b) Enquanto C estiver lendo o bloco B200, os blocos B300 a B400 são alterados por outra transação; c) Quando C chegar a B300, que foi transferido para um Segmento de Rollback, a transação modificadora é encerrada com commit; d) Enquanto C estiver lendo o bloco B350, uma terceira transação requere área de Rollback e os blocos B370 a B390 são cedidos. Questão: O que acontece com a consulta C? Erro? Terceira transação tem pedido negado? 2. Comprove que alterando a estrutura de uma tabela cujas linhas desejase recuperar inviabiliza-se o recurso Flashback. a) Crie uma tabela teste e alimente-a com dados; b) Anote a hora; c) Elimine suas linhas e emita um commit; d) Acrescente-lhe uma coluna; e) Tente recuperar seus dados a partir do recurso Flashback. 3. Verifique a presença da SMU e, caso exista, desative-a. • Caso seja necessário alterar a forma pela qual a área de Rollback está sendo gerenciada, faça o seguinte: Oracle 9i Fundamental
287
a) Altere o conteúdo do parâmetro undo_management para MANUAL; b) Derrube a instância e reinicie-a, certificando de fazê-lo com a utilização do Arquivo texto de parâmetros; c) Constate que o conteúdo da visão V$UNDOSTAT foi zerado. 4. Crie e ative um Segmento de Rollback, RNOVO, com as seguintes especificações: • MINEXTENTS 2 • MAXEXTENTS 3 • INITIAL 8K • NEXT 8K 5. Inicie uma nova transação e atribua-lhe RNOVO. • Use o comando set transaction. 6. Se já não existir, crie a procedure AlimentaHistorico. • Utilize o script fornecido 21_Alimenta_Historico.sql. 7. Repita o processo: execute a rotina e mostre os Segmentos de Rollback ativos (21_Mostra_RBS.sql) até que seja emitida a seguinte mensagem: ERROR at line 1: ORA-01562: failed to extend rollback segment number 20 ORA-01628: max # extents (3) reached for rollback segment RNOVO ORA-06512: at "DBAACAD.ALIMENTAHISTORICO", line 5 ORA-06512: at line 1
Oracle 9i Fundamental
288
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Verificar a presença da SMU (gerência automática da área de Rollback)
Veja o conteúdo do parâmetro undo_management.
Criar um Segmento de Rollback
Comando create rollback segment Esta funcionalidade, assim como alterar e excluir, está disponível no Enterprise Manager Console, mas cuidado: SMU deve estar desativada e a Tablespace destino deve ter gerenciamento de Extents do tipo Dicionário.
Alterar um Segmento de Rollback
Comando alter rollback segment
Eliminar um Segmento de Rollback
Comando drop rollback segment
Listar Segmentos de Undo/Rollback ou informações afins
Visões: DBA_SEGMENTS, DBA_ROLLBACK_SEGS, DBA_UNDO_EXTENTS, V$ROLLNAME, V$ROLLSTAT, V$UNDOSTAT e V$TRANSACTION
Direcionar a utilização de um Segmento de Rollback quando a SMU não estiver vigente
Comando: set transaction use rollback segment nome
Oracle 9i Fundamental
289
ANOTAÇÕES
Oracle 9i Fundamental
290
Capítulo 22 – SEGMENTOS DE TABELA OBJETIVOS • • • • • • • • •
Compreender a importância dos Segmentos de Tabela; Criar, alterar ou eliminar Segmentos de Tabela pelo SQL*Plus Worksheet; Acompanhar a utilização dos Segmentos de Tabela; Identificar e resolver problemas causados pelo encadeamento e/ou migração de linhas; Trabalhar com os objetos Materialized View e Index-Organized Table; Reconhecer a importância do particionamento de tabelas para a melhoria dos tempos de acesso; Habituar-se com a atualização periódica de estatísticas de tabelas; Reorganizar dinamicamente o espaço ocupado por uma tabela graças ao Package embutido DBMS_REDEFINITION; Manipular Tabelas Externas.
NOVIDADES •
•
•
O comando ANALYZE TABLE perdeu a importância de outrora. Recomenda-se agora atualizar estatísticas via o Package embutido DBMS_STATS; O Package embutido DBMS_REDEFINITION permite alterar dinamicamente características internas de uma tabela, sem afetar sua utilização; Além das organizações HEAP e INDEX, foi acrescentada mais uma, EXTERNAL. Ela permite que arquivos texto especiais sejam lidos como se fossem tabelas comuns.
ARQUIVOS NECESSÁRIOS • • • • • •
21_Alimenta_Historico.sql; 22_Ex_Cria_Tabelas.sql; 22_Ex_Altera_Tabelas.sql; 22_Ex_Materialized_Views.sql; 22_Lista_Extents.sql; 22_Lista_Tamanho_Linhas.sql; Oracle 9i Fundamental
291
• • • • • • •
22_Monta_Tabelas_Particoes.sql; 22_Alimenta_Dados.sql; 22_Altera_Tabela_Particoes.sql; 22_Lista_Estatisticas.sql; 22_Redefine_Alunos.sql; 22_Novos_Instrutores.txt; 22_Ex_Tabela_Externa.sql.
PRÉ-REQUISITOS • • • • • • •
Dominar comandos SQL dos tipos DDL, DML e DCL; Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Desenvolver Triggers básicos; Trabalhar com Packages embutidos; Conhecer o conceito de Tablespace e sua composição; Criar, alterar, excluir ou listar Tablespaces; Conhecer o conceito de Segmento e sua composição.
TEORIA 22.1 - Fundamentos As tabelas de um banco, repositórios de dados, na verdade representam Segmentos compostos de Extents e estes por Blocos. Por motivos de desempenho, recomenda-se isolar Segmentos de Tabela em Tablespaces próprias; inclusive tabelas com níveis de acesso diferentes também devem ser isoladas. Uma tabela pode ser classificada em: Aplicação
Tende a ser grande, muito consultada. Após a carga inicial, é pouquís-simo atualizada. Por exemplo: CEPs.
Negócio
Bastante consultada, atualização moderada, possui uma taxa de cresci-mento muito pequena. Por exemplo: Alunos, Instrutores.
Transacional
Sofre inserções, atualizações e exclusões constantes. Por exemplo: Histórico.
Segmentos de Tabela são criados com o já conhecido comando create table que possui uma sintaxe bastante mais ampla do que a já vista: além da especificação de campos e constraints, ainda é possível detalhar a Tablespace, Parâmetros de Armazenamento (INITIAL, NEXT, etc. para aquelas que constarem em Tablespaces com gerência de Extents baseada em Dicionário), que se sobrepõem aos definidos na Tablespace hospedeira, Oracle 9i Fundamental
292
e Parâmetros de Utilização de Espaço, que determinam como serão configurados os blocos da tabela. A sintaxe ainda simplificada51 do comando é mostrada em seguida: CREATE TABLE [GLOBAL TEMPORARY] nome (campos, constraints) [TABLESPACE nome] [PCTFREE inteiro entre 0 e 100] [PCTUSED inteiro entre 0 e 100] [INITRANS inteiro] [MAXTRANS inteiro] [STORAGE (INITIAL inteiro [K | M] NEXT inteiro [K | M] MINEXTENTS inteiro MAXEXTENTS inteiro PCTINCREASE inteiro entre 0 e 100)] [ORGANIZATION HEAP | INDEX | EXTERNAL] [ON COMMIT DELETE | PRESERVE ROWS] [LOGGING | NOLOGGING] [NOPARALLEL | PARALLEL inteiro] [PARTITION detalhes de particionamento]
As cláusulas estão detalhados em seguida: Cláusula
Detalhes
GLOBAL TEMPORARY
Informa que a tabela sendo criada será temporária, isto é, os dados serão visíveis apenas à sessão que os incluir (ao final da sessão, a tabela será limpa). Veja Exemplo 2, em seguida.
Nome
Nome do Segmento de Tabela
Campos, constraints
Nomes de campos com respectivos tipos e constraints associados. Veja mais detalhes e exemplos no capítulo 2.
TABLESPACE
Nome da Tablespace na qual estará inserida. Se tratar-se de uma tabela temporária, proíbe-se esta cláusula.
PCTFREE
Número inteiro representando a porcentagem de espaço deixado livre para atualizações de campos com tamanho variável (varchar2, nulos). Para determinar um valor razoável, deve-se analisar o comportamento da tabela. Se houver muitos campos com tamanho variável, recomenda-se um valor maior que 10%. Por outro lado, se os campos já vierem “completos”, aconselha-se um PCTFREE próximo a zero. Default: 10.
51
A sintaxe completa do comando e o detalhamento de todas as cláusulas podem ser encontrados no manual Oracle 9i SQL Reference, Capítulo 14.
Oracle 9i Fundamental
293
Cláusula
Detalhes
PCTUSED
Número inteiro representando a porcentagem de espaço utilizado para armazenamento de dados. Enquanto esse valor não for atingido, o bloco é tratado como “livre”. Default: 40. Para tabelas com poucas atualizações, recomenda-se 80%. Já para tabelas muito atualizadas, aconselha-se 20%. Já Kevin Loney em seu excelente ORACLE 8i DBA HANDBOOK, na página 191, sugere que o valor de PCTUSED somado ao do PCTFREE seja de 85.
INITRANS
Número de transações por bloco. Cada transação é registrada no cabeçalho do bloco junto com ponteiros para linhas cujos dados estão no bloco. Default: 1. Máximo: 255.
MAXTRANS
Número máximo de transações simultâneas acessando o bloco.
STORAGE
Parâmetros de Armazenamento utilizados quando a gerência de Extents for do tipo Dicionário (veja mais detalhes em 20.3). Ao realizar a carga de uma tabela, deve-se procurar, sempre que razoável, preencher os dados em apenas um Extent. Expansões devem ser evitadas, calculando valores adequados para NEXT e PCTINCREASE. Quando uma tabela atingir dez Extents, significa que o nível de fragmentação está alto e deve-se recriá-la. Uma vez alocado espaço, nenhum outro Segmento de Tabela o utiliza até que ocorra um drop table ou truncate table. O comando truncate table recupera os Extents alocados. Caso PCTINCREASE seja maior que zero, NEXT volta ao valor original.
ORGANIZATION
Informa como as linhas da tabela serão organizadas. Há três possibi-lidades: HEAP (sem nenhuma ordem específica; default), INDEX (em forma de índice - IOT; veja mais detalhes no item 22.6) ou EXTERNAL (tabela apenas de leitura e armazenada externamente ao banco; mais detalhes em 22.10).
ON COMMIT
Utilizada exclusivamente para tabelas temporárias. Determina se as linhas devem ser preservadas até o final da transação corrente (DELETE) ou da sessão (PRESERVE ROWS).
LOGGING
Determina se a criação da tabela e dos índices que dela decorrerem será registrada no Redo Log File (LOGGING) ou não (NOLOGGING). Caso não seja informado, busca-se a definição utilizada na Tablespace hospedeira. Utilizar a opção NOLOGGING, ainda que acelere a criação, representa um risco, já que não poderá ser recuperada a partir dos Archived Redo Log Files (mais detalhes no capítulo 25).
PARALLEL
Permite a criação da tabela utilizando recursos em paralelo (no Windows 2000 seriam threads; no Unix, processos).
Oracle 9i Fundamental
294
Cláusula
Detalhes
PARTITION
Especifica partições físicas a serem utilizadas para isolar grupos de linhas da tabela. Mais detalhes no item 22.7.
Os valores de PCTFREE, PCTUSED, INITRANS e MAXTRANS são conhecidos como Parâmetros de Utilização de Espaço. Lembre-se que ainda é permitido criar tabelas de objetos, como visto no capítulo 17.
Primeiro exemplo52: Recriando a tabela HISTORICO create table historico (cod_turma constraint historico_turma_fk references turmas (cod_turma), matricula constraint historico_aluno_fk references alunos (matricula), nota number (7,2), constraint historico_pk primary key (cod_turma, matricula)) tablespace users pctfree 20 pctused 65;
Segundo exemplo: Tabela temporária create global temporary table lista_chamada (cod_turma number(3), matricula number(3), nome varchar2(30), instrutor varchar2(30), sala number(2), nota number (7,2), constraint chamada_pk primary key (cod_turma, matricula)) on commit preserve rows;
Observações •
• •
Tabelas temporárias não podem possuir chaves estrangeiras, nem ser particionadas, nem organizadas como índice (IOTs) ou serem externas; Linhas de tabelas temporárias sempre ficam armazenadas em Tablespaces temporárias; Ainda que seu conteúdo seja volátil (dura por uma transação ou sessão), a estrutura de campos mantém-se permanente.
22.2 - Alteração de Segmentos de Tabela 52
Os exemplos apresentados 22_Ex_Cria_Tabelas.sql.
em
seguida
constam
Oracle 9i Fundamental
no
arquivo
exemplo
295
A sintaxe ainda simplificada do comando alter table é: ALTER TABLE nome ADD (campos, constraints) MODIFY (campos, constraints) DROP (campo, constraint) LOGGING | NOLOGGING PCTFREE inteiro entre 0 e 100 PCTUSED inteiro entre 0 e 100 INITRANS inteiro MAXTRANS inteiro STORAGE (cláusulas de armazenamento) MOVE novo destino RENAME TO novo nome ALLOCATE EXTENT (SIZE inteiro [K | M]) | DATAFILE nome DEALLOCATE UNUSED [KEEP numero [K | M]]
Observe os seguintes pontos: • Lembre-se que o comando alter table já foi utilizado no capítulo 2 (item 2.3) e no 16 para habilitar ou desabilitar os Triggers de uma tabela: alter table alunos disable all triggers;
Permite-se mudar a Tablespace de origem graças à cláusula MOVE (veja exemplo em seguida); • Evite utilizar a cláusula NOLOGGING; • Não é possível inserir campos não nulos em tabelas com dados, a não ser que seja utilizado um constraint DEFAULT. O espaço outrora ocupado pelas linhas apagadas de uma tabela não é recuperado. Isto só acontece nos comandos truncate table ou drop table. •
Primeiro exemplo53: Alterando parâmetros de utilização de espaço alter table historico pctfree 10 pctused 75;
Segundo exemplo: Tabela temporária alter table lista_chamada drop column sala;
Observação •
53
Para que seja possível a operação anterior, nenhuma sessão pode ter alimentado a tabela em questão.
Os exemplos apresentados 22_Ex_Altera_Tabelas.sql.
em
seguida
constam
Oracle 9i Fundamental
no
arquivo
exemplo
296
Terceiro exemplo: Movendo uma tabela de uma tablespace para outra alter table alunos move tablespace users;
Observações •
• •
•
O comando anterior somente funciona para tabelas não particionadas (partições devem ser movidas uma a uma). Não é possível mover tabelas temporárias, nem externas, nem possuindo campos LOB; A cláusula MOVE deve ser a única presente; Uma alternativa à cláusula MOVE seria exportá-la, eliminá-la, recriar a estrutura mencionando a nova Tablespace e importar seus dados a partir do arquivo exportado. O capítulo 25 explica as operações de importação e exportação; Uma terceira forma seria criar uma tabela duplicata com create table ... as select, especificando o novo destino, excluir a original e renomear a cópia com o nome da original.
22.3 - Identificação de Linhas Em tabelas cuja organização seja do tipo HEAP (especificação default da cláusula ORGANIZATION do comando create table), a ordem física das linhas geralmente não obedece à ordem de inserção. Ainda que elas possam coincidir em pequenas tabelas, discrepâncias tendem a ocorrer após muitas exclusões e inserções. Para conhecer o número da linha, pode-se utilizar a Pseudocoluna54 ROWNUM ou, de uma forma mais segura, por meio de outra Pseudocoluna, ROWID. Vejamos alguns exemplos: select rownum, nome_aluno from alunos where rownum < 10 order by 2 desc;
Saída: ROWNUM -----1 2 3 4 6 5 9 8 7 54
NOME_ALUNO -----------------------------Zebedeu Silva Hydra Yamandu Ramos Centaurus Wellington Libra Tadeu Perseu Marcelo Lyra Luis Eridanus Rios José Neves Gemini Daniel Auriga Carla Cassiopeia
No capítulo 6, item 6.4 (Sequences) já foram apresentadas duas outras Pseudocolunas: CURRVAL e NEXTVAL.
Oracle 9i Fundamental
297
Note que ROWNUM representa a ordem em que a linha foi lida, que pode diferir da ordem em que foi mostrada. Uma costumaz reclamação de DBAs e programadores acostumados com o Microsoft SQL Server que resolvem migrar para Oracle é a ausência da cláusula TOP no comando SELECT para retornar as n primeiras linhas. Por exemplo, o seguinte comando funcionaria no MS SQL Server, mas não no Oracle: select top 10 nome_aluno from alunos order by 2 desc
Para o Oracle, obteríamos resultado semelhante com o seguinte comando: select nome_aluno from (select nome_aluno from alunos order by 1 desc) where rownum < 11;
Observe que obtêm-se as linhas de um conjunto já ordenado, o que garante o resultado desejado. Vimos então que ROWNUM não representa um mecanismo confiável para retornar a enésima linha física de uma tabela. Para isto, utilizamos ROWID: select rowid, nome_aluno from alunos where nome_aluno like 'G%';
Saída: ROWID -----------------AAAH3fAAIAAAABiAAR AAAH3fAAIAAAABiAAU AAAH3fAAIAAAABiAAV AAAH3fAAIAAAABiAAW
NOME_ALUNO -----------------------------Gérson Orion Geraldo Capricornius Genaro Bootes Gago Ursa
Infelizmente, os valores de ROWID aparecem codificados conforme o seguinte critério: Do Caractere ...
Significado
1 ao 6
Segmento
7 ao 9
Arquivo
10 ao 15
Bloco
16 ao 18
Linha bloco
dentro
do
Para “traduzir” um ROWID, devemos utilizar funções do Package embutido DBMS_ROWID: select file_name from dba_data_files where relative_fno = (select dbms_rowid.rowid_relative_fno (rowid) from alunos where nome_aluno like 'G%' and rownum = 1);
Saída: FILE_NAME -----------------------------------------------------------E:\ORACLE\ORADATA\ACAD9\USERS01.DBF
Oracle 9i Fundamental
298
O Package embutido DBMS_ROWID apresenta outras funções. Vejamos algumas: Função
Resumo
ROWID_BLOCK_NUMBER
Retorna o número do bloco em que a linha em questão está armazenada.
ROWID_ROW_NUMBER
Número da linha.
ROWID_TO_ABSOLUTE_F NO
Número absoluto55 do arquivo contendo a linha.
ROWID_TO_RESTRICTED
Exibe um ROWID no formato utilizado previamente à versão 8.
22.4 - Encadeamento de Linhas Imagine o seguinte cenário: uma Tablespace que contém três tabelas distribuídas por 16 blocos: Blocos
Tabela
Observações
1a6
Alunos
7 a 10
Cursos
Sexto bloco ocupado
11 a 14
Instrutore s Bloco 14 parcialmente ocupado Nenhuma
15 e 16
está
parcialmente
Suponha que tenha ocorrido uma inserção na tabela CURSOS. Isto causará a ocupação de parte do décimo quinto bloco, provocando uma evidente fragmentação. Um problema mais grave aconteceria caso houvesse uma alteração que demandasse mais espaço em ALUNOS. Por exemplo, se um VARCHAR2 de 20 bytes fosse modificado para 40, poderiam acontecer dois fatos indesejáveis: toda a linha seria movida para outro bloco (migração) ou parte da linha seria gravada em outro bloco (encadeamento). Em qualquer dos casos, aconteceria uma inconveniente fragmentação. O destino de parte ou toda a linha alterada poderia ser o final do sexto bloco ou, pior, o décimo quinto. Para listar linhas quebradas, deve-se incialmente executar o script \oracle\ora92\rdbms\admin\utlchain.sql (ele criará uma tabela de trabalho deno-minada CHAINED_ROWS). Depois, coletam-se as linhas encadeadas com o coman-do:
55
Uma importante novidade introduzida na versão 8 é a alteração do formato do ROWID para que sejam contemplados arquivos relativos. Isto permitiu aumentar drasticamente a capacidade de endereçamento de linhas.
Oracle 9i Fundamental
299
analyze table alunos list chained rows;
Para listá-las, faça: select head_rowid from chained_rows where table_name = 'ALUNOS';
A solução desse problema acontece em três etapas: 1. Exportação dos objetos que constam na Tablespace. No caso, as três tabelas, mais as que forem dependentes (HISTORICO); 2. Exclusão das tabelas; 3. Importação dos dados. Os detalhes de implementação dos passos 1 e 3 serão vistos no capítulo 25. Quando a tabela possuir chaves estrangeiras apontando para ela, o cumprimento da segunda etapa causará transtornos, já que inicialmente devem-se desligar os cons-traints. Às vezes, resulta mais prático exportar todo o Schema, destruí-lo e voltar a importá-lo.
22.5 - Materialized Views Em ambientes em que há necessidade de consultar enormes bases de dados que também estão sendo alteradas, a concorrência de leituras e gravações pode causar sérios problemas de performance. Uma bela saída consiste em criar Materialized Views, capazes de armazenar dados espalhados por várias tabelas e ainda contendo agregações. Ainda existe a vantagem das atualizações periódicas (refreshing), o que garante o sincronismo entre as bases consultadas e atualizadas. O exemplo seguinte revela como criar uma Materialized View atualizada sob demanda56: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
create materialized view mv_instrutores build immediate Refresh complete on demand As select nome_instrutor, nome_curso, count(*) Alunos from instrutores i , turmas t, cursos c, historico h where i.cod_instrutor = t.cod_instrutor and t.cod_curso = c.cod_curso and t.cod_turma = h.cod_turma group by nome_instrutor, nome_curso;
Observações •
56
As tabelas que alimentam uma Materialized View são ditas master tables;
O exemplo consta no arquivo 22_Ex_Materialized_Views.sql.
Oracle 9i Fundamental
300
•
•
Em vez da opção IMMEDIATE (linha 2), poder-se-ia utilizar DEFERRED e os dados somente seriam inseridos na primeira atualização; Automatiza-se a atualização dos dados utilizando a cláusula ON COMMIT em vez de ON DEMAND (linha 4). Também é possível determinar uma periodicidade, digamos semanal, na atualização: refresh fast next sysdate + 7
•
Após a criação, deve-se informar ao Otimizador de Queries que há um novo recurso que pode ser utilizado. Isto deve ser feito via Package embutido DBMS_STATS, como visto no próximo item;
•
Curiosamente, a sintaxe padrão SQL-92 contendo cláusulas join foi rechaçada.
Uma vez criadas, as consultas serão muito mais eficientes já que não existe necessidade de realizar joins ou agregações: select * from mv_instrutores order by Alunos;
Alterada a base, atualiza-se a Materialized View com uma chamada ao Package embutido DBMS_MVIEW: begin dbms_mview.refresh('MV_INSTRUTORES'); end; /
22.6 - Index-Organized Tables (IOTs) Tabelas muito consultadas em base a valores exatos ou intervalos são belas candidatas a uma organização alternativa. Em vez da tradicional HEAP em que não há uma ordem específica para as linhas, há necessidade de estruturas de índice separadas para acelerar o acesso e as linhas são identificadas via ROWID, pode-se utilizar a opção INDEX na cláusula ORGANIZATION do comando create table. Cria-se, na verdade, um objeto híbrido denominado IOT (Index-Organized tables), em que tanto chaves como dados estão em uma mesma estrutura de árvore-B. Uma decorrência interessante dessa organização consiste na inserção ordenada. Por exemplo, imagine uma IOT possuindo milhares de linhas e contendo a chave primária baseada em um campo alfanumérico. Ao acontecerem inclusões, será necessário “abrir espaço” para que as novas linhas possam entrar. Isto, evidentemente, causará problemas de performance. Concluindo, IOTs representam um recurso adequado para tabelas muito consultadas e pouco atualizadas. E, de preferência, as buscas devem basear-se nos campos da chave primária, esta, aliás, de presença obrigatória. Oracle 9i Fundamental
301
Suponha que desejássemos criar uma tabela que guardasse os CEPs de todos os logradouros do país. Claramente, uma vez carregada, sofreria poucas alterações. Então: create table ceps ( cep char(10) primary key, uf char(2), municipio varchar (20), logradouro varchar (40)) organization index tablespace users;
Observações •
• •
•
Por ser essencialmente uma tabela, um IOT, podem-se utilizar os comandos insert, update, delete, etc. Inclusive, podemos acrescentar chaves estrangeiras ou novos índices a outros campos que não estejam na chave primária; Como não há ROWID, demanda-se menos espaço; Resulta impossível alterar a organização interna de uma tabela HEAP para IOT e vice-versa. Para realizar esta tarefa, devem-se exportar as linhas, eliminar a tabela, recriá-la sob nova organização e importar as linhas; Curiosamente, o parâmetro de utilização de espaço PCTUSED não pode ser utilizado em IOTs. O mesmo ocorre em índices, como veremos no capítulo seguinte.
22.7 - Partições Quando uma tabela muito grande possui crescimento desordenado, isto é, alguns “trechos” sofrem inserções em ritmos diferentes de outros, convém particioná-la. Imagine que a tabela ALUNOS apresente o seguinte comportamento: • • •
Cariocas são inseridos à taxa de 1.000 ao mês; Alguns paulistas são inseridos e outros eliminados; Mineiros e capixabas são apenas consultados.
Para minimizar os problemas causados pela fragmentação e melhorar o tempo de resposta geral, podemos dividir uma tabela em diversas partições, cada uma ocupando uma Tablespace própria. Por exemplo, a tabela Alunos poderia ser criada da seguinte maneira57: create table alunos (matricula number(3) 57
constraint alunos_pk primary key,
O comando seguinte encontra-se também criam-se as Tablespaces.
em
22_Monta_Tabelas_Particoes.sql.
Oracle 9i Fundamental
Lá
302
nome_aluno varchar2(30) constraint alunos_nome_nu not null, tel_aluno varchar2(10), endereco_aluno varchar2(30), cidade_aluno varchar2(20) default 'Rio de Janeiro', uf char(2) default 'RJ' constraint alunos_uf_ch check (uf in ('SP', 'MG', 'RJ', 'ES'))) partition by range (uf) (partition p1 values less than ('L') -- capixabas tablespace capixabas pctused 80 pctfree 5, partition p2 values less than ('Q') -- mineiros tablespace mineiros pctused 80 pctfree 5, partition p3 values less than ('RZ') -- cariocas tablespace cariocas pctused 30 pctfree 55, partition p4 values less than (maxvalue) -- paulistas tablespace paulistas pctused 50 pctfree 35);
Observações •
Para que seja possível criar partições, deve-se checar a presença da opção de particionamento. Isto pode ser comprovado no cabeçalho do SQL*Plus58: Conectado a: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.1.0 – Production
•
As partições representam, na verdade, segmentos. Isto pode ser comprovado pelo comando apresentado em seguida: select segment_name, segment_type, tablespace_name from dba_segments where owner = 'DBAACAD' and segment_type IN ('TABLE','TABLE PARTITION') order by 2;
Saída: SEGMENT_NAME -----------------------------… ALUNOS ALUNOS ALUNOS ALUNOS
•
SEGMENT_TYPE TABLESPACE_NAME ------------------ -----------------TABLE TABLE TABLE TABLE
PARTITION PARTITION PARTITION PARTITION
CAPIXABAS MINEIROS CARIOCAS PAULISTAS
Note com os valores dos parâmetros de utilização de espaço (PCTFREE e PCTUSED) foram estipulados segundo as características de utilização de cada partição.
Uma vez alimentadas as tabelas59, para visualizar os dados de apenas uma partição, poderíamos emitir o comando: select nome_aluno, uf from alunos partition(p2); 58
59
Trata-se do mesmo SQL*Plus Worksheet, porém utilizando uma interface mais rude. Mais detalhes no Apêndice A. Alimente as tabelas utilizando o script 22_Alimenta_Dados.sql.
Oracle 9i Fundamental
303
NOME_ALUNO -----------------------------Tadeu Perseu Luis Eridanus Rios José Neves Gemini
UF -MG MG MG
A inserção ou exclusão de linhas não sofre alterações quando a tabela é particionada; entretanto, devem-se evitar alterações (UPDATE) no campochave da partição, neste caso, UF. Uma nova partição poderia ser acrescentada60: alter table alunos split partition p1 at ('C') into (partition p11 tablespace baianos, partition p12 tablespace capixabas);
Evidentemente, deve-se criar previamente a Tablespace Baianos e também alterar a restrição sobre o campo UF para que aceite alunos da Bahia. Comprovando: select partition_name, tablespace_name from user_tab_partitions where table_name = 'ALUNOS'; PARTITION_NAME TABLESPACE_NAME ------------------------------ ---------------------P2 MINEIROS P3 CARIOCAS P4 PAULISTAS P11 BAIANOS P12 CAPIXABAS
Antes de inserir alunos baianos, devemos reconstruir a chave primária de Alunos: alter table historico drop constraint HISTORICO_aluno_fk; alter table alunos drop constraint alunos_pk; alter table alunos add constraint alunos_pk primary key(matricula); insert into alunos (matricula, nome_aluno, tel_aluno, endereco_aluno, uf, cidade_aluno) values (32, 'Vitória Vulpecula', '322-6432', 'R. do Farol, 100 casa 2', 'BA', 'Salvador'); alter table historico add constraint historico_aluno_fk foreign key (matricula) references alunos (matricula);
Comprovando a inserção: select nome_aluno, uf from alunos partition(p11); NOME_ALUNO UF ------------------------------ -Vitória Vulpecula BA
60
O comando apresentado em seguida, além do que cria a Tablespace para os baianos, encontra-se em 22_Altera_Tabela_Particoes.sql.
Oracle 9i Fundamental
304
Uma partição pode ser excluída sempre e quando não existam referências à tabela: alter table alunos drop partition p11; alter table alunos drop partition p11 * ERRO na linha 1: ORA-02266: chaves exclusiva/primária na tabela referenciadas por chaves externas ativadas
22.8 - Estatísticas Durante a análise de um select, o Otimizador de queries do Oracle precisa decidir rapidamente o melhor caminho. Será que vale a pena utilizar um determinado índice? Ou talvez uma combinação de outros dois? Ou será que uma varredura completa na tabela (Full Table Scan) seria mais adequada? Estas questões giram, invariavelmente, em torno de um ponto crucial: o volume. Se a tabela for grande, utilizam-se índices, senão, prefere-se uma varredura nos próprios dados (isto se não se tratar de uma IOT, já que, neste caso, percorrer a tabela ou o índice da chave primária dá no mesmo). Mas, durante a avaliação de um comando, simplesmente não há tempo de verificar o montante de linhas processadas. Por isso, existem as estatísticas que consistem em números que revelam a distribuição das chaves e a seletividade (quantas vezes uma determinada chave aparece repetida). Estatísticas devem ser geradas após significativas alterações no volume de dados, alteração na estrutura ou em algum índice. A frequência de atualização deve ser compatível com o nível de atualizações de uma tabela, ou seja, tabelas apenas consultadas devem ter suas estatísticas coletadas uma vez preenchidas. Já aquelas tabelas muito alteradas devem ter suas estatísticas atualizadas de forma recorrente. Até a versão 8i o comando responsável pela gerência de estatísticas era o analyze table. A partir da 8i e principalmente na 9i, recomenda-se enfaticamente a utilização do Package embutido DBMS_STATS. Ele coleta e gerencia estatísticas de uma coluna, índice, tabela ou Schema. Imagine que a tabela ALUNOS tenha acabado de ser carregada, entretanto o otimizador parece não saber disto... select num_rows from dba_tables where table_name = 'ALUNOS'; NUM_ROWS ----------
Atualizando as estatísticas: begin Oracle 9i Fundamental
305
dbms_stats.gather_table_stats('dbaacad', 'alunos'); end; /
E agora: select num_rows from dba_tables where table_name = 'ALUNOS'; NUM_ROWS ---------32
Em vez da tabela ALUNOS, poderíamos coletar estatísticas da Materialized View criada recentemente. Há outras rotinas para coleta de estatísticas semelhantes à utilizada anteriormente: • • • •
GATHER_INDEX_STATS GATHER_SCHEMA_STATS GATHER_DATABASE_STATS GATHER_SYSTEM_STATS
Uma forma mais elegante de exibir estatísticas consiste em utilizar a rotina GET_TABLE_STATS:61 create or replace procedure lista_linhas is linhas number; blocos number; media number; begin dbms_stats.get_table_stats ('dbaacad', 'alunos',null, null, null, linhas, blocos, media); dbms_output.put_line('Linhas: ' || to_char(linhas)); dbms_output.put_line('Blocos: ' || to_char(blocos)); end; /
Ativando: execute lista_linhas
Saída: Linhas: 32 Blocos: 5
Outras rotinas desempenham papel semelhante: • • • 61
GET_COLUMN_STATS GET_INDEX_STATS GET_SYSTEM_STATS
A rotina apresentada em seguida se encontra em 22_Lista_Estatisticas.sql.
Oracle 9i Fundamental
306
22.9 - Reorganização Uma proposta marcante da versão 9i consiste em aumentar ao máximo a disponibilidade dos dados, isto é, permitir que o DBA realize suas tarefas de manutenção sem afetar os tempos de acesso às tabelas. Antes da versão 9i, tarefas como alterações na estrutura da tabela (campos, constraints, Triggers, parâmetros de armazenamento, partições etc.), criação de índices ou até mesmo atualização de estatísticas eram impensáveis enquanto houvesse algum usuário acessando dados. Graças ao novo pacote embutido DBMS_REDEFINITION, permite-se minimizar o intervalo de tempo necessário para bloquear a tabela. Deve-se frisar, entretanto, que o processo é de natureza DDL, ou seja, não há como alterar dados presentes na tabela de origem. O desafio consiste em alterar parâmetros de utilização de espaço (PCTFREE, PCTUSED) de uma partição, adicionar uma nova coluna (DATA_NASC), acrescentar um constraint (impedir o cadastro de alunos com menos de 15 ou mais de 100 anos) e desenvolver um trigger (atualiza uma tabela auxiliar) sobre a tabela ALUNOS. Seguiremos o seguinte roteiro: 1. Utilizando a rotina CAN_REDEF_TABLE verificaremos se a tabela em questão pode ser processada. Caso ela não possua chave primária ou faça parte de uma Materialized View, não poderá ser trabalhada por DBMS_REDEFINITION; 2. Criaremos uma tabela intermediária idêntica a ALUNOS. Ela será o alvo das mudanças e quando o processo estiver concluído, tomará o lugar da original; 3. Preencheremos a tabela intermediária com dados a partir da rotina START_REDEF_TABLE; 4. Realizaremos as alterações previstas sobre a tabela intermediária; 5. Sincronizaremos as tabelas original e intermediária. Isto é benéfico para “descarregar” as atualizações de dados ocorridas na principal. Lembrese que centenas de usuários estarão realizando comandos DML (insert, update, delete) sobre a tabela original; 6. Trocaremos a principal pela intermediária. Durante este passo, geralmente curto, a tabela original ficará bloqueada; 7. Eliminaremos a antiga tabela principal.
22.9.1 - Testando Viabilidade do Processo Antes mesmo de iniciar o processo, convém criar uma tabela teste com um subconjunto representativo de linhas e aplicar-lhe os passos seguintes. Isto fará com que eventuais erros que ocorram durante as alterações na tabela possam ser corrigidos. Uma vez “azeitado” o roteiro, pode-se aplicá-lo na tabela de produção. Oracle 9i Fundamental
307
Tendo certeza de que o roteiro será cumprido à risca, iniciamos o processo. Inicialmente, deve-se verificar se ALUNOS pode ser redefinida: exec dbms_redefinition.can_redef_table ('DBAACAD', 'ALUNOS');
Caso nenhum erro surja do comando apresentado, seguimos em frente.
22.9.2 - Criação da Tabela Intermediária Neste passo será criada uma réplica da tabela original denominada INTERIM. Ela deve possuir os mesmos campos, constraints, Triggers, etc. (linhas ainda não). Infelizmente, ela deve estar no mesmo Schema da original, portanto constraints e Triggers devem ser renomeados. O comando de criação, além dos outros utilizados neste tópico, estão no script 22_Redefine_Alunos.sql. Observe os novos nomes de constraints. Perceba que lá existem partições. Inclusive, a criação delas poderia ter acontecido sob patrocínio de DBMS_REDEFINITION.
22.9.3 - Preenchimento dos Dados Uma vez criada a réplica, ela deve receber os dados da principal. Dependendo do volume dos dados, isto pode causar um sério impacto na(s) tablespace(s) hospedeira(s): exec dbms_redefinition.start_redef_table ('DBAACAD', 'ALUNOS', 'INTERIM');
A partir deste momento, quaisquer inserções, atualizações ou exclusões sobre a tabela ALUNOS serão guardadas para que possam ser reaplicadas ao final do processo de redefinição. Caso o volume de transações seja muito extenso, podem-se realizar sincronismos periódicos, como veremos na quinta etapa.
22.9.4 - Novas Características Inicialmente serão alterados os parâmetros de utilização de espaço da partição dos capixabas: alter table interim modify partition p12 pctfree 25 pctused 40;
Observe que a tabela alvo é INTERIM e não ALUNOS! A seguir, acrescentase um novo campo: alter table interim add peso number(3) null;
Um novo constraint: alter table interim add constraint alunos_peso_ch2 check (peso between 20 and 200);
E, finalmente, o trigger: Oracle 9i Fundamental
308
create or replace trigger t_aft_row_Alunos2 after insert on interim for each row declare v_faixa number(3); begin if :new.peso exp help=y Export: Release 9.2.0.1.0 - Production on Sex Jul 5 15:28:47 2002 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Você pode deixar que a Exportação solicite os parâmetros. Para isso, informe o comando comando seguido do seu nome de usuário/senha: Exemplo: EXP SCOTT/TIGER
Ou então poderá controlar como a Exportação será executada entrando com o comando EXP seguido de vários argumentos. Para especificar parâmetros, você usa palavras-chave: Formato: Exemplo:
EXP KEYWORD=valor ou KEYWORD=(valor1,valor2,...,valorN) EXP SCOTT/TIGER GRANTS=Y TABLES=(EMP,DEPT,MGR) ou TABLES=(T1:P1,T1:P2), se T1 for tabela particionada
USERID deve ser o primeiro parâmetro da linha de comandos. Palavra-chave Descrição (Default) Palavra-chave Descrição (Default) -------------------------------------------------------------------------USERID nome de usuário/senha FULL exportar arquivo inteiro (N) ... Exportação encerrada com êxito, sem advertências.
A tabela seguinte explica os parâmetros mais importantes73: Parâmetro
Descrição
USERID
Cadeia de conexão: usuário/senha e @host (quando a conexão acontecer a partir de um Cliente ou existir mais de uma instância no Servidor de Dados). Caso este parâmetro seja omitido, os dados de conexão serão pedidos interativamente.
FILE
Arquivo destino da cópia.
FULL
Indica que o banco completo deve ser exportado. Somente permitido para quem tiver o papel EXP_FULL_DATABASE. Valores possíveis: Y ou N (default).
73
Veja a descrição completa dos parâmetros na documentação do Oracle, manual Utilities (Capítulo 1).
Oracle 9i Fundamental
359
Parâmetro
Descrição
OWNER
Em vez de exportar o banco completo, pode-se escolher um ou mais Schemas.
TABLES
Em vez de exportar o banco completo, ou mesmo um Schema inteiro, pode-se escolher uma ou mais tabelas.
TABLESPACES
Em vez de exportar o banco completo, pode-se escolher uma ou mais Tablespaces.
BUFFER
Quantidade de bytes utilizados para armazenar linhas de tabelas que serão exportadas. O default depende do Sistema Operacional. Sugerido: 64.000.
COMPRESS
Muito utilizado para tabelas que residam em Tablespaces cujo gerenciamento seja baseado no Dicionário de Dados (veja detalhes em 20.3). Este parâmetro faz com que o segmento seja criado em apenas um Extent, fazendo com que fique desfragmentado. Valores possíveis: Y (default) ou N.
ROWS
Informa se as linhas das tabelas devem ser exportadas (Y) ou não (N). O default é Y.
LOG
Grava as mensagens emitidas pela exportação no arquivo indicado por este parâmetro.
TRANSPORT_ TABLESPACE e TTS_FULL_CHE CK
Geram metadados das Tablespaces por transportar (mais detalhes em 25.5).
Perceba que os parâmetros FULL, OWNER, TABLES e TABLESPACES são mutuamente exclusivos
Primeiro Exemplo: exportação completa C:\>exp dbaacad/dbaacad file=e:\backup\completo.dmp full=y log=e:\backup\saida.txt buffer=64000
Observações • • •
Não podem existir quebras de linha na digitação do comando; A instrução anterior poderia residir em um arquivo de lote; Uma visão simplificada da saída seria:
Conectado a: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.1.0 - Production Exportação executada no conjunto de caracteres de WE8MSWIN1252 e no conjunto de caracteres de AL16UTF16 NCHAR Sobre exportar o banco de dados inteiro ... . exportando definições de tablespace . exportando perfis . exportando definições de usuário . exportando funções
Oracle 9i Fundamental
360
. exportando custos de recurso . exportando definições de segmento de rollback . exportando vínculos de banco de dados . exportando números de seqüência . exportando nomes alternativos de diretórios . exportando namespaces de contexto . exportando nomes da biblioteca de função externa . exportando sinônimos do tipo PÚBLICO . exportando sinônimos do tipo privado . exportando definições de tipos de objeto . exportando objetos e ações procedurais de sistema . exportando objetos e ações procedurais anteriores ao esquema . exportando definições de cluster . sobre exportar tabelas de SYSTEM ... via Caminho Convencional ... . . exportando tabela AQ$_INTERNET_AGENT_PRIVS 0 linhas ... . . exportando tabela XCF 0 linhas . . exportando tabela XDF 0 linhas . sobre exportar tabelas de DBAACAD ... via Caminho Convencional ... . . exportando tabela ALUNOS 31 linhas . . exportando tabela CURSOS 10 linhas . . exportando tabela HISTORICO 100 linhas . . exportando tabela INSTRUTORES 10 linhas . . exportando tabela TURMAS 20 linhas . exportando sinônimos . exportando views . exportando restrições referenciais de integridade . exportando procedimentos armazenados . exportando operadores . exportando tipos de índices . exportando índices funcionais, extensíveis e de bitmap . exportando ações contabilizáveis . exportando gatilhos . exportando views materializadas . exportando logs de snapshot . exportando filas de serviço . exportando filhos e grupos de renovação . exportando dimensões . exportando objetos e ações procedurais posteriores ao esquema . exportando tabela histórica do usuário . exportando opções de auditoria default e do sistema . exportando estatística Exportação encerrada com êxito, sem advertências.
exportadas exportadas exportadas exportadas exportadas exportadas exportadas exportadas
Segundo Exemplo: exportação de dois Schemas C:\>exp dbaacad/dbaacad file=e:\backup\schemas.dmp owner=(dbaacad, scott) log=e:\backup\schemas.txt buffer=64000 compress=y
Observação •
Os parênteses são desnecessários caso apenas um Schema seja exportado.
Terceiro Exemplo: exportação de uma Tablespace C:\>exp dbaacad/dbaacad file=e:\backup\users.dmp tablespaces=users log=e:\backup\users.txt buffer=64000 compress=y
Oracle 9i Fundamental
361
Quarto Exemplo: exportação de uma Tabela C:\>exp dbaacad/dbaacad file=e:\backup\alunos.dmp tables=alunos log=e:\backup\alunos.txt buffer=64000 compress=y rows=n
Observações • •
Se houvesse mais de uma tabela, elas deveriam aparecer separadas por vírgulas e a lista delimitada por parênteses; Vê-se que foi exportada apenas a definição da tabela (sem linhas), já que o parâmetro ROWS está como N. O arquivo gerado, ALUNOS.DMP, apesar de possuir um formato proprietário, pode ser aberto com um editor de textos comum (Bloco de Notas, por exemplo).
25.2.2 - Importação A importação somente faz sentido se houver um arquivo produzido pelo utilitário de exportação. Recomenda-se sua utilização quando houver necessidade de transportar um Schema, ou uma dada tabela, ou mesmo Tablespace. O utilitário de exportação IMP, do tipo linha de comando, pode ter sua sintaxe investigada da seguinte maneira: C:\>imp help=y Import: Release 9.2.0.1.0 - Production on Dom Jul 7 09:18:34 2002 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Você pode deixar que a Importação emita um prompt solicitando os parâmetros, entrando com o comando comando seguido do seu nome de usuário/senha: Exemplo: IMP SCOTT/TIGER
Ou então, você pode controlar a forma como a Importação será executada entrando com o comando IMP seguido de vários argumentos. Para especificar parâmetros, você usa palavras-chave: Formato: IMP KEYWORD=valor ou KEYWORD=(valor1,valor2,...,valorN) Exemplo: IMP SCOTT/TIGER IGNORE=Y TABLES=(EMP,DEPT) FULL=N ou TABLES=(T1:P1,T1:P2), se T1 for tabela particionada USERID deve ser o primeiro parâmetro da linha de comandos. Palavra-chave Descrição (Default) Palavra-chave Descrição (Default) -----------------------------------------------------------------------------USERID nome de usuário/senha FULL importar arquivo inteiro (N) ... Importação encerrada com êxito, sem advertências.
Oracle 9i Fundamental
362
A tabela seguinte explica os parâmetros mais importantes74: Parâmetro
Descrição
USERID
Cadeia de conexão: usuário/senha e @host (quando a conexão acontecer a partir de um Cliente ou existir mais de uma instância no Servidor de Dados). Caso omitido, será pedido.
FILE
Arquivo origem da cópia.
FULL
Indica que o banco completo deve ser importado. Somente permitido para quem tiver o papel IMP_FULL_DATABASE. Valores possíveis: Y ou N (default).
FROMUSER
Indica Schema origem.
TOUSER
Schema destino.
TABLES
Lista de tabelas a serem importadas.
TABLESPACES e TTS_OWNERS
Utilizados em conjunto com TRANSPORT_TABLESPACE = Y. Mais detalhes em 25.5.
SHOW
Lista conteúdo do arquivo origem. Apenas utilizável com FULL=Y, FROMUSER, TOUSER e TABLES.
IGNORE
Indica se a importação não deve ser interrompida ao primeiro erro (Y). Default: N.
COMMIT
Indica se deve ser realizado um COMMIT quando a quantidade de bytes transferida atingir o indicado no parâmetro BUFFER (Y), ou ao final de cada tabela importada (N). Apesar de ser N o valor padrão, recomenda-se enfaticamente utilizar Y.
BUFFER
Quantidade de bytes utilizada para armazenar linhas de tabelas que serão exportadas. O default depende do Sistema Operacional. Sugerido: 64.000.
ROWS
Informa se as linhas das tabelas devem ser importadas (Y) ou não (N). O default é Y.
LOG
Grava as mensagens emitidas pela importação no arquivo indicado por este parâmetro.
Perceba, mais uma vez, que os parâmetros FULL, FROMUSER/TOUSER, TABLESPACES e TABLES não devem ser utilizados no mesmo comando. Os exemplos seguintes complementam os criados no item anterior, 25.2.1 Exportação.
Primeiro Exemplo: mostra o conteúdo do arquivo por importar Supondo que no quarto exemplo não tenha sido utilizado o parâmetro ROWS=N, comando seguinte proporciona uma forma mais confiável de extrair a definição da tabela ALUNOS: 74
Veja a descrição completa dos parâmetros na documentação do Oracle, manual Utilities (Capítulo 2).
Oracle 9i Fundamental
363
C:\>imp dbaacad/dbaacad file=e:\backup\alunos.dmp tables=alunos show=y log = e:\backup\imp_alunos.txt
Observações A instrução não realiza importação alguma; Veja como ficaria o arquivo IMP_ALUNOS.TXT: Conectado a: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.1.0 - Production Arquivo de exportação criado por EXPORT:V09.02.00 via caminho convencional importação realizada nos conjuntos de caracteres WE8MSWIN1252 e NCHAR AL16UTF16 . importando objetos de DBAACAD para DBAACAD "CREATE TABLE "ALUNOS" ("MATRICULA" NUMBER(3, 0), "NOME_ALUNO" VARCHAR2(30) " "CONSTRAINT "ALUNOS_NOME_NU" NOT NULL ENABLE, "TEL_ALUNO" VARCHAR2(10), "END" "ERECO_ALUNO" VARCHAR2(30), "CIDADE_ALUNO" VARCHAR2(20), "UF" CHAR(2)) PCTF" "REE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1" " FREELIST GROUPS 1) TABLESPACE "USERS" LOGGING NOCOMPRESS" " ALTER TABLE "ALUNOS" MODIFY ("CIDADE_ALUNO" DEFAULT 'Rio de Janeiro')" " ALTER TABLE "ALUNOS" MODIFY ("UF" DEFAULT 'RJ' )" . . saltando a tabela "ALUNOS" "CREATE UNIQUE INDEX "ALUNOS_PK" ON "ALUNOS" ("MATRICULA" ) PCTFREE 10 INIT" "RANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 FREELISTS 1 FREELIST GROUPS 1) TA" "BLESPACE "USERS" LOGGING" "ALTER TABLE "ALUNOS" ADD CONSTRAINT "ALUNOS_UF_CH" CHECK (uf in ('SP', 'MG'" ", 'RJ', 'ES')) ENABLE NOVALIDATE" "ALTER TABLE "ALUNOS" ADD CONSTRAINT "ALUNOS_PK" PRIMARY KEY ("MATRICULA") " "USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 FREELI" "STS 1 FREELIST GROUPS 1) TABLESPACE "USERS" LOGGING ENABLE " "ALTER TABLE "ALUNOS" ENABLE CONSTRAINT "ALUNOS_UF_CH"" Importação encerrada com êxito, sem advertências.
Segundo Exemplo: importação completa C:\>imp dbaacad/dbaacad file=e:\backup\completo.dmp full=y log=e:\backup\saida.txt buffer=64000 ignore=y commit=y;
Observações • • •
Não podem existir quebras de linha na digitação do comando; A instrução anterior poderia residir em um arquivo de lote; Apesar de ser Y o default para o parâmetro IGNORE, resolveu-se utilizá-lo para enfatizar sua importância. Ele concede mais flexibilidade ao comando, já que não é necessário que o banco destino esteja completamente vazio.
Terceiro Exemplo: importação de um Schemas C:\>imp dbaacad/dbaacad file=e:\backup\schemas.dmp fromuser=dbaacad touser=monick log=e:\backup\imp_schemas.txt buffer=64000 ignore=y commit=y
Oracle 9i Fundamental
364
Observação •
Para que o comando anterior obtenha êxito, deve ter sido criado previamente um Schema denominado MONICK que possua, no mínimo, os papéis predefinidos CONNECT e RESOURCE.
Quarto Exemplo: importação de uma Tabela Suponha que a tabela HISTORICO tenha sido eliminada inadvertidamente. Poderíamos recuperá-la a partir do arquivo gerado pela exportação do terceiro exemplo de 25.2.1: C:\>imp dbaacad/dbaacad file=e:\backup\users.dmp tables=historico log=e:\backup\imp_historico.txt buffer=64000 ignore=y commit=y
Observação •
Note que a importação da tabela HISTORICO não precisa vir de um arquivo gerado pela única exportação desta tabela. Também poder-se-ia trazê-la de uma exportação completa.
25.3 LogMiner A funcionalidade LogMiner (introduzida na versão 8i, mas muito melhorada na 9i) permite extrair informações dos Redo Log Files ou Archived Redo Log Files. Além das possibilidades oferecidas para Auditoria (é possível saber como estavam os dados antes de um dado momento), faz também com que pequenos erros de usuário possam ser revertidos sem a necessidade de importações ou paradas de Banco. Antes que a busca comece, entretanto, deve-se cumprir duas exigências básicas: criar um dicionário de dados e avisar que dados complementares devem ser registrados a partir desse momento. Normalmente, gera-se o dicionário de dados como um arquivo externo (caminho indicado pelo parâmetro de inicialização UTL_FILE), que deve ser regularmente copiado para uma área de back up. Caso UTL_FILE esteja nulo, algum valor deve receber75: alter system set utl_file_dir = 'E:\oracle\admin\Acad9\udump' scope=spfile;
Infelizmente, o parâmetro recém-alterado não é dinâmico, o que significa a obrigatoriedade em fechar a instância e reabri-la para que a mudança surta efeito. Veja como fazê-lo relembrando o item 19.4.
75
O comando seguinte somente faz sentido caso a instância tenha sido aberta com um arquivo de parâmetros binário (SPFILE.ORA). Caso não tenha sido, altere o arquivo de parâmetros texto (INIT.ORA). Para saber mais, consulte o Capítulo 19.
Oracle 9i Fundamental
365
Uma vez fechada e reaberta a instância, pode-se enfim criar o desejado Dicionário de Dados para o LogMiner. Ele conterá uma imagem dos metadados do Banco. Conectado como SYS, faça76: execute dbms_logmnr_d.build('dictionary.ora', 'e:\oracle\admin\acad9\udump', options => dbms_logmnr_d.store_in_flat_file);
Apenas certifique de que nenhum comando DDL esteja sendo executado no momento da criação do Dicionário de Dados, pois ele será desconsiderado para o LogMiner. Como já dito, periodicamente deve-se resguardar DICTIONARY.ORA e uma nova versão gerada após alterações significativas nos metadados.
Atenção •
Caso não se diga nada em contrário, as tabelas destinadas ao LogMiner serão criadas na Tablespace SYSTEM. Para não sobrecarregá-la, recomenda-se utilizar outra Tablespace, o que pode ser obtido com o comando: execute dbms_logmnr_d.set_tablespace('example');
A segunda exigência básica consiste em avisar ao Oracle Server que mais infor-mações devem ser gravadas nos Redo Log Files para que o LogMiner possa executar seu trabalho: alter database add supplemental log data;
Este comando permite algumas variações nas quais é possível aumentar a quantidade de informações a ser gravada nos Redo Log Files, objetivando melhorar o trabalho do LogMiner. Entretanto, isto pode causar problemas de desempenho. A partir deste ponto, o trabalho consiste em: 1. Informar o arquivo de busca (Redo ou Archived); 2. Disparar a busca; 3. Realizar a consulta de comandos e, eventualmente, disparar outros que desfaçam o efeito deles, sempre e quando não sejam do tipo DDL (create, alter, truncate etc.). Neste caso pode-se, no máximo, saber quem disparou o comando; 4. Encerrar a busca. Como exemplo, faremos uma atualização desastrada: update cursos set preco = 0; commit;
76
Os comandos deste item estão em 25_Testa_LOGMNR.sql.
Oracle 9i Fundamental
366
O primeiro passo consiste em identificar o Redo Log File em que aconteceu o fatídico comando e cadastrá-lo junto ao LogMiner. Imagine que tenha sido o Redo Log File corrente: select member from v$log v inner join v$logfile l on l.group# = v.group# where v.status = 'CURRENT';
E uma suposta saída: MEMBER ------------------------------------------------E:\ORACLE\ORADATA\ACAD9\REDO03.LOG
Agora já é possível informar ao LogMiner onde deve procurar. Conectado como SYS, faça: execute dbms_logmnr.add_logfile (options => dbms_logmnr.new, Logfilename => 'E:\ORACLE\ORADATA\ACAD9\REDO03.LOG');
Opcionalmente, pode-se fornecer mais um arquivo de busca: execute dbms_logmnr.add_logfile (options => dbms_logmnr.addfile, Logfilename => 'E:\ORACLE\ORADATA\ACAD9\REDO01.LOG');
E caso não seja mais necessário, retirá-lo: execute dbms_logmnr.add_logfile (options => dbms_logmnr.removefile, Logfilename => 'E:\ORACLE\ORADATA\ACAD9\REDO01.LOG');
Ainda como SYS, dispara-se a busca: execute dbms_logmnr.start_logmnr (DictFileName => 'E:\oracle\admin\Acad9\udump\dictionary.ora', StartTime => to_date('7-Jul-2002 16:00:00', 'DD-MON-YYYY HH24:MI:SS'), Endtime => to_date('7-Jul-2002 18:00:00', 'DD-MON-YYYY HH24:MI:SS'));
Este comando poderia não consultar o Dicionário de Dados gerado como arquivo externo e sim acessar dinamicamente os metadados mais atuais: execute dbms_logmnr.start_logmnr (Options => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG, StartTime => to_date('7-Jul-2002 16:00:00', 'DD-MON-YYYY HH24:MI:SS'), Endtime => to_date('7-Jul-2002 18:00:00', 'DD-MON-YYYY HH24:MI:SS'));
O inconveniente em desconsiderar o arquivo externo está em não poder acessar comandos que acessaram tabelas que existiam quando o arquivo foi gerado e agora não existem mais. Consultando a base gerada77: select sql_undo from v$logmnr_contents where username = 'DBAACAD' and seg_name = 'CURSOS';
E a saída: SQL_UNDO 77
Liste a estrutura de V$LOGMNR_CONTENTS. Perceba que o campo SQL_REDO é uma imagem do comando desastrado.
Oracle 9i Fundamental
367
-------------------------------------------------------------------------update "DBAACAD"."CURSOS" set "PRECO" = '800' where "PRECO" = '0' and ROWID = 'AAAHZxAAJAAAAB2AAA'; … 10 linhas selecionadas.
Perceba que os comandos listados podem ser executados para que os efeitos da operação desastrada sejam revertidos. Para encerrar uma sessão de buscas com LogMiner, faça: execute dbms_logmnr.end_logmnr;
Este salutar comando fará com que o LogMiner libere recursos previamente alocados. Antes de começar uma nova busca, devem-se recadastrar os arquivos Redo ou Achive.
25.4 DBMS_FLASHBACK Como visto no Capítulo 21, pode-se utilizar o pacote embutido DBMS_FLASHBACK para realizar recuperações relativamente recentes. Ele trabalha consultando Segmentos de Undo cujos dados podem ser preservados por tantos segundos quanto indicado no parâmetro UNDO_RETENTION. Como não há certeza absoluta de que os dados necessários estejam nos Segmentos de Undo78, não se deve confiar cegamente nesse pacote. O ideal seria combinar sua funcionalidade com outras, para que as probabilidades de recuperação sejam máximas. Assim, deve-se garantir a execução de exportações lógicas que garantam o resguardo de dados críticos em um intervalo próximo ao determinado por UNDO_RETENTION. Por exemplo, caso estime-se o tempo de retenção em cinco horas (18.000 segundos), poder-se-ia agendar uma exportação lógica das tabelas regularmente alteradas para, digamos, de quatro em quatro horas. O problema das exportações lógicas está em seu caráter estático, ou seja, se às onze da manhã realizou-se uma cópia de uma determinada tabela permanentemente alterada e aconteceu uma perda às duas, o arquivo gerado pelo EXP não terá utilidade caso sejam necessárias as alterações ocorridas nestas três horas. Para estas situações, recomenda-se a técnica de Log Miner, que, como visto, extrai dos Redo Log Files (ou Archived Redo Log Files) os comandos que permitam reverter os efeitos da perda, sempre e quando não sejam do tipo DDL. Perdas que causem indisponibilidade da instância (quebra de um disco, por exemplo) não podem ser sanadas com DBMS_FLASHBACK. Pode-se voltar um Cold Backup ou, melhor, um Hot Backup, que consiste nos arquivos de 78
Lembre-se que será requisitada a área destinada ao trabalho de DBMS_FLASHBACK quando não houver possibilidade de expansão física dos Segmentos de Undo. Também será impossível qualquer recuperação, caso a tabela tenha sofrido um comando DDL (Alter, Truncate).
Oracle 9i Fundamental
368
dados e dos Archived Redo Log Files. Melhor do que Cold ou Hot, entretanto, seria utilizar o Recovery Manager, que proporciona recuperações mais ágeis, já que as cópias produzidas tendem a ser mais otimizadas. Como se vê, o Oracle oferece vários recursos de recuperação de dados e o pacote DBMS_FLASHBACK é apenas um deles. Recomenda-se enfaticamente ao DBA conhecê-los todos, para que, em momentos de crise, possa escolher a técnica mais adequada, ou seja, que garanta o menor tempo possível de inatividade no Banco.
25.5 - Tablespaces Transportáveis A partir da versão 8i introduziu-se a facilidade de copiar dados entre instâncias mais rapidamente do que utilizando exportação/importação. O processo consiste em: 1. Identificar uma ou mais Tablespaces que possam ser transportadas; 2. Verificar se o transporte é possível. Por exemplo, não se pode levar uma Tablespace contendo uma tabela que possua uma chave primária cujo índice resida numa segunda Tablespace. Veremos um procedimento que checa a viabilidade de transporte; 3. Fazer com que a(s) Tablespace(s) na origem seja(m) apenas de leitura; 4. Copiar fisicamente os arquivos que constituam a(s) Tablespace(s) origem para o diretório em que serão anexados à instância destino; 5. Exportar metadados utilizando EXP; 6. Na instância destino, importar metadados com IMP; 7. Voltar Tablespaces, na origem e no destino, à modalidade de gravação. Antes de começar os trabalhos, observe o seguinte: Origem e destino devem ser da mesma plataforma, isto é, não é possível copiar uma Tablespace sob Unix para Windows2000 e vice-versa; Se origem e destino tiverem tamanhos de bloco diferentes, o destino deve possuir algum valor para o parâmetro DB_XX_CACHE_SIZE, em que XX representa o tamanho do bloco da origem. Neste item faremos uma cópia da Tablespace USERS da instância ACAD9 para outra homônima em TESTE79. Para tornar o exemplo mais interessante, suponha que a instância origem possua tamanho de bloco padrão igual a 8KB, enquanto que na destino seja de 4KB. Caso não exista uma área na memória de TESTE para blocos de 8KB, temos que criá-la: 79
Supõe-se que a instância TESTE já tenha sido criada e não possua a Tablespace USERS. Caso ela não exista, peça ao seu DBA para criá-la ou consulte capítulo 26 para criar Bancos de Dados e realizar acessos a mais de uma instância.
Oracle 9i Fundamental
369
alter system set db_8k_cache_size = 524288 scope=spfile;
O comando anterior destinou 512KB para blocos de 8KB, mas exige que a instância seja fechada e novamente aberta. Para certificar-se que uma dada Tablespace pode ser transportada, ela deve ser submetida à procedure TRANSPORT_SET_CHECK. Conectado como SYS em ACAD9, executa-se o comando: execute dbms_tts.transport_set_check ('USERS', TRUE);
Ele checa a viabilidade do transporte (o segundo argumento informa que constraints devem ser verificadas também). Para consultar o “log” da rotina anterior, faça: select * from transport_set_violations;
Caso não existam empecilhos ao transporte, impediremos que USERS sofra gravações enquanto durar o processo de transporte: alter tablespace users read only;
A seguir, a cópia física. Primeiro conecte-se como DBA ao SQL*Plus80 (no ambiente Windows, geralmente pode ser encontrado via Start, Programs, Oracle - OraHome90, Application Development, SQL Plus) e execute o comando sem quebra de linha81: host copy E:\oracle\oradata\Acad9\USERS01.DBF e:\oracle\oradata\teste\users01.dbf
Ele fará com que o arquivo físico que constitui a Tablespace USERS seja copiado. Note que poderiam ser vários, caso houvesse mais de uma Tablespace por transportar, ou USERS possuísse mais de um Data File. O passo seguinte consiste em gerar metadados: C:\> exp transport_tablespace=y tablespaces=users file=e:\backup\def_users.dmp
Antes de prosseguir, duas observações relevantes: • A variável de ambiente ORACLE_SID deve receber o valor ACAD9. No Windows2000, execute o programa regedit, localize-a e alterea. Isto fará com que não seja necessário utilizar o host string na chamada ao EXP; • A geração de metadados deve acontecer obrigatoriamente em uma conexão SYS. E você já sabe que toda conexão com SYS deve ser como AS SYSDBA, portanto, uma vez digitado o comando anterior, será pedido um nome de usuário, ao qual deve-se responder como: Sys/senha as sysdba
80
81
Essencialmente SQL*Plus é a já conhecida SQL*Plus Worksheet, porém de uma forma um pouco mais rústica. Historicamente, sempre foi muito utilizada. Veja algumas dicas de utilização no Apêndice A. Por favor, ajuste o comando a seguir para que faça sentido em seu ambiente.
Oracle 9i Fundamental
370
Uma vez gerados os metados com sucesso, USERS em ACAD9 já pode ser novamente gravada: alter tablespace users read write;
E que venha a importação: C:\> imp transport_tablespace=y file=e:\backup\def_users.dmp datafiles= e:\oracle\oradata\teste\users01.dbf, tablespaces = users tts_owners = (dbaacad, monick) fromuser = (dbaacad, monick) touser = (dbateste, monick)
Cuja saída seria: Import: Release 9.2.0.1.0 - Production on Qua Jul 10 12:49:17 2002 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. Nome do usuário: sys/senha as sysdba Conectado a: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production With the Partitioning, OLAP and Oracle Data Mining options JServer Release 9.2.0.1.0 Production Arquivo de exportaτπo criado por EXPORT:V09.02.00 via caminho convencional Prestes a importar metadados do(s) tablespace(s) transportável... importação realizada nos conjuntos de caracteres WE8MSWIN1252 e NCHAR AL16UTF16 . importando objetos de DBAACAD para DBATESTE . importando objetos de MONICK para MONICK . importando objetos de DBAACAD para DBATESTE . importando objetos de MONICK para MONICK . importando objetos de DBAACAD para DBATESTE Sobre ativação de restrições... Importação encerrada com êxito, sem advertências.
Perceba que: • A variável de ambiente ORACLE_SID deve ter seu valor alterado para TESTE; • O parâmetro TTS_OWNERS informa os donos de objetos na Tablespace original; • Graças à dupla FROMUSER/TOUSER, pode-se fazer o mapeamento de usuários; • DBATESTE e MONICK já devem existir em TESTE. Não se esqueça que em TESTE, USERS ainda está como READ ONLY.
25.6 - Cold Backup A maneira mais simples e, freqüentemente, mais segura de realizar uma cópia consiste em fechar a instância nas formas normal (melhor) ou imediata; copiar TODOS os arquivos constituintes (Data Files, Redo Log Files, temporários, controle, parâmetros e senhas) para um local seguro e depois abri-la novamente. Quando se fecha uma instância de maneira normal, garante-se que os dados estão consistentes e não existem anomalias internas, muito comuns Oracle 9i Fundamental
371
após fechamentos abruptos. Em casos extremos, pode ser impossível abrir um Banco após um shutdown abort. Se por um lado este processo é simples, ele não garante que os dados estarão totalmente atualizados, já que, em caso de recuperação, será perdido o trabalho realizado entre o Cold e o momento da perda. Recomenda-se ter à mão um script, que deve ser atualizado a cada novo arquivo inserido, a ser executado pelo SO e contendo comandos de cópia de todos os arquivos. Analise o conteúdo de 25_Gera_Cold.sql: set echo off pages 0 feed off spool E:\Usuarios\Eduardo\LivroO9\Scripts\ParteIII\cold.bat select 'copy '|| name || ' e:\cold ' from v$datafile; select 'copy '|| name || ' e:\cold ' from v$controlfile; select 'copy '|| name || ' e:\cold ' from v$tempfile; select 'copy '|| member || ' e:\cold ' from v$logfile; select 'copy E:\oracle\database\SPFILEACAD9.ORA e:\cold' from dual; select 'copy E:\oracle\database\PWDACAD9.ORA e:\cold' from dual; spool off
Quando executado, criará um arquivo de lote, COLD.BAT, contendo os comandos de cópia necessários. Quando houver necessidade de efetuar uma recuperação a partir de um Cold, basta inverter o processo, ou seja, com a instância fechada copiar os arquivos desde a área de backup para as posições originais. Caso se tenha obedecido ao padrão OFA, não se deve esquecer que os arquivos es-tarão em discos diferentes. Observe que NENHUM data file pode ser omitido. Caso falte um, o Banco não po-derá ser reaberto, assim o Script 25_Gera_Cold.sql deve ser executado sempre que houver alterações na quantidade de arquivos do Banco. Rama Velpuri e Anand Adkoli, no imprescindível ORACLE 8 BACKUP & RECOVERY HANDBOOK, na página 459, sugerem que os arquivos de log não sejam copiados, já que poderão ser reconstruídos no momento da abertura do banco (opção RESETLOGS). Contudo, há um senão: esta opção somente funciona se tiver acontecido um recovery (essencialmente aplicaram-se transações que constavam nos Archived Logs), fato que raramente ocorre ao voltar um Cold. Para “zerar” o Redo Log File corrente, faça: alter database clear logfile group n
Onde n representa o Redo Log File corrente.
25.7 - Hot Backup 25.7.1 - Modo ArchiveLog O Banco estar em modo ArchiveLog significa que o processo ARCH está cons-tantemente lendo os Redo Log Files inativos e copiando-os para outro local. Isto per-mitirá operações de cópia enquanto o Banco estiver aberto, o que garante dados mais atualizados. Desta forma, um Redo Log File Oracle 9i Fundamental
372
somente pode ser reutilizado quando o ARCH o tiver liberado. Deve--se notar que cada arquivo produzido será uma cópia fiel de algum Redo Log File. O aumento de segurança é notável: mesmo que a instância seja terminada de forma anormal, o modo ArchiveLog não é retirado, pois esta informação fica nos Control Files. Existem situações, contudo, em que não se recomenda a utilização do Modo ArchiveLog. Por exemplo, em ambientes de desenvolvimento ou em Bancos que recebam seus dados a partir de uma aplicação externa. Neste caso, para remediar uma perda, bastaria refazer a última carga. Em caso de ocorrerem problemas com o modo ArchiveLog, deve-se consultar ime-diatamente o arquivo de alertas (ALERT_sid.LOG). O espaço em disco utilizado pelo ARCH pode acabar, podem ter ocorrido problemas físicos no disco, o processo ARCH pode ter sido derrubado, etc. Para habilitar o Modo ArchiveLog, deve-se efetuar seis passos: Alterar os parâmetros log_archive_start (true), log_archive_dest (diretório de destino para os arquivos gravados por ARCH) e log_archive_format. Por exemplo82: alter system set log_archive_start = true scope = spfile; alter system set log_archive_dest = '%ORACLE_HOME%\database\archive' scope = spfile;
Fechar o Banco. Abrir o Banco parcialmente: startup mount
Cuja saída poderia ser: Instância ORACLE iniciada. Total System Global Area 72424008 bytes Fixed Size 453192 bytes Variable Size 58720256 bytes Database Buffers 12582912 bytes Redo Buffers 667648 bytes Banco de dados montado.
Habilitar o Modo ArchiveLog: alter database archivelog;
Disparar o processo ARCH: archive log start;
Abrir o Banco: alter database open;
82
Caso não se esteja utilizando o arquivo binário de parâmetros, deve-se alterar o correspondente INIT.ORA
Oracle 9i Fundamental
373
Para confirmar a operação: archive log list;
E a saída: Modo log de banco de dados Arquivamento Arquivamento automático Destino de arquivamento e:\oracle\database\archive A seqüência de log on-line mais antiga Próxima seqüência de log a arquivar Seqüência de log atual
Modo de Ativado 23 25 25
Outra forma: select name, log_mode, checkpoint_change# from v$database; NAME LOG_MODE CHECKPOINT_CHANGE# --------- ------------ -----------------ACAD9 ARCHIVELOG 1368680
Para desabilitar o Modo ArchiveLog, devem-se efetuar o processo inverso: • Alterar os parâmetros log_archive_start (false); • Fechar o Banco; • Abri-lo em estado Mount; • Emitir o comando alter database noarchivelog; • Abrir o Banco.
25.7.2 - Hot Backup Estando o Banco em Modo ArchiveLog, o backup pode acontecer sem indisponibilizar a Instância. A cópia é feita em nível de Tablespaces, que podem continuar sendo acessadas. Evidentemente, esta operação deve, preferencialmente, acontecer em horários de pouca atividade no Banco. O roteiro é o seguinte: a. Cópia física das Tablespaces, inclusive SYSTEM: alter tablespace nome begin backup; Copiar fisicamente arquivos que constituem a Tablespace para o diretório destino; alter tablespace nome end backup; b. Cópia física dos Archived Redo Log Files: Interrupção momentânea do Modo ArchiveLog; Cópia dos Archived Redo Log Files; c. Cópia física dos Control Files. Durante o processo de cópia, o Servidor encarrega-se de não gravar diretamente na Tablespace. Recomenda-se não fazer essa operação em mais de uma Tablespace simultaneamente.
Oracle 9i Fundamental
374
O arquivo 25_Hot.sql fornece um exemplo de backup para o banco original. Ativa-se o script pelo arquivo 25_FazHot.bat83 rem script que realiza hot backup rem rem conexão rem connect / @acad9 as sysdba rem rem limpa hot velho rem host del /Q e:\hot\*.* rem rem copia arquivos de tablespaces rem host echo SYSTEM alter tablespace SYSTEM begin backup; host copy E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF e:\hot alter tablespace SYSTEM end backup; host echo UNDOTBS1 alter tablespace UNDOTBS1 begin backup; host copy E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF e:\hot alter tablespace UNDOTBS1 end backup; host echo USERS alter tablespace USERS begin backup; host copy E:\ORACLE\ORADATA\ACAD9\USERS01.DBF e:\hot alter tablespace USERS end backup; …demais Tablespaces alter system switch logfile; rem rem copia archived redo log files rem host echo archived redo log files archive log stop; host copy E:\oracle\database\archive\*.* e:\hot archive log start; rem rem copia control files rem host echo Control File alter database backup controlfile to 'e:\hot\controlfile.bak'; rem exit rem FIM
Observações •
83
Existe muita controvérsia quanto ao momento mais adequado para eliminar Archived Redo Log Files. Teoricamente, uma vez realizado o Hot Backup, os Archived Files criados antes do início
Sempre deve-se evitar a criação de scripts contendo senhas; daí a necessidade de realizar conexões autenticadas pelo SO (mais detalhes em 24.6).
Oracle 9i Fundamental
375
• •
•
do backup poderiam ser eliminados. Entretanto, pode acontecer uma fatalidade: o hot backup recém-realizado pode se corromper ou simplesmente perder-se. Qual seria a saída? Simples-mente recuperar o Hot anterior com todos os Archived Redos gerados depois dele, fato que seria impossível caso eliminássemos Archived Redos a cada Hot. Portanto, a regra geral consiste em nunca perder Archived Redo Log Files!84. Caso sejam acrescentados novos Data Files, esse arquivo deve ser atualizado. Perceba que não consta no Script a Tablespace Temporária85. Isto não chega a ser um problema, já que, caso se perca a Tablespace temporária, outra pode ser criada. A mesma restrição aplica-se a Tablespaces que estejam bloqueadas para gravação (READ ONLY). O conteúdo do arquivo que invoca o backup (25_fazhot.bat) pode ser o seguinte: sqlplus /nolog @25_hot.sql > e:\saida.txt
Como veremos em breve, a recuperação a partir de um Hot Backup baseiase no Arquivo de Controle mais recente. Daí a importância de existirem várias cópias, espalhadas por vários discos. Relembre o Capítulo 19 (item 19.1.2): graças ao parâmetro CONTROL_FILES podemos garantir essas cópias. Uma ótima idéia seria agendar a execução do arquivo anterior para que ocorra em horários prefixados. No Windows 2000, tarefas podem ser agendadas via Start, Programs, Accessories, System Tools, Scheduled Tasks.
25.7.3 - Recuperação a partir de um Hot Backup Recuperação (recovery) significa fazer com que os arquivos de um Banco de Dados estejam em sincronia com seu Arquivo de Controle. Isto acontece graças ao SCN (System Change Number) presente nos cabeçalhos dos Data Files, bem como no Arquivo de Controle. Como vimos no Capítulo 19, atualizam-se SCNs após a ocor-rência de checkpoints. Uma vez constatada a necessidade de recuperação, devem-se analisar as causas:
84
85
Uma interessante alternativa consiste em utilizar os parâmetros LOG_ARCHIVE_DEST_x, em que X pode variar entre 1 e 10. No Apêndice E, voltaremos a eles. Na verdade isto ocorreu porque a Tablespace em questão possuía Gerenciamento de Extents Local. Se fosse baseado em Dicionário, deveria constar no Script.
Oracle 9i Fundamental
376
Causa
Fazer
Instância derrubada
Nestes casos, a recuperação é automática. O Oracle verifica os arquivos, sincroniza-os e desfaz transações não concluídas. Deve-se analisar o arquivo de alerta para buscar possíveis causas. Basta alterar o parâmetro control_files para que não se faça referência ao arquivo perdido. Caso todos tenham sido perdidos, utilize o Control files comando alter database backup controlfile to trace;86 e, em seguida: create control file;
Disco inacessível devido à corrupção de arquivos:
Data files
Recupere arquivo do último backup, coloque o banco em estado mount, utilize o comando recover database e abra o banco. Eventualmente, o banco pode ser aberto sem um dado arquivo, contanto que ele não possua dados cruciais. Com o banco em estado mount, basta emitir o comando: alter database datafile nome offline drop;
Archived Redo Log Files
Comando inapropriado
Impossível recuperá-los. Devem ser multiplexados ou constar em discos espelhados.
Roteiro: a) Fechar o Banco; b) Recuperar pelo SO os arquivos copiados no último Hot ou Cold Backup; c) Abrir o Banco em estado Mount; d) Ainda no SQL*Plus, usar o comando recover database opção; e) Abrir o Banco reiniciando os logs: alter database open resetlogs. f) Realizar um Cold Backup.
Os Redo Log Files já são naturalmente copiados para Archived Redo Log Files pelo processo ARCH. Além disso, as probabilidades de perdas são menores, já que eles devem ser espelhados para outro disco via multiplexação. Evidentemente, se não tiver sido realizado nenhum backup do tipo HOT, restará apenas o COLD, ainda que ele também possa ser utilizado em conjunto com os Archived Redo Logs, sempre e quando o Banco estiver em Modo ArchiveLog. As opções mais importantes do comando recover database são: 86
Tenha em mente que este comando apaga toda e qualquer informação gravada pelo RMAN, inviabilizando quaisquer recuperações futuras via RMAN. Faça quantas cópias for possível de seu Control File!
Oracle 9i Fundamental
377
• • • •
UNTIL CANCEL: acontecem recuperações até que o DBA cancele; UNTIL TIME: fornecida data/hora limite no formato: ‘YYYY-MMDD:HH24:MI:SS’; UNTIL CHANGE num: número do checkpoint; USING BACKUP CONTROLFILE: indicada quando todos os Control Files tiverem sido perdidos e seja necessário recuperar um do backup.
Em caso de arquivos corrompidos, há ainda mais três possibilidades: • • •
recover tablespace nome recover datafile nome recover logfile nome
25.8 Recovery Manager 25.8.1 - Terminologia Recovery Manager (RMAN) representa a forma mais inteligente de realizar cópias de segurança e recuperações. Trata-se de um programa independente do Oracle Server, porém interage intensamente com ele. No fundo, não passa de um conjunto de comandos de alto nível que lêem e gravam no Control File de um Banco-alvo. Embora possua um aspecto hostil, recomenda-se enfaticamente investir tempo em seu aprendizado. Um dos grandes diferenciais do RMAN em relação aos Hots Backups reside no fato de realizar as operações em nível de bloco em vez de arquivo. Desta forma, ele consegue copiar apenas os blocos que foram alterados desde a última cópia, o que proporciona muito mais velocidade na operação, além de viabilizar a migração de bancos entre plataformas heterogêneas. Antes de conhecermos operações básicas possíveis com RMAN, vale esclarecer alguns termos largamente utilizados pelo utilitário: Termo
Significado
Target Database
Banco de Dados cujo Arquivo de Controle será lido ou gravado para levar a cabo operações de backup ou recuperação.
Recovery Database
Banco de Dados em que serão armazenados os metadados gerados pelo RMAN. Apesar de possível, não deve coincidir com o Target Database. Inclusive, o ideal seria criá-lo em outro Servidor, o que permitiria gerenciar vários Bancosalvo.
Oracle 9i Fundamental
378
Termo
Significado
Recovery Catalog
Metadados (tabelas, visões, procedures) criados no Recovery Database a partir do Arquivo de Controle do Target Database para controlar as operações de cópia e recuperação.
Channel Process
Processo (como definido no Capítulo 19, item 19.3.2) criado no Target Database para efetuar uma cópia ou recuperação. Criado pelo comando allocate channel.
Backup Piece
Arquivo gerado por um backup. Possui formato proprietário e pode ser o resultado da combinação de vários arquivos físicos.
Backup Set
Grupo de Backup Pieces.
Cópia
Resultado de um backup, mas com formato proprietário. Seria como realizar um Hot Backup.
Restore
Copiar um arquivo físico desde o local em que foi gravado o backup até a área de produção.
Recovery
Procedimento consistindo em recuperar blocos perdidos.
Disk Buffer
Áreas de memória alocadas para backup ou restore envolvendo áreas em disco. Durante um backup são alocados para arquivos em disco sendo lidos. Também são utilizados quando o destino do backup estiver em disco. Durante um restore são alocados para arquivos em disco sendo gravados ou lidos, caso o destino do backup esteja em disco.
Tape Buffer
Áreas de memória alocadas para backup ou restore envolvendo áreas em fita. Durante um backup são áreas de memória alocadas para arquivos com destino em fita. Durante um restore são alocados para arquivos sendo lidos em fita.
não
Observações • •
•
O RMAN pode ler vários arquivos simultaneamente para gerar um Backup Piece. Esta técnica chama-se Multiplexing. Dois parâmetros desempenham papéis primordiais durante os trabalhos do RMAN: BACKUP_TAPE_IO_SLAVES (dinâmico) e DBWR_IO_SLAVES (estático). Quando BACKUP_TAPE_IO_SLAVES possuir o valor TRUE, a gravação em fita pode ser assíncrona, ou seja, enquanto os dados estiverem sendo gravados em fita, o Processo Servidor responsável pela interação com a fita pode desempenhar outras tarefas. Outro benefício vem da utilização da SGA (mais especificamente Large Pool Oracle 9i Fundamental
379
•
•
Area, quando houver valor para LARGE_POOL_SIZE), em vez da PGA. Já DBWR_IO_SLAVES implementa acessos assíncronos a disco (mais de um em simultâneo) e somente pode ser utilizado quando o disco sendo processado não suportar operações assíncronas e o valor do parâmetro DB_WRITER_PROCESSES (estático) for maior que um. Também utiliza a SGA em vez da PGA. Quando o destino de Backups for uma fita, deve existir uma ferramenta de terceiros capaz de interagir com o RMAN para viabilizar o acesso. Isto porque o RMAN não é capaz de ler ou gravar diretamente de uma unidade de fita. Na verdade, ele apenas possui uma API genérica (Oracle SBT API) que deve ser configurada na ferramenta de terceiros.
25.8.2 - Preparação Neste item será preparado o ambiente necessário para trabalhar com o RMAN. Assume-se a existência de outra instância, TESTE87, que desempenhará o papel de Recovery Database. Quando gerou-se a instância TESTE, foi automaticamente criado um usuário deno-minado RMAN. Ele já possui os metadados e permissões necessários para interagir com o utilitário RMAN, entretanto sua conta está bloqueada e a senha expirada: connect / @teste as sysdba alter user rman account unlock;
A próxima vez que o usuário RMAN tentar uma conexão, será pedida uma nova senha. Assumindo que o usuário RMAN já tenha validado sua nova senha, o próximo passo consiste em ativar o utilitário de linha RMAN e conectar-se ao que será o Recovery Database: C:\ >rman Recovery Manager: Release 9.2.0.1.0 - Production Copyright (c) 1995, 2002, Oracle Corporation. All rights reserved. RMAN> connect catalog rman/rman@teste conectado ao banco de dados do catálogo de recuperação RMAN>
Observe que o Recovery Catalog já existe e repousa sob domínios do usuário RMAN. Caso seja necessário criar os metadados sob outro usuário, o seguinte comando deve ser aplicado: RMAN> create catalog;
A seguir, deve-se realizar uma conexão ao Target Database: RMAN> connect target dbaacad/dbaacad@acad9 87
Pode ser a mesma utilizada para testar a cópia de Tablespaces entre instâncias, assunto discutido no item 25.5
Oracle 9i Fundamental
380
conectado ao banco de dados de destino: ACAD9 (DBID=492139415) RMAN>
Agora informa-se ao Recovery Catalog que ACAD9 será seu Target Database: RMAN> register database; banco de dados registrado no catálogo de recuperação iniciar ressinc. completa do catálogo de recuperação ressinc. inteira completa RMAN>
A operação apresentada basicamente fez com que o conteúdo do Arquivo de Controle do Target Database fosse transferido para o Recovery Catalog. Pelo SQL*Plus Worksheet , conectado como RMAN na instância TESTE, é possível fazer algumas pesquisas muito interessantes: select db_key, dbid, name from rc_database;
E a saída: DB_KEY DBID NAME ---------- ---------- -------1 492139415 ACAD9
Outra: select name, CREATION_TIME, INCLUDED_IN_DATABASE_BACKUP from rc_tablespace; NAME -----------------------------CWMLITE DRSYS EXAMPLE INDX ODM SYSTEM TOOLS UNDOTBS1 USERS XDB
CREATION -------12/05/02 12/05/02 12/05/02 12/05/02 12/05/02 12/05/02 12/05/02 12/05/02 12/05/02 12/05/02
INC --YES YES YES YES YES YES YES YES YES YES
10 linhas selecionadas.
Observe que as Tablespaces pertencem ao Target Database.
25.8.3 - Backup Voltando ao utilitário RMAN, existem curiosas maneiras de descobrir que um determinado Banco precisa de um backup: RMAN> report need backup days=1; Relatório de arquivos cuja recuperação precisa mais de 1 dias de logs arquivados Arquivo Dias Nome ---- ----- ------------------------------------------1 63 E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF 2 63 E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF 3 63 E:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF
Oracle 9i Fundamental
381
4 5 6 7 8 9 10
63 63 63 63 63 63 63
E:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF E:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF E:\ORACLE\ORADATA\ACAD9\INDX01.DBF E:\ORACLE\ORADATA\ACAD9\ODM01.DBF E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF E:\ORACLE\ORADATA\ACAD9\USERS01.DBF E:\ORACLE\ORADATA\ACAD9\XDB01.DBF
O seguinte comando efetua uma cópia completa do Banco-alvo: Run { Allocate channel ch_1 device type disk format 'e:\backup\%U'; Backup database; Release channel ch_1;}
Cujo resultado seria: RMAN> Run { 2> Allocate channel ch_1 device type disk format 'e:\backup\%U'; 3> Backup database; 4> Release channel ch_1;} canal alocado: ch_1 canal ch_1: sid=17 devtype=DISK Iniciando backup em 14/07/02 canal ch_1: iniciando conjunto de backups do arquivo de dados full canal ch_1: especificando arquivo(s) de dados no conjunto de backups Incluindo SPFILE atual no conjunto de backup incluindo arquivo de controle atual no conjunto de backups fno=00001 name=E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF do arquivo de dados de entrada fno=00002 name=E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF do arquivo de dados de entrada ... fno=00008 name=E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF do arquivo de dados de entrada canal ch_1: iniciando o componente 1 em 14/07/02 canal ch_1: componente 1 finalizado em 14/07/02 handle de componente=E:\BACKUP\01DTI6PH_1_1 comentário=NONE canal ch_1: conjunto de backups concluído, tempo decorrido: 00:02:57 Finalizado backup em 14/07/02 canal liberado: ch_1 RMAN>
Observações •
•
•
88
A instrução run {} indica a existência de um grupo de comandos. Nesse caso específico, deve-se reservar um Channel Process (veja Terminologia), efetuar a cópia completa e liberar recursos previamente utilizados88; No destino foi criado um Backup Piece cujo tamanho resulta bastante menor do que a soma dos tamanhos dos arquivos físicos que o compõem; Caso houvesse mais de um disco destinado a cópias de segurança, poderiam ter sido alocados mais Channel Processes para acelerar a
Na verdade a alocação de Channel Processes não precisaria ser explícita. Veja em 25.8.5 como pré-configurar destinos.
Oracle 9i Fundamental
382
•
cópia (um para cada disco). Neste caso seriam criados dois Backup Pieces, mas, perdendo um, o Backup Set ficaria inviabilizado; Se o destino fosse uma unidade de fita e houvesse uma ferramenta de terceiros configurada para compreender comandos do RMAN, a requisição do Channel Process mudaria para: Allocate channel ch_1 device type sbt;
Após a conclusão do Backup completo, a consulta aos arquivos precisando ser copiados traria o já esperado resultado: RMAN> report need backup days=1; Relatório de arquivos cuja recuperação precisa mais de 1 dia de logs arquivados Arquivo Dias Nome ---- ----- ------------------------------------------RMAN>
E pelo SQL*Plus Worksheet , conectado como RMAN na instância TESTE, também se verifica o sucesso da cópia: select db_id, backup_type, pieces, to_char(start_time, 'dd/mm/yy hh24:mi:ss') momento from rc_backup_set; DB_ID BACKUP_TYPE PIECES MOMENTO ---------- -------------------- ---------- ----------------492139415 D 1 14/07/02 17:20:54
Imagine que após a cópia apresentada tenha-se criado mais uma Tablespace no Target Database: create tablespace avaliacoes datafile 'e:\oracle\oradata\acad9\acadaval.ora' size 10 m;
Para sincronizar o Arquivo de Controle do Target Database e o Recovery Catalog, utiliza-se o comando resync catalog: RMAN> resync catalog; iniciar ressinc. completa do catálogo de recuperação ressinc. inteira completa
Emitindo os comandos de consulta a metadados, como report, também provoca-se o sincronismo (quando houver diferenças): RMAN> report schema at time 'sysdate'89; iniciar ressinc. completa do catálogo de recuperação ressinc. inteira completa Relatório do esquema do banco de dados
89
O comando report schema at time 'sysdate-1'; não traria referência à Tablespace recém-inserida.
Oracle 9i Fundamental
383
File K-bytes ---- ---------1 409600 2 204800 3 20480 4 20480 5 156800 6 25600 7 20480 8 10240 9 25600 10 39040 11 10240
Tablespace -------------------SYSTEM UNDOTBS1 CWMLITE DRSYS EXAMPLE INDX ODM TOOLS USERS XDB AVALIACOES
RB segs ------YES YES NO NO NO NO NO NO NO NO NO
Nome do Arquivo de Dados ------------------E:\…\SYSTEM01.DBF E:\…\UNDOTBS01.DBF E:\…\CWMLITE01.DBF E:\…\DRSYS01.DBF E:\…\EXAMPLE01.DBF E:\…\INDX01.DBF E:\…\ODM01.DBF E:\…\TOOLS01.DBF E:\…\USERS01.DBF E:\…\XDB01.DBF E:\…\ACADAVAL.ORA
A lista de sincronismos efetuados pode ser acompanhada de: select to_char(RESYNC_TIME, 'dd/mm/yy hh24:mi:ss') Momento from rc_resync; MOMENTO ----------------14/07/02 17:18:31 14/07/02 17:24:02
Em vez de realizar uma nova cópia completa do Banco-alvo para resguardar a Tablespace recém-inserida, pode-se apenas copiá-la: Run { Allocate channel ch_1 device type disk format 'e:\backup\%U'; Backup tablespace avaliacoes; Release channel ch_1;}
Além do Target Database completo e de suas Tablespaces, ainda podem-se realizar cópias em nível de Data File, Archived Log, Control File ou Backup Set.
25.8.4 - Recuperação Imagine que tenha sido criada uma nova tabela, AVALIACOES, na Tablespace homônima90: create table avaliacoes (id_aval number(3) not null, data_aval date not null, texto varchar(200)) tablespace avaliacoes;
Suponha também que algumas linhas tenham sido inseridas: insert into avaliacoes values (1, sysdate, 'Boa'); insert into avaliacoes values (1, sysdate, 'Ruim'); insert into avaliacoes values (1, sysdate, 'Excelente'); commit;
Por um contratempo qualquer, o Data File que constituía a Tablespace Avaliacões perdeu-se. Desta forma, a instância- alvo deve ser fechada imediatamente: RMAN> shutdown immediate
90
Os comandos seguintes encontram-se em 25_Gera_Avaliacoes.sql.
Oracle 9i Fundamental
384
banco de dados fechado banco de dados desmontado encerramento de instância Oracle
Para que possa ser aberta em estado MOUNT: RMAN> startup mount conectado ao banco de dados de destino (não iniciado) instância Oracle iniciada banco de dados montado Total da área Global do Sistema 72424008 bytes Fixed Size Variable Size Database Buffers Redo Buffers
453192 58720256 12582912 667648
bytes bytes bytes bytes
Antes de levar a cabo a recuperação, convém checar o estado das cópias disponíveis: RMAN> crosscheck backup91; canal alocado: ORA_DISK_1 canal ORA_DISK_1: sid=13 devtype=DISK componente de backup submetido a verificação cruzada: localizado como 'AVAILABLE' handle de componente de backup=E:\ORACLE\DATABASE\04DTIHQQ_1_1 id reg.=4 marcação=467224413 componente de backup submetido a verificação cruzada: localizado como 'AVAILABLE' handle de componente de backup=E:\BACKUP\05DTIKJM_1_1 id reg.=5 marcação =467227257 componente de backup submetido a verificação cruzada: localizado como 'AVAILABLE' handle de componente de backup=E:\BACKUP\06DTIL0G_1_1 id reg.=6 marcação =467227664 componente de backup submetido a verificação cruzada: localizado como 'AVAILABLE' handle de componente de backup=E:\BACKUP\07DTILBT_1_1 id reg.=7 marcação =467228029 Fez a verificaτπo cruzada de 4 objetos
Executando o comando seguinte: RMAN> recover tablespace avaliacoes;
Teríamos o seguinte erro: Iniciando recover em 14/07/02 utilizando o canal ORA_DISK_1 RMAN-00571: =========================================================== RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS =============== RMAN-00571: =========================================================== RMAN-03002: failure of recover command at 07/14/2002 17:36:29 RMAN-06094: datafile 11 must be restored
Ele aconteceu porque tentamos efetuar uma recuperação sem antes aplicar a restauração (veja terminologia em 25.8.1). Sendo assim, requerese a cópia mais recente do arquivo perdido desde a área de backup até a área de produção: RMAN> restore datafile 11; Iniciando restore em 14/07/02 91
Perceba que não foi especificado nenhum Channel Process para efetuar o comando, assim utiliza-se o padrão ORA_DISK_1. Voltaremos a ele no item 25.8.5.
Oracle 9i Fundamental
385
utilizando o canal ORA_DISK_1 canal ORA_DISK_1: iniciando restauração de conjunto de backups de arquivo de dados canal ORA_DISK_1: especificando arquivo(s) de dados para restauração a partir do conjunto de backups restaurando arquivo de dados 00011 para E:\ORACLE\ORADATA\ACAD9\ACADAVAL.ORA canal ORA_DISK_1: restaurada a parte de backup 1 handle de componente=E:\BACKUP\07DTILBT_1_1 tag=TAG20020714T173349 parâms=NULL canal ORA_DISK_1: restaurar inteiro Finalizado restore em 14/07/02 RMAN>
Caso tivessem sido gerados Archived Redo Log Files desde o momento do backup até a restauração, teríamos que executar o comando recover tablespace avaliacoes para sincronizar a Tablespace com o resto do Banco. Agora deve-se abrir o Target Database para que possamos comprovar o sucesso da recuperação: RMAN> alter database open; banco de dados aberto RMAN>
Comprovando: SQL> connect dbaacad/dbaacad@acad9 Conectado. SQL> select * from avaliacoes;
E a resposta: ID_AVAL ---------1 1 1
DATA_AVA -------14/07/02 14/07/02 14/07/02
TEXTO --------------------Boa Ruim Excelente
Além de um Data File, podem-se restaurar um Control File, o banco completo (opção Database), uma Tablespace ou SPILE. Já a recuperação aplica-se a Data File, Tablespace ou Database (neste caso o Target Database somente pode ser aberto com a opção RESETLOGS, que faz com que os Redo Log Files sejam zerados).
Atenção •
Após abrir um Banco com opção RESETLOGS, deve-se efetuar um backup completo o mais rapidamente possível, já que os Archived Redo Logs anteriores perdem sua utilidade.
Para o RMAN, o fato de um Target Database ter sido aberto com RESETLOGS significa que uma nova incarnation foi criada. O comando seguinte lista todas as “vidas” de um banco-alvo: RMAN> list incarnation; Lista de Encarnações de Banco de Dados Chave de BD Chave Inc Nome do BD ID de BD
SCN de Redefinição de CUR
Oracle 9i Fundamental
386
Hora de Redefinição ------- ------- -------- ---------------- --- ---------- ---------1 15 ACAD9 492139415 NO 190578 30/06/02 1 2 ACAD9 492139415 YES 1686501 14/07/02
A Incarnation key poderia ser utilizada para efetuar recuperações a partir de backups gerados antes da abertura com RESETLOGS. Por exemplo: RMAN> reset incarnation to 15; RMAN> recover database until time “TO_DATE (07/1/02 8:30:00', 'MM/DD/YY HH24:MI:SS')”;
25.8.5 - Automação Uma importante novidade introduzida na versão 9i consiste na possibilidade de armazenar de forma permanente alguns parâmetros que automatizam operações de cópia e recuperação. Por exemplo, pode-se especificar um valor predefinido para os Channel Processes: RMAN> configure channel 1 device type disk format 'e:\backup\%U';
Agora o comando: Backup tablespace avaliacoes;
Fará com que a cópia vá para o diretório previamente determinado. Outra configuração bastante recomendável consiste em automatizar o Backup do Control File. Assim, sempre que houver uma cópia que tenha obtido sucesso, o Control File também será resguardado: RMAN> configure controlfile autobackup on;
A resposta ao pedido de backup da Tablespace Avaliacoes seria: RMAN> Backup tablespace avaliacoes; Iniciando backup em 14/07/02 utilizando o canal ORA_DISK_1 canal ORA_DISK_1: iniciando conjunto de backups do arquivo de dados full canal ORA_DISK_1: especificando arquivo(s) de dados no conjunto de backups fno=00011 name=E:\ORACLE\ORADATA\ACAD9\ACADAVAL.ORA do arquivo de dados de entrada canal ORA_DISK_1: iniciando o componente 1 em 14/07/02 canal ORA_DISK_1: componente 1 finalizado em 14/07/02 handle de componente=E:\BACKUP\09DTIQ3T_1_1 comentário=NONE canal ORA_DISK_1: conjunto de backups concluído, tempo decorrido: 00:00:03 Finalizado backup em 14/07/02 Iniciando Control File and SPFILE Autobackup em 14/07/02 handle de componente=E:\ORACLE\DATABASE\C-492139415-20020714-00 comentário=NONE Finalizado Control File and SPFILE Autobackup em 14/07/02 RMAN>
Para mostrar todos os parâmetros, execute o comando: RMAN> show all; os parâmetros de configuração RMAN são: CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default CONFIGURE BACKUP OPTIMIZATION OFF; # default CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default CONFIGURE CONTROLFILE AUTOBACKUP ON; CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
Oracle 9i Fundamental
387
CONFIGURE CONFIGURE CONFIGURE CONFIGURE CONFIGURE CONFIGURE
DEVICE TYPE DISK PARALLELISM 1; # default DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default CHANNEL 1 DEVICE TYPE DISK FORMAT 'e:\backup\%U'; MAXSETSIZE TO UNLIMITED; # default SNAPSHOT CONTROLFILE NAME TO 'E:\ORACLE\DATABASE\SNCFACAD9.ORA'; # default
RMAN>
Outra forma de automação bastante interessante consiste em criar scripts. Por exemplo: create script completo { backup database plus archivelog; }
O pequeno “programa” anterior efetua a cópia de todos os arquivos do Target Database, inclusive Archived Redo Log Files. Para executá-lo, faça: run { execute script completo; }
Nada impede que possa ser executado a partir do Sistema Operacional. Suponha que a chamada anterior conste em um arquivo denominado AVAL.RMAN. Então: rman TARGET dbaacad/dbaacad@acad9 CATALOG rman/rman@teste @aval.rman
faria com que fosse executado o Script depois das devidas conexões. Uma vez concluída a operação, o controle volta ao SO. Para eliminar um Script, faça: Delete script 'completo';
25.9 - Conclusão As atividades de cópia e recuperação são extremamente críticas, e somente o tempo e os possíveis dissabores causados pelas perdas darão ao DBA a serenidade necessária para executá-las sem traumas. Existem, no entanto, algumas regras que não podem ser desprezadas: a. Se o Banco de Dados não for meramente de teste, nem os dados sejam regularmente importados, sempre utilize o Modo ArchiveLog; b. Seja um especialista em RMAN. Após aprender o conteúdo do item 25.8 e fazer TODOS os exemplos e exercícios propostos, ataque a documentação oficial da Oracle (existem três manuais sobre o assunto: Recovery Manager Reference, Quick Reference e User’s Guide); c. Possua múltiplas cópias de Control Files; d. Multiplexe Log Files; e. Nunca copie arquivos ativos; f. Antes de operações críticas, faça um backup completo.
Oracle 9i Fundamental
388
EXERCÍCIOS Para este Laboratório, supõe-se a existência de duas instâncias (ACAD9 e TESTE). EM ACAD9 deve existir um usuário denominado DBAACAD com status de DBA e possuindo as tabelas do Controle Acadêmico (CURSOS, TURMAS, ALUNOS, INSTRUTORES e HISTORICO).
Atenção Realize os exercícios propostos em seguida em um ambiente de testes, nunca com dados críticos. Nos exercícios 1 e 2, serão praticadas cópias e recuperações lógicas. 1. Exporte TURMAS interativamente. Siga o roteiro: a. Em uma janela de comando, execute o programa EXP sem nenhum argumento; b. Digite usuário e host string separados por @; c. Digite a senha; d. Especifique 64000 para o tamanho do buffer; e. Direcione a saída para TURMAS.DMP. Aceite as demais opções pressionando enter. 2. Elimine os registros da Tabela TURMAS e depois recupere-a logicamente. • Execute o utilitário IMP de forma interativa. 3. Neste exercício você conhecerá uma limitação do LogMiner: a impossibilidade da reversão de um comando DDL. Siga o roteiro: a. Verifique o conteúdo do parâmetro UTL_FILE_DIR. Veja também se existe um Dicionário de Dados para o LogMiner. Caso não exista, ajuste o parâmetro e crie o Dicionário (veja mais detalhes em 25.3); b. Reforce o aviso ao Banco que informações suplementares devem ser gravadas: alter database add supplemental log data;
c. Elimine a tabela HISTORICO; d. Descubra o Redo Log Corrente e, conectado como SYS, cadastreo com: execute dbms_logmnr.add_logfile (options => dbms_logmnr.new, Logfilename => 'redo corrente');
e. Dispare a busca, porém informe que comandos DDL devem ser acompanhados:
Oracle 9i Fundamental
389
execute dbms_logmnr.start_logmnr (DictFileName => 'dicionário', StartTime => momento inicial, Endtime => momento final, Options => DBMS_LOGMNR.DDL_DICT_TRACKING);
f. Execute o comando: select username, sql_undo, sql_redo from v$logmnr_contents operation = 'DDL';
where
Essa consulta permitirá descobrir quem executou um DDL e qual foi ele (campo SQL_REDO). Perceba que SQL_UNDO está nula. Faça um Cold Backup a partir do Script gerado com 25_GERA_COLD.SQL: • Se necessário, ajuste os caminhos dos arquivos; • Não se esqueça de derrubar a instância corrente e depois levantá-la novamente. Limpe as tabelas HISTORICO e TURMAS. A partir de 25_GERA_COLD.SQL, gere outro Script possuindo comandos de restauração. Restaure as tabelas perdidas utilizando o Script criado no último exercício. Neste exercício você vai recuperar a Tablespace temporária. Siga o roteiro: a. Feche ACAD9; b. Elimine o arquivo associado à Tablespace TEMP (geralmente TEMP01.DBF); c. Abra ACAD9; Apesar de não ter sido emitida nenhuma mensagem de erro, aconteceram problemas, já que não existe mais um arquivo que deveria existir. d. Constate a ocorrência de problemas abrindo o arquivo de alertas; Lembre-se do Capítulo 19, item 19.1.5, que o arquivo de alertas registra avisos e erros. Ao final dele, deve haver algo semelhante a: •
4.
5. 6. 7. 8.
Thu Jul 18 18:45:09 2002 Errors in file e:\oracle\admin\acad9\bdump\acad9_dbw0_1596.trc: ORA-01157: cannot identify/lock data file 201 - see DBWR trace file ORA-01110: data file 201: 'E:\ORACLE\ORADATA\ACAD9\TEMP01.DBF' ORA-27041: unable to open file OSD-04002: não é possível abrir arquivo O/S-Error: (OS 2) The system cannot find the file specified.
Outra forma de constatar o erro pode ser pedir ao Enterprise Manager Console para listar os arquivos da Tablespace TEMP. e. Crie outra Tablespace temporária, digamos TEMP2; f. Altere a Default Temporary Tablespace para TEMP2: alter database default temporary tablespace temp2; Oracle 9i Fundamental
390
g. Elimine a Tablespace temporária original; h. Feche a instância corrente de ACAD9, abra-a novamente e constate que não acontecerem erros no arquivo de alertas. 9. Verifique se o Modo ArchiveLog está ligado. Caso não esteja, ligue-o. 10. Force uma duplicação dos Archived Redo Log Files. • Trata-se de uma medida bastante salutar, já que existirá uma cópia de cada Archived Redo Log File gerado em outra localidade (de preferência situada em um disco físico diferente): alter system set log_archive_duplex_dest = 'd:\archives\' scope = both;
11. Realize um Hot backup de ACAD9 Aproveite o script 25_HOT.SQL. 12. Provoque a perda da Tablespace USERS, a que contém as tabelas do Controle Acadêmico. • Conectado como DBAACAD, confirme que suas tabelas estão em USERS: select table_name, tablespace_name from user_tables;
Feche ACAD9 e elimine o arquivo associado à Tablespace USERS. 13. Recupere a Tablespace USERS. Siga o roteiro: a. Restaure o arquivo associado à Tablespace, isto é, traga-o do diretório em que foi gravado o Hot Backup para o de produção; b. Abra ACAD9 em estado Mount; c. Emita o comando recover database; Caso tenham sido gerados Archived Redo Log Files após o último Hot Backup, serão pedidos neste momento. Aceite que sejam aplicados até que não reste nenhum. d. Abra ACAD9 e constate que DBAACAD recuperou suas tabelas. Nos exercícios 14 a 19 será simulada uma perda provocada por imperícia de usuário. 14. Limpe a Tabela HISTORICO. Anote o número do Checkpoint corrente, última seqüência, próxima e corrente. • Utilize o comando archive log list. 15. Alimente a tabela HISTORICO. Faça novas anotações 16. Realize um Hot Backup do Banco. • Atualize anotações. 17. Provoque um log switch. • Comando: alter system switch logfile Oracle 9i Fundamental
391
18. Limpe a tabela HISTORICO. 19. Recupere a tabela HISTORICO. Siga o roteiro: a. Feche o Banco; b. Restaure o arquivo associado à Tablespace USERS (em que estava a tabela perdida); c. Abra o Banco em estado Mount; d. Emita o comando: recover database until cancel; e. Se houver apenas um aviso, interrompa, feche o Banco e recomece. f. Abra o Banco. 20. Faça com que tanto o Control File, quanto o arquivo binário de parâmetros (SPFILE) sejam copiados cada vez que ocorra um backup pelo Recovery Manager (RMAN). Basta utilizar a configuração: configure controlfile autobackup on;
21. Certifique-se que o destino dos backups realizados pelo RMAN esteja direcionado para um diretório conhecido. • Conecte-se pelo RMAN ao Target Database (ACAD9) e ao Recovery Database (TESTE). • Consulte parâmetros armazenados com SHOW ALL. Veja se aparece: CONFIGURE CHANNEL 1 DEVICE TYPE DISK FORMAT 'caminho';. • Realize o backup da Tablespace USERS com nível incremental 1. Anote o tamanho do Backup Piece gerado. • As cópias incrementais são utilizadas para que seja possível copiar apenas os blocos que mudaram entre um backup e outro. Para gerar uma primeira cópia a ser tomada como base pelas demais, faça: backup incremental level = 1 tablespace users;
•
•
LEVEL pode variar enre 0 e 4. Ao utilizar o nível 3, por exemplo, serão copia-dos todos os blocos alterados desde o último backup de nível 0, 1, 2 ou 3. Para listar de uma forma resumida todos os backups ocorridos com USERS, faça:
list backup of tablespace users summary;
22. Inclua um aluno e faça um novo backup de USERS, também incremental. Compare o tamanho do Backup Piece gerado neste exercício com o anterior. 23. Provoque uma inconsistência nos backups. Oracle 9i Fundamental
392
Siga o roteiro: a. Troque o nome do maior arquivo gerado no exercício anterior; b. Verifique a consistência dos backups: crosscheck backup;
c. Liste backups órfãos por meio do comando: report obsolete orphan;
24.
Observe que será mostrado o nome antigo do Backup Piece o qual foi alterado. Caso não seja possível recuperar a versão original, podem-se eliminar órfãos por meio do comando: delete obsolete; Gere uma versão texto do arquivo binário de parâmetros. • Utilize o comando: restore spfile to pfile 'destino';
Ao abrir o arquivo gerado no Bloco de Notas, certifique-se de que o texto seja mostrado com quebras de linha. Realize uma cópia fiel do Data File associado à Tablespace USERS. • Utilize o comando:
• 25.
copy datafile 'arquivo origem' to 'destino';
O arquivo produzido pode ser utilizado numa recuperação fora do RMAN, já que não possui formato proprietário. Esta técnica proporciona mais segurança em comparação às realizadas via SO (Cold e Hot), já que acontecem testes de integridade. • Além de Data Files correntes, ainda é possível fazer cópias de Data Files, Control Files (corrente ou cópia) ou Archived Redo Log Files. 26. Crie uma imagem do Control File corrente. Utilize o comando: •
copy current controlfile to 'destino';
• 27. •
Nos próximos três derradeiros exercícios, veremos como recuperar a Tablespace SYSTEM utilizando o Recovery Manager. Realize um backup completo. Como o destino já está pré-configurado, basta emitir o comando: backup database plus archivelog;
28. •
Perca SYSTEM. Derrube a instância e elimine o arquivo associado à Tablespace SYSTEM. Ao tentar abrir novamente o Banco, a seguinte mensagem será mostrada: Oracle 9i Fundamental
393
RMAN> startup conectado ao banco de dados de destino (não iniciado) instância Oracle iniciada banco de dados montado RMAN-00571:==================================================== RMAN-00569: ========= ERROR MESSAGE STACK FOLLOWS ============= RMAN-00571: =================================================== RMAN-03002: failure of startup command at 07/19/2002 17:49:00 ORA-01157: não é possível identificar/bloquear arquivo de dados 1 - consulte arquivo de análise DBWRORA-01110: 1 do arquivo de dados: 'E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF' RMAN>
29. Recupere SYSTEM. Emita os comandos: Restore tablespace system; Recover tablespace system; Alter database open;
REFERÊNCIA RÁPIDA Tarefa
Como fazer
Realizar uma cópia de segurança lógica
Utilitário de linha de comando EXP. Para conhecer seus parâmetros, digite: Exp help=y
Realizar uma recuperação lógica
Utilitário de linha de comando IMP. Para conhecer seus parâmetros, digite: Imp help=y Conectado como SYS, execute:
Criar o Dicionário de Dados para o LogMiner em um arquivo externo
execute dbms_logmnr_d.build ('dictionary.ora', 'diretório em UTL_FILE_DIR', options => dbms_logmnr_d.store_in_flat_file);
A criação do Dicionário de Dados deve acontecer apenas uma vez, assim como a sinalização de que informações adicionais irão para os Redo Log Files: alter database add supplemental log data;
Direcionar a criação dos objetos do LogMiner para uma Tablespace específica
Acrescentar um arquivo (Redo ou Archived) à busca do LogMiner
Conectado como SYS, execute: execute dbms_logmnr_d.set_tablespace('ts');
Em que ts representa uma Tablespace destino. Antes de disparar uma busca pelo LogMiner, devemse registar os arquivos (Redos ou Archived) a serem utilizados como fonte: execute dbms_logmnr.add_logfile (options => dbms_logmnr.new, Logfilename => 'arquivo');
Além do procedimento NEW, costuma-se utilizar ADDFILE. Para remover um arquivo, REMOVEFILE.
Oracle 9i Fundamental
394
Tarefa
Como fazer Existindo um Dicionário de Dados e tendo sido cadastrados os arquivos-fonte, dispara-se a busca: execute dbms_logmnr.start_logmnr (DictFileName => 'dicionário', StartTime => to_date('dd-mmm-aaaa hh:mm:ss', 'DD-MON-YYYY HH24:MI:SS'), Endtime => to_date(' dd-mmm-aaaa hh:mm:ss', 'DD-MON-YYYY HH24:MI:SS'));
Disparar uma busca com o LogMiner
Consultar resultado da busca do LogMiner
Visão V$LOGMNR_CONTENTS.
Encerrar uma sessão LogMiner
execute dbms_logmnr.end_logmnr;
Verificar se uma dada Tablespace pode ser transportada
A instrução seguinte verifica inclusive constraints: execute dbms_tts.transport_set_check ('ts', TRUE);
O resultado será armazenado em: sys. transport_set_violations
Executar um comando do SO a partir do SQL*Plus ou RMAN
Comando HOST
Realizar Backup.
Feche o Banco, copie os arquivos, reabra o banco.
um
Cold
Recuperação Cold.
Feche o Banco, copie os arquivos para os lugares de origem, reabra o banco.
Ligar o Modo ArchiveLog.
Siga roteiro de 25.7.1.
Realizar um Hot Online Backup.
Colocar Tablespaces em estado BACKUP, copiar seus arquivos, retirá-las do estado BACKUP. O Banco deve estar em Modo ArchiveLog.
Recuperação Hot.
Fechar o Banco, abri-lo em Mount, Comando recover database, abrir o Banco.
Ativar o RMAN.
Em uma janela de linha de comando faça: rman TARGET usu/senha@host CATALOG usu/senha@host
Criar o Recovery Catalog referente ao Target Database no Recovery Database.
Comando create catalog. Para registrar o Target, register database. Para destruir o Recovery Catalog, comando drop catalog.
Consultar Recovery Catalog a partir do SQ7LPlus Worksheet.
Views RC_*. Exemplos: RC_BACKUP_PIECE, RC_DATABASE, RC_DATAFILE, RC_RESYNC, RC_TABLESPACE etc.
Consultar Catalog a RMAN.
Recovery partir do
Comandos list e report. Exemplos: list backup of tablespace users summary; report obsolete orphan;
Oracle 9i Fundamental
395
Tarefa
Como fazer
Sincronizar o Recovery Catalog com o Control File do Target
Comando resysnc catalog. Exemplo: resync catalog;
Realizar um Backup pelo RMAN
Comando backup. Exemplo: Backup database;
Restaurar pelo RMAN.
Comando restore. Exemplo: restore tablespace system;
Recuperar pelo RMAN
Comando recover. Exemplo: recover tablespace avaliacoes;
Validar RMAN
backups
do
Armazenar configurações no RMAN
Comando crosscheck backup. Comando configure. coman-do show all.
Para
Oracle 9i Fundamental
exibir
configurações,
396
ANOTAÇÕES
Oracle 9i Fundamental
397
Capítulo 26 – CRIAÇÃO DE UM BANCO DE DADOS OBJETIVOS • • • •
Criar um Banco de Dados no ambiente Windows 2000; Identificar a criação do Banco; Criar Host Strings; Remover um Banco de Dados.
NOVIDADES •
•
O Assistente encarregado da criação, o Database Configuration Assistant (DBCA), facilitou enormemente a criação de Bancos de Dados; Introduziu-se o conceito de Gabarito, que permite criar um padrão que agiliza a criação de vários Bancos de Dados possuindo características semelhantes.
ARQUIVOS NECESSÁRIOS •
Nenhum.
PRÉ-REQUISITOS • • •
Utilizar SQL*Plus Worksheet para realizar acesso a bases Oracle; Identificar elementos da arquitetura Oracle; Conhecer os conceitos de Tablespace, Usuário, Schema, Tabela.
TEORIA 26.1 - Fundamentos É muito comum a coexistência de vários Bancos de Dados em um Servidor. A criação depende bastante do SO que está sendo utilizado (Unix, Windows 2000, etc.). Daremos o enfoque Windows 2000. A criação de um segundo Banco requer alguns cuidados: Oracle 9i Fundamental
398
• • •
•
Organização lógica que siga o padrão OFA; Verificação de espaço em disco e memória; Determinação de novas variáveis de ambiente: ORACLE_HOME e ORACLE_SID. Elas podem ser pesquisadas pelo Registry em: HKEY_LOCAL_MACHINE\ SOFTWARE\ORACLE; Cópia de todos os Bancos correntes.
Tomadas as precauções citadas, parte-se para a criação propriamente dita: a. Criar os diretórios nos diversos discos pelos quais o Banco irá se espalhar; b. Edição do Arquivo de Parâmetros em que constem as características da Instância (nome, utilização de memória, etc.) e outras do próprio Banco (tamanho do Bloco padrão, por exemplo); c. Configurar Clientes para que possam se conectar ao novo Banco (LISTENER.ORA e TNSNAMES.ORA). No Windows 2000 eles estão no diretório \oracle\network\admin.
26.2 - Database Configuration Assistant O Windows 2000 possui uma ferramenta gráfica capaz de criar Bancos de Dados: o Database Configuration Assistant (Start, Programs, Oracle OraHome90, Configu-ration and Migration Tools). Após uma tela de boas-vindas ao lado, surge a primeira possibilidade de interação: Escolhendo Criar um banco de dados, depois pressionando Próxi-mo, são mostradas telas interativas nas quais o Banco vai sendo cons-truído.
Algumas dicas: • Na tela 2, Gabaritos de Bancos de Dados, são apresentados diversos modelos contendo parâmetros e definições de arquivos. Se o Banco por criar for de uso genérico, escolha General Purpose; • Na tela 3, Identificação de Bancos de Dados, são pedidos o nome e o SID (digitando o primeiro, preenche-se o segundo); Oracle 9i Fundamental
399
Na tela 4, Opções de Conexão de Banco de Dados, escolhe-se entre o Modo Dedicado ou Compartilhado (Shared Server - veja Capítulo 19, item 19.3.2.1); • Na tela 5, Parâmetros de Inicialização, configuram-se os parâmetros. Nada impede que, uma vez criado o Banco, a instância seja aberta com outro Arquivo de Parâmetros; • Na penúltima tela, Armazenamento de BD, especificam-se os arquivos (Control, Redo, Data); • Finalmente na última, existe a possibilidade de criar efetivamente o Banco ou simplesmente gerar um Gabarito, que poderá ser utilizado em futuras criações. Uma vez criado, o Banco pode ser enriquecido com novas Tablespaces e seus respectivos segmentos. •
Atenção •
•
A variável de ambiente ORACLE_SID sempre recebe o SID do último Banco criado. Para acessar outros bancos previamente criados, deve-se fazê-lo utilizando Host Strings, mesmo no Servidor. Uma conseqüência direta da criação de um novo Database consiste na criação de um novo Serviço, cujo nome será OracleServiceSID.
26.3 - Net Configuration Assistant Caso exista mais de uma instância em um Servidor, devem-se obriga-toriamente criar Host Strings para que seja possível conectar-se à que não seja padrão (aquela apontada pela variável de am-biente ORACLE_SID). Para criar um Host String, car-regue o Net Configuration Assistant (também em Start, Programs, Oracle - OraHome92, Configuration and Migration Tools), cuja primeira tela será: Escolhendo a terceira opção, Configuração do Nome do Serviço de Rede Local, e pressionando em Próximo, abre-se um leque com cinco possibilidades: Adicionar, Reconfigurar, Deletar, Renomear e Testar. Escolhendo a primeira, Adicionar, abre-se a terceira tela na qual se pede uma carac-terização quanto à versão: Oracle 8i (default) ou anterior. Oracle 9i Fundamental
400
A quarta tela pedirá o nome do Serviço, que deve coincidir com a SID por acessar. A quinta tela pedirá o protocolo de comunicação (geralmente escolhe-se TCP) e a próxima requer o nome do Servidor contendo o Banco por acessar. Encerra-se o processo, dando a opção de teste.
26.4 - Eliminação de um Banco de Dados Para destruir um Banco de Dados, também se utiliza o Database Configuration Assistant (opção Deletar um banco de dados da primeira tela). A destruição será possível sempre e quando o Banco estiver aberto, pois o DBCA realiza uma conexão. Apesar de ser avisado que o Banco será destruído, inclusive Serviço e arquivos, nenhum aviso mais sério acontece caso existam outras sessões abertas. Caso o Banco excluído seja o padrão, deve-se alterar a variável de ambiente ORACLE_SID após a eliminação.
EXERCÍCIOS 1. Siga as instruções do DBCA e crie um Banco denominado ORC1. • Ao final, analise os diretórios criados, especialmente os arquivos que constam em CREATE (oracle\admin\SID\create). 2. Cheque o valor das variáveis de ambiente ORACLE_SID e ORACLE_HOME • Ao conectar-se no Servidor, qual Banco pode ter a Host String omitida? 3. Altere ORACLE_SID para ACAD9. 4. Crie um Host String para realizar conexões a ORC1, caso já não exista uma. 5. Cadastre o Banco recém-criado no Enterprise Manager Console.
REFERÊNCIA RÁPIDA Tarefa Criar um Dados
Como fazer Banco
de
Carregue o DBCA, escolha a opção Criar um banco de da-dos e siga as instruções do assistente.
Criar um Host String
Carregue o Net Configuration Assistant, escolha a opção Configuração do Nome do Serviço de Rede Local e siga as instruções do assistente.
Apagar um Banco de Dados
Pelo DBCA, escolha a opção Deletar um banco de dados e siga as instruções do assistente. O serviço deve estar ativa-do e o Banco aberto.
Oracle 9i Fundamental
401
APÊNDICE A: SQL*PLUS Antes do advento da SQLPlus Worksheet, introduzida na versão 8i, os trabalhos envolvendo a liguagem SQL aconteciam primordialmente via SQL*Plus. Basicamente, a Worksheet conferiu um aspecto um pouco menos hostil à antecessora, já que todos os comandos específicos (DESCRIBE, START, etc.) de uma podem ser utilizados na outra e vice versa. Na versão 9i, com o desaparecimento da ferramenta Server Manager, a SQL*Plus ainda é utilizada para algumas tarefas bastante específicas tais como a execução de Scripts que ativem comandos do Sistema Operacional (comando HOST). Lembre-se, no gigante capítulo 24, como aconteceu o Hot Backup. Existem duas modalidades de utilização para a SQL*Plus: uma gráfica e outra em modo linha. No Windows 2000, a primeira ativa-se de forma semelhante à Worksheet: Start, Programs, Oracle – OraHome90, Application Development:
Para agilizar a ativação do programa pode-se criar um atalho (shortcut) na área de trabalho onde: Target (alvo) Start em)
In
\oracle\bin\sqlplusw.exe string
usuário/senha@host
(iniciar Algum diretório contendo Scripts
Uma das grandes dificuldades apresentadas pelo SQL*Plus consiste em suas parcas opções de edição. A digitação restringe-se a uma área Oracle 9i Fundamental
402
bastante limitada (na verdade, apenas onde está o cursor). Caso cometa-se um erro num comando durante a digitação, não se pode navegar com teclas de movimentação de cursor para frente ou para trás. Existem algumas alternativas que amenizam este problema: • Através do comando START pode-se disparar arquivos contendo um conjunto de comandos editado em um editor de textos tais como o Bloco de Notas; • O comando EDIT carrega o Editor de Textos associado (geralmente o Bloco de Notas) e permite editar o último comando SQL emitido. Normalmente este comando produz um arquivo denominado AFIEDT.BUF; • Pode-se recuperar comandos passados selecionando-os ao arrastar o mouse sobre eles com o botão esquerdo do mouse pressionado. Ao terminar a seleção, clica-se o botão direito do mouse e o conteúdo selecionado será transportado para a área corrente de edição; • Os comandos que manipulam a área de transferência do Windows são largamente utilizados (Copy, Paste, Cut). Além de EDIT, existem outros comandos que manipulam o buffer: Comando
Descrição
Save arquivo
Grava conteúdo especificado.
Append texto
Incorpora o texto em questão ao final do buffer.
Get arquivo
Sobrepõe o buffer com o arquivo especificado.
Run
Executa o conteúdo abreviado como /
do
buffer
do
no
buffer.
arquivo
Pode
ser
A modalidade não gráfica carece de quaisquer benefícios de edição, entretanto, permite a utilização sem realizar conexão alguma. Por exemplo, recorde o conteúdo do arquivo de lote 25_FAZHOT.BAT: C:\> sqlplus /nolog
@25_hot.sql > e:\saida.txt
Observe que ainda dispara-se um Script, 25_HOT.SQL.
Oracle 9i Fundamental
403
APÊNDICE B: MODELO DE CONTROLE ACADÊMICO A figura abaixo mostra uma representação gráfica das tabelas, que constam do Estudo de Caso trabalhado ao longo do livro, e seus inter-relacionamentos. Note como os campos chave são destacados e a cardinalidade dos relacionamentos. Por exemplo: a tabela Instrutores possui o campo cod_instrutor como chave primária e relaciona-se com a tabela turmas sob cardinalidade 1:N, isto é, um instrutor pode ministrar várias turmas, porém, cada turma possui apenas um instrutor.
Oracle 9i Fundamental
404
____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________ ____________________________________________________________________
Oracle 9i Fundamental
405
APÊNDICE C: BIBLIOGRAFIA COMENTADA Ler apenas um livro ou assistir a um curso, por melhor que sejam, não bastam para for-mar um especialista nos assuntos tratados até aqui. Necessita-se uma constante formação posterior para aprofundar os temas apresentados, ou mesmo abrir novas fronteiras. No material disponível na Internet existe um arquivo .XLS, Livros_Oracle9i, que contém, além dos livros aqui citados, outros mais sobre Oracle9i. Não se trata de uma lista definitiva, e nem poderia, pois o mercado editorial possui um comportamento extremamente dinâmico. A seguir, mostramos uma relação de obras que, ou ajudaram de forma marcante o autor na sua empreitada, ou complementam os assuntos tratados neste livro, para que o leitor possa aprofundar os assuntos aqui abordados. 1Título: Autores: Editora: Comentário s:
ORACLE 9I FOR WINDOWS 2000 - TIPS & TECHNIQUES Scott Jesse, Matthew Hart, Michael Sale Osborne/Oracle Press - 2002 Págs. 637 Por ser dedicado exclusivamente à plataforma Windows, logra abordar assuntos que normalmente são esquecidos. Destaque para as diferenças únicas na arquitetura do produto utilizado sob Windows 2000 (cap. 2), detalhes internos da instalação (cap. 4) e configurações (cap. 5). O sexto capítulo traz um rico material sobre Recovery Manager. Vale a pena também conferir a Parte IV, na qual comenta como garantir alta disponibilidade dos dados via Real Application Clusters (RAC) e Transparent Application Failover (TAF). Não deixe de ler o Capítulo 13, onde há valiosas informações sobre como implementar Bancos de Dados Standby.
2Título: Autor: Editora: Comentário s:
ORACLE 9i - DBA HANDBOOK Kevin Loney, Marlene Theriault Oracle Press - 2001 Págs. 980 Trata-se de um guia bastante completo de apoio à atividade do DBA. Deve estar sempre à mão para ser consultado em caso de dúvidas. Esgota os assuntos de uma forma bastante completa, com destaque à abordagem de Configurações Lógica e Física (caps. 3 e 4), Ajustes de Desempenho (cap. 8), Recovery Manager (cap. 12) e Problemas de conectividade (Parte III). Já existe a versão traduzida para português.
3Título:
ORACLE 8i - BACKUP & RECOVERY HANDBOOK Oracle 9i Fundamental
406
Autor:
Rama Velpuri, Anand Adkoli
Editora:
Oracle Press - 2000
Comentário s:
Até meados de julho de 2002 ainda não tinha sido publicada a versão para 9i, e quando sair, não hesite em adquiri-la. A recuperação de um Banco danificado representa a atividade de maior pressão para um DBA. E o sucesso dela depende fundamentalmente da existência de uma Política de Backup consistente. Este indispensável livro esgota os recursos oferecidos pelo Oracle8i para realizar backups e recuperações. Destaquem-se os capítulos 7 (Recovery Manager), 8 (Replicação) e, principalmente, o décimo, em que são discutidos 22 estudos de caso baseados em fatos reais.
Págs.
695
4Título:
ORACLE 8i DATABASE ADMINISTRATION
Autor:
Noel Yuhanna
Editora:
Manning Pub Co. - 1999
Comentário s:
Sua organização baseada em casos práticos é bastante peculiar e recomen-dável para quem já possui alguma vivência de administração de Bancos de Dados. Os onze capítulos subdividem-se em itens do tipo “Como posso realizar determinada tarefa?”, o que torna o livro extremamente objetivo. Até meados de julho de 2002 não tinha sido publicada a versão abran-gendo 9i. Já existe versão traduzida, mas ela peca demais pela utilização de termos com tradução esdrúxula.
Págs.
528
5Título:
INSTANT ORACLE9I PL/SQL SCRIPTS
Autores:
Kevin Loney, Megh Thakkar, Rachel Carmichael
Editora:
Oracle Press 2001
Comentário s:
Oferece inúmeros scripts que auxiliam a administração de Bancos de Dados. Há de tudo um pouco: desde a inspeção de estruturas de memória, passando pela interdependência entre tabelas via chaves estrangeiras e até gerência de espaço em disco.
Págs.
598
6Título:
ORACLE PERFORMANCE TUNING TIPS & TECHNIQUES
Autores:
Richard Niemiec, Brad Brown, Joe Trezzo
Editora:
Oracle Press 1999
Comentário s:
Trata-se de um clássico. O mais completo guia de ajuste de performance (tuning) já publicado. Destaque para o capítulo dedicado a índices (2), a consultas (8), PL/SQL (10) e às visões V$ (14). Espera-se o lançamento da edição abrangendo o 9i para breve.
Págs.
894
Oracle 9i Fundamental
407
7Título: Autores: Editora: Comentário s:
PROJETO DE BANCO DE DADOS - UMA VISÃO PRÁTICA Maurício Pereira de Abreu e Felipe Nery R. Machado Érica - 1999 Págs. 324 Apesar de não ser um livro sobre Oracle, constitui excelente material introdutório às etapas anteriores à construção de bancos de dados físicos, em que se destacam a modelagem conceitual e o M.E.R. Traz um extenso capítulo sobre a linguagem SQL.
8Título: Autores: Editora: Comentário s:
ORACLE9I DBA 101 Marlene Theriault, Rachel Carmichael, James Viscusi Oracle Press - 2002 Págs. 550 Dedicado ao DBA e ao seu dia-a-dia. Inicia definindo o papel do DBA e introduz a arquitetura Oracle; a segunda parte apresenta um interessante capítulo (9 - What We Do Daily) que mostra uma sistematização no tra-balho do DBA. A terceira parte trata sobre segurança e a quarta sobre ajustes de desempenho (tuning).
9Título: Autor: Editora: Comentário s:
ORACLE9I UNIX ADMINISTRATION HANDBOOK Donald K. Burleson Oracle Press - 2002 Págs. 517 Manual do DBA que trabalha em plataformas Unix (Solaris, HPUNIX, IBM-AIX UNIX e Linux). Há vários scripts valiosos, tanto Oracle quanto Unix. Aborda o produto Statspack para capturar estatísticas Unix.
10Título: Autores: Editora: Comentário s:
ORACLE9I: A BEGINNER'S GUIDE Michael Abbey, Michael J. Corey, Ian Abramson Oracle Press - 2001 Págs: 515 Sua linguagem simples e direta credencia-o como “porta de entrada” ao mundo Oracle. Tenta ser generalista, porém aprofunda alguns tópicos. Destaque para os capítulos 1 (Oracle: The Company and the Software - traz um belo histórico sobre a Oracle), 3 (sobre a arquitetura interna), 4 (Database Objects), Parte III (apoio ao desenvolvedor) e, na Parte IV, destaca-se o capítulo 13 (I is for Internet). Vale a pena conferir o capítulo 17 (Data Warehousing) . Deve ser traduzido em breve.
11Título:
SQL SERVER 2000 FUNDAMENTAL Oracle 9i Fundamental
408
Autor: Editora: Comentário s:
Eduardo Terra Morelli Editora Érica - 2001 Págs. 504 Também não trata sobre Oracle, mas de SQL Server, seu maior concor-rente. Escrito pelo mesmo autor de Oracle 9i Fundamental, segue o mesmo estilo, com abundância de dicas, scripts e exercícios.
12Título:
ORACLE9I XML HANDBOOK
Autor:
Mark Scardinan
Editora:
Osborne - 2001
Comentário s:
XML caminha a passos largos para transformar-se na linguagem padrão de intercâmbio de dados entre plataformas heterogêneas. Este livro explica, não apenas as estruturas desta importante linguagem, como também aplicações utilizando Oracle. Destaque-se a abordagem ao Oracle9i Application Server.
Págs.
576
13Título:
ORACLE9I SQLJ PROGRAMMING
Autores:
Nirva Morisseau-Leroy, Martin Solomon, Gerald Momplaisir
Editora:
Osborne - 2001
Comentário s:
SQLJ é uma linguagem que incorpora SQL a Java. Muito utilizada para desenvolver aplicações Web. Este livro explica como criá-las com auxílio do produto Oracle Portal.
Págs.
608
14Título:
ORACLE9I JDBC PROGRAMMING
Autores:
Nirva Morisseau-Leroy, Martin Solomon, Gerald Momplaisir
Editora:
Oracle Press - 2001
Comentário s:
JDBC (Java Database Connectivity), representa mais uma alternativa de de-senvolvimento de aplicações que interajam com Bancos de Dados Oracle. Destaque para a Parte II, na qual se compara JDBC com PL/SQL e ensina-se a lidar com os preceitos da Programação Orientada por Objetos. O capítulo 10 mostra como criar Enterprise Java Beans (EJB) e JavaServer Pages (JSP).
Págs.
608
15Título:
OCP - ORACLE9I CERTIFICATION
Autores:
Chip Dawes et al.
Editora:
Sybex - 2002
Págs.
-
Oracle 9i Fundamental
409
Comentários:
Oferece material de estudo para a certificação em Oracle 9i. Abordam-se quatro exames: OCA/OCP: Introduction to Oracle9i SQL (1Z0-007) OCA/OCP: Oracle9i DBA Fundamentals I (1Z0-031) OCP: Oracle9i DBA Fundamentals II (1Z0-032) OCP: Oracle9i Performance Tuning (1Z0-033) Incluídos quatro CDs com inúmeras questões para treino.
Seja qual for o livro estudado, não se esqueça de que a documentação que vem com o Oracle também constitui uma fonte de inestimável valor. Toda organizada em forma de hipertexto, permite a busca rápida de assuntos nem sempre abordados nos livros, tais como: sintaxes completas de comandos e descrição de parâmetros.
Oracle 9i Fundamental
410
APÊNDICE D: EXEMPLO DE RELATÓRIO DE LEVANTAMENTO Este documento visa estabelecer, em linhas gerais, as medidas que devem ser toma-das para conhecer e otimizar uma ou mais bases de dados Oracle. O questionário seguinte traça um perfil da instalação, algumas medidas básicas são sugeridas e, finalmente, mostra-se o script AD.sql (Análise Detalhada) que invoca vários outros. Questionário 1)
Qual é a configuração de hardware? (CPUs, memória, discos)
2)
Os discos possuem redundância?
3)
Existe algum Servidor destinado a testes?
4)
Existe contrato Oracle?
5)
Quantas versões distintas do Oracle Server existem? Quais são elas?
6)
Quantos bancos existem?
7)
Quanto espaço em disco atualmente está destindo aos dados?
8)
Quantas instâncias são utilizadas?
9)
Quantos usuários espera-se que utilizem a base e quantos farão isso de forma concorrente?
de
algum
nível
manutenção
com
de
a
10) Como estão organizadas as Tablespaces? Seguiu-se o padrão OFA? 11) Existe alguma política de backup? Qual? Há unidades de fita envolvidas? 12) Existe uma política de upgrade de hardware? 13) Qual é a configuração de software? (SOs, ferramentas) 14) Quantas aplicações usarão a base? 15) Existem roles? 16) Que tipos de aplicações predominam: OLTP ou batch? Oracle 9i Fundamental
411
17) Os dados hoje presentes provêm de bases externas ou de transações? 18) Existe alguma política de manutenção de Segmentos de Rollback92? 19) Como estão organizadas as Tablespaces? Quais são gerenciadas localmente e quais são por Dicionário de Dados? 20) Existe o hábito de atualizar as estatísticas? 21) Índices são reconstruídos periodicamente? 22) A fragmentação de Segmentos de Dados é verificada com alguma freqüência? 23) Com que freqüência verificam-se o arquivo de Alertas e o gerado por traces?
Medidas Básicas Antes de pensar em qualquer tipo de otimização, algumas medidas devem ser tomadas: • Realizar um backup “cold”. • Analisar o resultado do script AD.sql (Análise Detalhada). • A otimização deve começar pelo hardware (CPU, discos), seguir com a memória, depois com armazenamento e concluir com SQL. • Verificar a relação entre Data Block Buffer Cache e o tamanho do banco. Não deve superar 2%. • Verificar freqüência de log switches. • Verificar presença de gargalos de I/O. • Verificar regras de separação de arquivos, segundo a OFA. • Analisar possibilidade de mecanismos avançados de separação de dados: RAID e RAW Devices. AD.sql (Análise Detalhada) spool saida.txt set feedback off set pagesize 40 set linesize 200 set termout off prompt ANALISE DIARIA prompt column Agora format a20 heading 'Agora:' select to_char(sysdate,'dd/mm/yyyy hh24:mi ') Agora from dual;
92
Esta questão somente aplica-se detalhes no Capítulo 21.
caso
a
SMU
não
Oracle 9i Fundamental
esteja
vigente.
Mais
412
prompt prompt ********************** A Instância corrente está no ar: column Startup format a20 heading "Último Startup:" select to_char(logon_time, 'dd/mm/yy hh24:mi:ss') Startup from sys.v_$session where sid=1; prompt prompt Em dias e horas: prompt select SYSDATE-logon_time "Dias", (SYSDATE-logon_time)*24 "Horas" from sys.v_$session where sid=1 ; @ArquivosParametros prompt prompt ********************** Analisa espaço disponível @Espaco_disponivel prompt prompt ********************** Existe algum segmento que não possa realizar a próxima extensão ? @Ver_Extent prompt prompt ********************** Mostra E/S por arquivo @CriaHra prompt prompt ********************** Mostra Hit Ratio por usuário e Usuários por programa @CriaHru prompt prompt ******** Mostra Extents por Segmento em Tablespaces gerenciadas via Dicionário @LeMaiores prompt prompt ********************** Acompanhamento dos Segmentos de Rollback @mostrarbs.sql prompt prompt ********************** Tuning de Memória: Percentual de Memória Livre na Shared Pool @MemoriaLivre.sql prompt prompt ********************** Tuning de Memória: SQL Area @LibraryCacheReloads.sql prompt prompt ********************** Tuning de Memória: Database Buffer Cache @DataBaseCache.sql prompt prompt ********************** Tuning de Memória: Redo Log Buffer @RedoLogBuffer.sql prompt prompt ********************** Tuning de Memória: Ordenações em disco e memória @Sorts.sql prompt prompt ********************** Distribuição de tabelas select owner Dono, count(*) Tabelas from dba_tables group by owner order by 2 desc; spool off set termout on set feedback on
Todos os arquivos mencionados, inclusive AD.sql, encontram-se no diretório HOTS. Oracle 9i Fundamental
413
Exemplo de saída Em alguns pontos da saída apresentados em seguida, preferiu-se omitir detalhes. ANALISE DIARIA Agora: -------------------26/07/2002 16:39 **********************
A Instância corrente está no ar:
Último Startup: -------------------26/07/02 09:32:21 Em dias e horas: Dias Horas ---------- ---------,296724537 7,12138889 **********************
Versão corrente
--------------------------------------------------------------Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production PL/SQL Release 9.2.0.1.0 - Production CORE 9.2.0.1.0 Production TNS for 32-bit Windows: Version 9.2.0.1.0 - Production NLSRTL Version 9.2.0.1.0 - Production **********************
Nome do Banco, Data de Criação e Modo Archive
Banco Data Modo Archive --------- -------- -----------ACAD9 30/06/02 ARCHIVELOG **********************
Tablespaces e Data Files
Tablespace -----------------------------AVALIACOES CWMLITE DRSYS EXAMPLE INDX ODM SYSTEM TOOLS UNDOTBS1 USERS XDB **********************
Local/Dic --------------LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL
Arquivo -------------------------------E:\ORACLE\ORADATA\ACAD9\ACADAVAL.ORA E:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF E:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF E:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF E:\ORACLE\ORADATA\ACAD9\INDX01.DBF E:\ORACLE\ORADATA\ACAD9\ODM01.DBF E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF E:\ORACLE\ORADATA\ACAD9\USERS01.DBF E:\ORACLE\ORADATA\ACAD9\XDB01.DBF
Control Files
Arquivo -------------------------------------------------E:\ORACLE\ORADATA\ACAD9\CONTROL01.CTL E:\ORACLE\ORADATA\ACAD9\CONTROL02.CTL E:\ORACLE\ORADATA\ACAD9\CONTROL03.CTL **********************
Redo Log Files
Oracle 9i Fundamental
414
Grupo ---------1 2 3
Arquivo -------------------------------------------------E:\ORACLE\ORADATA\ACAD9\REDO01.LOG E:\ORACLE\ORADATA\ACAD9\REDO02.LOG E:\ORACLE\ORADATA\ACAD9\REDO03.LOG
GROUP# SEQUENCE# Bytes Livres ARC Status FIRST_CHANGE# TEMPO ---------- ---------- ---------------- --- ------------ ------------- --------------1 20 104,857,600 YES INACTIVE 2539199 26/07/02 08:31:13 2 21 104,857,600 YES INACTIVE 2563506 26/07/02 08:58:26 3 22 104,857,600 NO CURRENT 2588402 26/07/02 09:32:53 **********************
Localização de Arquivos Trace e Archive
Parâmetro -----------------------------background_dump_dest log_archive_dest user_dump_dest ********************** está ligado
Local -------------------------------e:\oracle\admin\Acad9\bdump %ORACLE_HOME%\database\archive e:\oracle\admin\Acad9\udump
SS: caso o parâmetro abaixo seja diferente de zero, o SS
Parâmetro Valor ------------------------------ ---------shared_servers 1 **********************
Parâmetros relacionados com a Database Buffer Cache
Bytes destinados a blocos de tamanho padrão está em DB_CACHE_SIZE. Caso este valor ultrapasse 2% do espaço utilizado, aumentar o DBC. Os demais valores (db_xx_cache_size) destinam-se a outros tamanhos de bloco Parâmetro -------------------db_block_size db_cache_size db_16k_cache_size db_2k_cache_size db_32k_cache_size db_4k_cache_size db_8k_cache_size
Valor -------------------8192 12582912 0 0 0 0 0
********************** Parâmetro -------------------db_create_file_dest log_buffer optimizer_mode sga_max_size shared_pool_size sort_area_size spfile
Outros Parâmetros interessantes
Valor -----------------------------------------524288 CHOOSE 72424008 25165824 524288 %ORACLE_HOME%\DATABASE\SPFILE%ORACLE_SID%.ORA
**********************
SGA
Parâmetro Valor -------------------- -------------------Database Buffers 12,582,912
Oracle 9i Fundamental
415
Fixed Size Redo Buffers Variable Size **********************
453,192 667,648 58,720,256 Propriedades do Banco
Propriedade -----------------------------DICT.BASE DEFAULT_TEMP_TABLESPACE DBTIMEZONE NLS_LANGUAGE NLS_TERRITORY NLS_CURRENCY NLS_ISO_CURRENCY NLS_NUMERIC_CHARACTERS NLS_CHARACTERSET NLS_CALENDAR NLS_DATE_FORMAT NLS_DATE_LANGUAGE NLS_SORT NLS_TIME_FORMAT NLS_TIMESTAMP_FORMAT NLS_TIME_TZ_FORMAT NLS_TIMESTAMP_TZ_FORMAT NLS_DUAL_CURRENCY NLS_COMP NLS_LENGTH_SEMANTICS NLS_NCHAR_CONV_EXCP NLS_NCHAR_CHARACTERSET NLS_RDBMS_VERSION GLOBAL_DB_NAME EXPORT_VIEWS_VERSION **********************
Valor -------------------------------2 TEMP2 -07:00 AMERICAN AMERICA $ AMERICA ., WE8MSWIN1252 GREGORIAN DD-MON-RR AMERICAN BINARY HH.MI.SSXFF AM DD-MON-RR HH.MI.SSXFF AM HH.MI.SSXFF AM TZR DD-MON-RR HH.MI.SSXFF AM TZR $ BINARY BYTE FALSE AL16UTF16 9.2.0.1.0 ACAD9.US.ORACLE.COM 8
Analisa espaço disponível
Espaço Total Livre (MB) ----------------------194.21 Espaço Total Alocado (MB) ------------------------934.38 TABLESPACE MB Livres Total MB % Livre -------------------- --------- --------- --------XDB .19 38.13 .50 EXAMPLE 1.81 166.25 1.09 SYSTEM 8.38 400.00 2.10 TOOLS 3.94 10.00 39.40 UNDOTBS1 89.81 200.00 44.91 DRSYS 10.31 20.00 51.55 CWMLITE 10.63 20.00 53.15 ODM 10.69 20.00 53.45 USERS 23.63 25.00 94.52 AVALIACOES 9.88 10.00 98.80 INDX 24.94 25.00 99.76 ********************** extensão ?
Existe algum segmento que não possa realizar a próxima
**********************
Mostra E/S por arquivo
Total E/S ----------------
Oracle 9i Fundamental
416
161,049 Arquivo BLOCOS_LIDOS BLOCOS_GRAVADOS Total E/S ------------------------------------------------------------------------------------E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF 141614 234 141,848 E:\ORACLE\ORADATA\ACAD9\XDB01.DBF 6526 2 6,528 E:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF 5505 12 5,517 E:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF 1859 2 1,861 E:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF 1671 2 1,673 E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF 137 1053 1,190 E:\ORACLE\ORADATA\ACAD9\ODM01.DBF 1071 2 1,073 E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF 1068 2 1,070 E:\ORACLE\ORADATA\ACAD9\USERS01.DBF 250 2 252 E:\ORACLE\ORADATA\ACAD9\ACADAVAL.ORA 23 2 25 E:\ORACLE\ORADATA\ACAD9\INDX01.DBF 10 2 12 **********************
Mostra Hit Ratio por usuário e Usuários por programa
Usuarios conectados ------------------11 Username Estação Usuário SO Hit Ratio LOGON --------------- --------------- --------------- --------- ----SYSTEM TMORELLI TMORELLI\Admini 74.96 16:28:49 strator Programa Usuários -------------------- -------ORACLE.EXE 10 ******** Mostra Extents por Segmento em Tablespaces gerenciadas via Dicionário **********************
Acompanhamento dos Segmentos de Rollback
RBS WRITES WRAPS SHRINKS EXTENDS Extents ---------- ---------- ---------- ---------- ---------- ------SYSTEM 7248 0 0 0 6 _SYSSMU1$ 674038 1 0 1 25 _SYSSMU2$ 664838 1 0 1 25 _SYSSMU3$ 674356 0 0 0 26 _SYSSMU4$ 671504 0 0 0 19 _SYSSMU5$ 671760 1 0 1 25 _SYSSMU6$ 668560 1 0 1 25 _SYSSMU7$ 678906 1 0 1 25 _SYSSMU8$ 664866 1 0 1 25 _SYSSMU9$ 724916 1 0 1 27 _SYSSMU10$ 668654 1 0 1 25 ************ Quem está usando ? *****
Relação de locks. O tempo está em segundos
********************** Pool
Tuning de Memória: Percentual de Memória Livre na Shared
****************** Área Total AREA Bytes Totais -------------------- ---------------shared_pool_size 25,165,824 large_pool_size 4,194,304 java_pool_size 4,194,304
Oracle 9i Fundamental
417
****************** Área Livre AREA Bytes Livres -------------------- ---------------shared pool 21,999,452 large pool 4,194,304 java pool 4,194,304 **********************
Tuning de Memória: SQL Area
Efetuar tuning na SQL AREA caso o percentual do gethitratio estiver abaixo do 90%. %GetHitRatio -----------98,4403392
Caso o PINHITRATIO fique muito próximo ou superior a 1 (um) indica que está havendo muito parse de sql que já está em memória EXECUCOES RELOADS PINHITRATIO ---------- ---------- ----------91607 35 ,038206687 **********************
Tuning de Memória: Database Buffer Cache
Caso o percentual de Leituras em memória em relação a leitura física dos blocos de dados for menor que 90% existe algum problema no data base buffer cache. CACHE HIT RATIO --------------83,634711 **********************
Tuning de Memória: Redo Log Buffer
Esta rotina verifica o redo log buffer. Caso o valor seja superior a 1(um) deve-se aumentar o redo log buffer Percentual ---------0.00000 **********************
Tuning de Memória: Ordenações em disco e memória
Aumentar parâmetro SORT_AREA_SIZE caso o percentual seja maior que 10% Em disco Em memória Percentual ---------- ---------- ---------0 7,733 0.00000 **********************
Distribuição de tabelas
DONO TABELAS -------------------- ---------SYS 342 SYSTEM 132 OLAPSYS 58 …
Oracle 9i Fundamental
418
DBAACAD MONICK XDB ORDSYS SCOTT OUTLN PM
6 5 5 5 4 3 2
O relatório apresentado, quando emitido regularmente, permite alimentar dados históricos que revelem a evolução do banco. Outras tarefas devem ser desempenhadas freqüentemente: Verificação do sucesso das cópias de segurança, inclusive para fita; Eliminação de Archived Redo Log Files que já tenham sido copiados; Atualização das estatísticas; Recriação de índices; Consulta ao arquivo de alertas; Verificação dos arquivos de trace.
Oracle 9i Fundamental
419
ANOTAÇÕES
Oracle 9i Fundamental
420
APÊNDICE E: STANDBY DATABASES E.1 - Fundamentos Em locais onde seja necessária a disponibilidade permanente dos dados recomenda-se a implantação de um Standby Database (Banco de Dados de Prontidão), preferencialmente em outro Servidor físico. Trata-se de um recurso oferecido pelo Oracle Server (a partir da versão 7.3), que consiste em manter dois Servidores trabalhando ininterruptamente; um atuando como cópia do outro. Caso o principal fique inutilizável, rapidamente podese disponibilizar o Standby. Com isto, a duração do downtime tende a ser mínima. Além do maior poder de recuperação, a presença de um Servidor Standby proporciona outra inegável vantagem: pode-se utilizá-lo como fonte para emissão de relatórios administrativos. Com isto, alivia-se a carga de trabalho sobre o principal. Basicamente o processo consiste em aplicar as transações armazenadas nos Archived Redo Log Files do Servidor principal no Standby. Existem três modos de operação: Recovery
Read-Only Activated
Servidor Standby disponível apenas para que sejam aplicadas recuperações provenientes do principal. Pode estar nos modos Manual, em que aplicam-se manualmente as recuperações, ou Automático, no qual se transferem os Archived Redo Log Files automaticamente. Interrompe-se o modo de recuperação, permitindo consultas. É possível alternar para o modo Recovery. Deixa de ser Standby propriamente dito e passa a trabalhar como um Servidor normal, sem qualquer vínculo com o principal. Não é possível mudar este estado para os anteriores.
A criação do ambiente com os dois Servidores interligados pode ser levada a cabo com a funcionalidade Oracle Data Guard, que ainda permite automatizar diversos aspectos da manutenção dos Servidores Standby (podem existir até dez). Ela pode ser utilizada via comandos SQL, parâmetros de instância ou ainda pela ferramenta Data Guard Manager, disponível em modo linha de comando ou interface gráfica, embutida no produto Oracle Enterprise Manager.
Oracle 9i Fundamental
421
Neste apêndice não abordaremos a Oracle Data Guard. Para conhecê-la, por favor recorra à documentação oficial (Oracle 9i Data Guard Concepts and Administration). Para que seja possível implantar uma solução Standby, alguns requisitos devem ser atendidos: • Bancos devem ter o mesmo nome; • Ainda que não seja obrigatório, recomenda-se que a estrutura de diretórios de ambos Servidores seja idêntica; • Antes de iniciar o processo de implantação, já deve existir uma instância no Servidor Standby; • Deve-se instalar a mesma versão do Oracle Server em ambos Servidores; • O Sistema Operacional deve ser o mesmo em ambos Servidores, inclusive quanto a patches (Services Packs); • O Banco de Dados Principal deve estar em Modo Archive; • A quantidade e o tamanho de Redo Log Files devem ser idênticos em ambos BDs.
E.2 - Parâmetros no Banco Principal Os Archived Redo Log Files desempenham um papel crítico para os Standby Databases, já que são responsáveis por armazenar as transações gravadas nos Redo Log Files. Sendo assim, costuma-se multiplexar os Archived Logs para minimizar a possibilidade de perdas. Em vez dos parâmetros LOG_ARCHIVE_DEST e LOG_ARCHIVE_DUPLEX_DEST, costuma-se utilizar LOG_ARCHIVE_DEST_n e LOG_ARCHIVE_DEST_STATE_n, em que n pode variar entre 1 e 10. A seguir, realiza-se tal troca para a instância ACAD9, mas em vez de alterá-los um a um, acompanha-se o seguinte roteiro alternativo, conectados como SYS: • Gerar Arquivo de Parâmetros Texto a partir do Arquivo de Parâmetros Binário: create pfile = 'initacad9.ora' from spfile = 'spfileacad9.ora';
Editar o arquivo texto recém-criado e realizar a troca propriamente dita93; • Fechar a instância e abri-la utilizando o Arquivo de Parâmetros Texto:
•
Shutdown startup pfile = 'E:\oracle\ora92\database\initacad9.ora'
93
Caso seja utilizado o Bloco de Notas como editor para realizar a troca, habilite a quebra de linha automática (Format, Word Wrap).
Oracle 9i Fundamental
422
• Atualizar o Arquivo de Parâmetros Binário: create spfile = 'spfileacad9.ora' from pfile ='initacad9.ora';
• Fechar a instância e abri-la utilizando o Arquivo de Parâmetros Binário recém-atualizado: shutdown startup
O trecho de INITACAD9 em que constariam as definições dos parâmetros LOG_ARCHIVE_DEST_n teria o seguinte aspecto: *.log_archive_dest_1='LOCATION=E:\oracle\ora92\database\archive MANDATORY' *.log_archive_dest_2='LOCATION=C:\Dest_Log_2' *.log_archive_dest_3='LOCATION=D:\Dest_Log_3' *.log_archive_dest_4='SERVICE=STANDBY'
Observações • Não podem existir brancos ao redor do operador de atribuição (=); • A palavra reservada MANDATORY indica que, enquanto o Archived Redo Log File não for gerado na citada localização, o Banco ficará suspenso. O comportamento padrão é OPTIONAL, que apenas gera um aviso caso o Log File não possa ser gravado. Recomenda-se enfaticamente que exista ao menos um destino mandatório; • Em vez de gravar um Archived Redo Log File em algum diretório, pode-se enviá-lo a outro Servidor. Isto, aliás, representa a essência dos Bancos de Dados de prontidão. No exemplo anterior, STANDBY significa um host string válido que permite acesso a uma outra instância. O trecho de INITACAD9 em que constariam as definições dos parâmetros LOG_ARCHIVE_DEST_STATE_n teria o seguinte aspecto: *.log_archive_dest_state_1=ENABLE *.log_archive_dest_state_2=ENABLE *.log_archive_dest_state_3=ENABLE *.log_archive_dest_state_4=DEFER
Observações • Para cada LOG_ARCHIVE_DEST_n deve existir um LOG_ARCHIVE_DEST_STATE_n equivalente; • A palavra reservada DEFER indica que os Archived Logs ainda não precisarão ser gravados no destino associado. Isto desobriga a instância Standby de estar disponível durante a abertura do Banco de Dados principal, o que não chega a ser um problema, já que o parâmetro é dinâmico.
Oracle 9i Fundamental
423
E.3 - Parâmetros no Banco Standby Uma vez criada a instância que desempenhará o papel Standby, seu arquivo de parâmetros também deve sofrer algumas alterações: STANDBY_ARCHIVE_DEST
Igual ao LOG_ARCHIVE_DEST; representa o local onde serão depositados os Log Files a serem aplicados.
DB_FILE_NAME_CONVERT
Utilizado caso existam diferenças entre as localizações físicas dos Data Files em ambas instâncias.
LOG_FILE_NAME_CONVER T
Utilizado caso existam diferenças entre as localizações físicas dos Redo Log Files.
Veja como ficaria o trecho do Arquivo de Parâmetros do Banco Standby: *.log_archive_start = true *.log_archive_dest='D:\oracle\admin\Archive' *.standby_archive_dest='D:\oracle\admin\Archive' *.db_file_name_convert = ('E:\ORACLE\ORADATA\ACAD9\XDB01.DBF', 'D:\ORACLE\ORADATA\ACAD9\XDB01.DBF', 'E:\ORACLE\ORADATA\ACAD9\USERS01.DBF', 'D:\ORACLE\ORADATA\ACAD9\USERS01.DBF', 'E:\ORACLE\ORADATA\ACAD9\UNDOTBS01.DBF', 'D:\ORACLE\ORADATA\ ACAD9\UNDOTBS01.DBF', 'E:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF', 'D:\ORACLE\ORADATA\ACAD9\TOOLS01.DBF', 'E:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF', 'D:\ORACLE\ORADATA\ACAD9\SYSTEM01.DBF', 'E:\ORACLE\ORADATA\ACAD9\ODM01.DBF', 'D:\ORACLE\ORADATA\ACAD9\ODM01.DBF', 'E:\ORACLE\ORADATA\ACAD9\INDX01.DBF', 'D:\ORACLE\ORADATA\ACAD9\INDX01.DBF', 'E:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF', 'D:\ORACLE\ORADATA\ACAD9\EXAMPLE01.DBF', 'E:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF', 'D:\ORACLE\ORADATA\ACAD9\DRSYS01.DBF', 'E:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF', 'D:\ORACLE\ORADATA\ACAD9\CWMLITE01.DBF') db_file_name_convert = ('E:\ORACLE\ORADATA\ACAD9\REDO03.LOG', 'D:\ORACLE\ORADATA\ACAD9\REDO03.LOG', 'E:\ORACLE\ORADATA\ACAD9\REDO02.LOG', 'D:\ORACLE\ORADATA\ACAD9\REDO02.LOG', 'E:\ORACLE\ORADATA\ACAD9\REDO01.LOG', 'D:\ORACLE\ORADATA\ACAD9\REDO01.LOG')
Observação • Perceba que o Banco Standby também deve possuir o Modo ArchiveLog ligado, já que será necessária a geração de Archived Log Files numa eventual migração do Standby em principal.
E.4 - Implantando Modo Manual Para implantar o Modo Standby Recovery Manual, deve-se observar o seguinte roteiro: Oracle 9i Fundamental
424
1) Copiar Arquivo de Controle do Banco principal, mas com carcterísticas de prontidão (não precisa estar conectado como SYS): alter database create standby controlfile as 'e:\backup\control.bak';
2) Realizar um Cold Backup do Banco principal. Uma vez concluída a cópia, pode-se abrir novamente o Banco; 3) Copiar para o Servidor Standby os Data Files do Cold Backup produzido no passo anterior e o Arquivo de Controle gerado no passo um (NÃO levar os Redo Log Files). Deve-se levar também o Arquivo de Senhas; 4) Gerar tantas cópias do Control File produzido no passo um quantas houver no parâmetro CONTROL_FILES da instância Standby. Naturalmente, os nomes também devem ser os mesmos; 5) Caso a instância Standby esteja aberta, deve ser fechada. Restaurar os Data Files trazidos no passo três, bem como os Arquivos de Controle do quarto passo. Abrir o Banco em modo nomount: startup nomount;
6) Montar o Banco Standby: alter database mount standby database;
7) Deixar o banco em estado de recuperação: recover standby database;
O comando recover lê os arquivos que constem no diretório indicado pelo parâmetro STANDBY_ARCHIVE_DEST. Para dar continuidade ao processo, devem-se copiar manualmente os Archived Redo Log Files gerados pelo Servidor principal para o diretório indicado em STANDBY_ARCHIVE_DEST. Recomenda-se automatizar de alguma forma esta transferência, quiçá criando um arquivo de lote que realize a cópia.
E.5 - Implantando Modo Automático Antes de implantar o Modo Standby Recovery Automático, deve-se certificar a conexão entre o Servidor principal e o Standby, ou seja, deve existir um host string no principal que represente o Standby. Consulte o Capítulo 26, item 26.3 para criar host strings. Para implantar o Modo Standby Recovery Automático, execute os passos 1 a 6 do item E.4 e execute o comando: recover managed standby database timeout tempo;
Oracle 9i Fundamental
425
Em que tempo representa o intervalo em minutos por esperar até que "apareça" outro Archived Redo Log File proveniente do Servidor principal. Resta habilitar a geração de Archived Redo Log Files no Banco principal emitindo um comando semelhante a este: Alter system set log_archive_dest_state_4=ENABLE scope=both;
Uma forma de verificar se a transferência está acontecendo consiste em investigar a visão V$LOG_HISTORY. Ela mostra o número do último archive aplicado e deve ser igual em ambos Servidores. Outro teste: • Anotar último Archive Redo Log File gerado; • Criar tabela no Servidor principal; inserir linhas; commit; alter system switch
logfile;
• Verificar se Archive foi gerado; • Verificar se Archive foi transportado; • Verificar se Archive foi aplicado (V$LOG_HISTORY); Alguns cuidados devem ser tomados durante a gerência do processo: • Não gere novos Archived Redo Log Files enquanto o Servidor Standby estiver fechado. Primeiro ele não será transportado e depois não será lido, já que fará referência a um caminho inexistente. Caso seja gerado um Archive enquanto o Standby estiver fechado, siga o roteiro: • Em uma outra sessão, conectado como SYS: recover managed standby database cancel; shutdown immediate
• Recrie o Control File no principal (primeiro passo E.4); • Transporte-o para o Servidor Standby; • Repita o quarto passo de E.4 (cópia e troca de nome do Arquivo de Controle); • No Servidor Standby crie um diretório homônimo ao destino dos Archived Redo Log Files no Servidor de produção. Copie para lá os novos Archived Redo Log Files; • Finalmente, no Standby: recover managed standby database timeout tempo; O mais importante é perceber que o Standby não pode estar fechado nunca!
E.6 - Implantando Modo Leitura Estando o Servidor Standby em Modo Manual, basta emitir o comando: alter database open read only;
Para voltar ao Modo Standby Recovery Manual, conecte-se como SYS e emita os comandos: Oracle 9i Fundamental
426
shutdown immediate startup nomount alter database mount standby database;
Copiar Archived Redo Log Files do Servidor principal, e: recover standby database;
Observe que uma vez derrubada a instância, o roteiro é idêntico ao mostrado E.4, a partir do passo 5. O fato de estar habilitado somente para leitura evidencia-se no conteúdo do campo ENABLED da visão V$DATAFILE. Estando o Servidor Standby em Modo Automático, conecte-se como SYS e emita os comandos: recover managed standby database cancel; alter database open read only;
Para voltar ao Modo Standby Recovery Automático, conecte-se como SYS e emita os comandos: shutdown immediate startup nomount alter database mount standby database; recover managed standby database timeout tempo;
E.7 - Desativando Servidor Standby Quando ocorrer uma perda no Servidor principal cuja, recuperação terá duração proibitiva, ativa-se o Servidor Standby, que deve ter sido montado em forma exclusiva (default). Uma vez ativado um Banco que já foi Standby não é mais possível voltá-lo ao Modo Standby, seja Manual ou Automático. Para ativar um Banco Standby, acompanhe o seguinte roteiro: • Caso seja possível, armazene o Redo Log File corrente: alter system switch logfile;
• Mova-o para o Servidor Standby e aplique-o antes de ativar o Banco. • Cancele o modo de recuperação: recover managed standby database cancel
• Emita o comando: alter database activate standby database;
• Derrube a instância: shutdown immediate
• Se possível, faça um Cold Backup; • Finalmente: startup mount alter database open;
E.8 - Conclusões Oracle 9i Fundamental
427
A técnica que implementa Bancos de Dados Standby constitui uma ótima decisão a ser tomada em ambientes em que a disponibilidade dos dados for um fator crítico, entretanto a gerência do processo resulta algo trabalhoso, como visto neste apêndice. Felizmente, existem outras técnicas que também propiciam alta disponibilidade dos dados, porém a custos mais elevados: Log Transport Services
Faz com que a criação de Archived Redo Log Files no Banco de prontidão seja automática e implementada pelo próprio processo LGWR. Apesar de conferir mais segurança, paga-se um preço alto de performance.
Oracle Data Guard
Como já comentado, permite automatizar desde a criação de Bancos Standby até a transformação de um deles em Banco principal. Deve ser adquirido à parte, no produto Oracle Enterprise Manager.
Replicação
Gera redundância de dados entre Bancos, objetivando reduzir distâncias físicas entre clientes e os dados desejados. Também implementada via Oracle Enterprise Manager, ferramenta Replication Management Tool.
Real Application Clusters
Dois ou mais servidores vistos logicamente como um e compartilhando recursos (memória, disco, cpu, etc.). Caso um nó falhe, os trabalhos não serão interrompidos. Existem sete manuais sobre o assunto na Documentação oficial Oracle.
Oracle 9i Fundamental
428
APÊNDICE F: APOIO NA INTERNET A Internet hoje, sem dúvida alguma, constitui a maior fonte de conhecimento da humanidade. Não existe artigo, livro ou enciclopédia que possa encerrar a plenitude da Internet, portanto não consultá-la constitui grave desleixo. O que impressiona na Internet é o seu dinamismo. Provavelmente, quando o leitor estiver lendo este apêndice, alguns endereços apresentados em seguida nem existam mais e outros tenham surgido. Precisaríamos ter um livro também dinâmico que acompanhasse o ritmo desenfreado da Grande Rede. Quem sabe os livros, dentro de pouco tempo, não terão também este dinamismo? Este apêndice reúne diversos sites que têm correlação com os assuntos tratados neste livro. Não se objetiva apresentar uma lista definitiva de endereços, fato que seria impossível devido ao dinamismo já citado. A pesquisa que resultou nestas listas analisou mais de 100 sites em busca de informações complementares ao livro. Recomendo que sejam visitados aos poucos e alguns, como os que oferecem scripts, recebam visitas regulares. Constam vários sites de fabricantes de ferramentas de apoio ao trabalho do DBA (BMC, QUEST, EMBARCADERO, etc.). De uma forma geral, todas permitem realizar download de versões demo, o que deve ser feito para conhecer melhor as ferramentas. A ferramenta utilizada foi o AltaVista (www.altavista.com) e a cadeia de caracteres inicialmente utilizada foi: database and text:(not book) and (oracle9i) and (article or whitepaper) and (DBA)
Muitos sites foram descobertos a partir de outros; pela experiência do autor ou extraídos de diversas edições da bimestral Oracle Magazine. www.
Comentários
Allroundautomations.nl
Oferece o aplicativo PL/SQL Developer.
2.
bmc.com
Dona da família de ferramentas Patrol que, entre outras funções, apóia tarefas de administração e permite realizar importações e exportações entre bases Oracle e outras. Destaque para DBXray.
3.
bradmark.com
Comercializa família de produtos Norad: tarefas de manutenção no banco, acompanhamento, avisos de problemas.
1.
Oracle 9i Fundamental
429
www.
Comentários
4.
compuware.com
Família de produtos DevPartner que apóia o desen-volvimento e administração em bases Oracle. Des-taque para o DBPartner for Oracle.
5.
datamirror.com
Ferramentas de integração entre SGBDRs. Destaque para a dupla DB/XML Transform e DB/XML Vision.
6.
dbazine.com/ch_oracle. html
Artigos, links, desafios.
7.
embarcadero.com
DBArtisan: ambiente gráfico de apoio ao DBA.
8.
google.com
Imprescindível ferramenta de busca. Muito útil ao procurar sugestões para erros, já que devolve sites em que há comentários sobre a solução buscada. Coloque-o na seção de favoritos.
9.
idevelopment.info
Dicas, scripts, certificação.
10.
ioug.com
Página oficial do International Oracle Users Group-Americas.
11.
lazydba.com
Oportunidades de emprego; artigos; scripts.
12.
leccotech.com
SQL Expert: identifica problemas de performance e sugere soluções. DB Expert: auxilia o DBA em suas tarefas.
13.
maop.org/sig-dba
Página oficial da associação de DBAs MAOP (Mid Atlantic Association of Oracle Professionals): eventos, artigos, scripts, análise de livros.
14.
datadirecttechnologies.com
Oferece o DataDirect que substitui com ganhos o Net8 ou SQL*Net para conexão entre clientes e servidores.
15.
oracle.com
Porta de entrada para o mundo Oracle.
16.
oracle.com/oramag
Imprescindível publicação bimestral oficial da Oracle com assinatura grátis. Traz diversos artigos que abrangem inúmeros tópicos do mundo Oracle: desde dicas de programação, técnicas de utilização de ferramentas de apoio na Web até artigos especializados na administração de bases de dados.
17.
oraclefans.com
Scripts, dicas, chat, links, análise de livros, oportunidades de trabalho.
18.
www.oracle.matrix. com.br
Página nacional com scripts, links, artigos e dicas.
Oracle 9i Fundamental
links,
sugestões
para
430
www.
Comentários
19.
orafaq.com
Relação de FAQs sobre inúmeros assuntos relacionados com bases Oracle.
20.
oraworld.com
Possui diversas dicas sobre certificação: dúvidas freqüentes, links para cursos on-line; simulados, etc.
21.
pocketdba.com
Oferece o PocketDBA, ferramenta de apoio ao DBA a ser executada em hand helds.
22.
precise.com
Ferramentas de otimização de SQL.
23.
quest.com
Fabricante de diversas ferramentas de apoio das quais se destacam o SQL Navigator, utilizado neste livro, e Spotlight. Recomendase enfaticamente o teste desses produtos.
24.
senware.com
Comercializa a ferramenta AutoDBA, que automatiza diversas tarefas administrativas.
tusc.com
Artigos, análise de livros, serviços de administração de dados remota, permite o download de diversas apresentações nos formatos PPT e DOC.
revealnet.com
Foi adquirida pela Quest no final de 2001, assim acontecerá um desvio para a Quest. Oferece bases de conhecimento para diversos tópicos, entre os quais PL/SQL e administração.
27.
searchdatabase.com
Teleconferências (webcasts), ferramenta de busca por meio do mecanismo implementado pelo google (a busca de DBMS_FLASHBACK resultou em oito entradas), artigos, links, análise de livros, dicas.
28.
simulus.com
SIMperformance que avalia a performance geral.
29.
Softcert.com
Oferece simulados demo para programas de certificação Oracle (OCA, OCP e OCM).
30.
softwarejobs.com
Newsletter para profissionais em Sybase; oportunidades de trabalho.
31.
teamdba.com
Links, dicas, problemas comentados, produtos. Aborda Oracle, Sybase e SQL Server. É preciso cadastro prévio. Associação grátis.
25.
26.
Oracle 9i Fundamental
Oracle,
431
www.
Comentários
32.
http://otn.oracle.com94
Porta de entrada para o OTN (Oracle Technical Network) em que são oferecidos exemplos de código, artigos e scripts, além da documentação oficial. Requer cadastro gratuito prévio.
33.
uaex.edu/srea
site da Universidade de Arkansas com dicas, truques e scripts.
34.
virtualdba.com
Possibilita a consulta e compra de diversos produtos Oracle, entre outros fabricantes.
35.
wtainc.com/whitepap.htm Artigos
Talvez o site mais importante de todos, aquele que proporciona mais conhecimento sobre Oracle9i e cujas visitas devem ser regulares, seja o da documentação oficial: http://otn.oracle.com/docs/products/oracle9i/doc_library/release2/index.htm
Há mais de cem manuais, porém alguns merecem destaque: Administrator’s Guide
Tarefas do DBA, criação de Bancos, gerência de instân-cias, Arquivos, LogMiner, Tablespaces, SMU, Tabelas & Índices, Segurança.
Application’s Guide
Grupo de cinco manuais dando desenvolvimento de aplicações.
Backup Concepts
and
Recovery
Sedimenta conceitos Recuperação.
sobre
ênfase Backup
ao e
Concepts
Traz definições sobre inúmeros conceitos; tratase de um imenso glossário enriquecido.
Error Messages
Relação de todas as mensagens de erro e sugestões de como resolvê-las.
Master Glossary
Conjunto de links para demais manuais.
New Features
Novos recursos introduzidos nas versões 9.01 e 9.2.
PL/SQL Reference
94
Developer
User’s
and
Comandos e funções PL/SQL explicados com sintaxe e exemplos.
Recovery Manager
Há três manuais: Quick Reference, Reference e User’s Guide.
SQL Reference
Comandos e funções SQL explicados com sintaxe e exemplos.
Supplied PL/SQL Packages and Type Reference
Relação de Packages embutidos com descrições e exemplos de utilização.
Este site não é acessado com o prefixo http://www. Também pode ser achado a partir de www.oracle.com em Communities.
Oracle 9i Fundamental
432
Utilities
Detalha os principais utilitários, incluindo IMP e EXP.
Oracle 9i Fundamental
433
APÊNDICE G: INSTALAÇÃO NO WINDOWS 2000 G.1 - Fundamentos O presente apêndice fornece subsídios à instalação Oracle sob Windows 2000. Ela pode acontecer a partir de CDs fornecidos pelo fabricante ou dos três arquivos em formato .ZIP disponíveis em: http://otn.oracle.com/software/products/oracle9i/content.html.
Qualquer que seja o método escolhido, pressupõe-se que o produto já tenha sido legalmente adquirido. Caso se escolha copiar os arquivos disponíveis na Internet, devem-se ressaltar três pontos: os três arquivos ocupam juntos 1.338 MB (584, 512 e 242 MB respectivamente); deve-se possuir um registro na Oracle Technology Network (OTN), aliás, gratuito e imprescindível. Finalmente, lembre-se que o conteúdo do site da Oracle possui grande dinamismo, portanto ninguém garante que os arquivos permanecerão disponíveis para sempre. Antes de efetuar a instalação, recomenda-se ler cuidadosamente a documentação referente ao assunto no manual Installation Guide for Windows. A versão utilizada foi a 9.2, também conhecida como Oracle Server 9i Release II.
G.2 - Requerimentos de Hardware Servidor
Cliente
PC baseado em processador Pentium 166 ou superior. RAM: mínimo 128 MB; sugerido: 512 MB. Espaço em disco: dependendo da instala-ção escolhida, pode chegar a 4,8 GB (Enterprise ou Personal Editions em discos FAT). Em discos NTFS (recomendável), não passa de 3 GB.
PC baseado em processador Pentium 166 ou superior. RAM: mínimo 64 MB, sugerido 128 MB. Para espaço em disco aproximado: 800 MB.
G.3 - Requerimentos de Software Servidor
Cliente
Windows 2000. Windows 2000 Recomendável último Service Pack (exige- superior). Windows 9x/XP. se pelo menos o primeiro) Oracle 9i Fundamental
(Workstation
ou
434
Para ter acesso à documentação na Internet, pede-se o Internet Explorer 5.0 ou superior (6.0 para XP).
G.4 - Processo Siga este roteiro: • Conecte-se ao Windows 2000 como algum membro do grupo de administradores; • Encerre todas as aplicações e também os serviços Oracle, caso existam; • Insira o primeiro CD de instalação ou execute o arquivo Setup, presente no diretório em que estão descompactados os arquivos provenientes do primeiro ZIP. Uma vez inserido o CD, caso a instalação não entre imediatamente, execute o programa Setup, residente na raiz do CD; • Na tela de boas-vindas é possível desinstalar algum produto existente, ou começar uma nova instalação, clicando em Próximo; • Informe a origem dos arquivos por instalar e os dados para o Oracle Home (nome, diretório de instalação dos produtos e idioma). Recomenda-se aceitar valores sugeridos. Ao clicar em Próximo, inicia-se a criação da lista de produtos por instalar. Ainda é possível escolher o idioma a ser adotado; • Escolhida a opção Oracle9i Database 9.2, pede-se a edição: Enterprise, Standard ou Personal. Caso a instalação ocorra a partir dos CDs, estas opções dependerão do CD utilizado; • A próxima caixa de diálogo permite caracterizar o banco exemplo. Pode-se, inclusive, escolher não criá-lo. As telas que seguem caracterizarão o banco exemplo (nome, sid, diretório destino, etc.); • A última interação exibe um resumo das escolhas feitas. A partir deste ponto, os arquivos começarão a ser copiados e os programas, registrados.
G.5 - Verificação Existem várias alternativas para confirmar a instalação: • Ative o programa Universal Installer (Start, Programs, Oracle Installation Products) e verifique os programas instalados pressionando em Produtos Instalados:
Oracle 9i Fundamental
435
Painel de Controle, Administrative Tools, Services: confira se o serviço OracleServiceSID (em que SID representa o Banco recémcriado) está como Started. Verifique também OracleOraHome92Agent (ele representa o Oracle Home). Conexões a partir de clientes ou para outras instâncias também exigirão o OracleOraHome92TNSListener; • Verifique os programas no menu Start, Programs, Oracle – OraHome92; • Ative o SQL*Plus Worksheet (pasta Application Development) e conecte-se como usuário SYSTEM, senha fornecida na criação do banco exemplo, ou a que tenha sido fornecida durante a criação do Banco. Supondo que tenha sido criado o Banco de Dados ACAD9, a estrutura de diretórios gerada terá o seguinte aspecto: •
Oracle 9i Fundamental
436
O diretório \ORACLE recebe a denominação genérica de oracle base; já \ORACLE\ORA92 será oracle home (pode existir mais de uma home). Os arquivos de ACAD9 estarão sob \ORACLE\ORADATA (Data Files), \ORACLE\ADMIN (alertas, traces) e \ORACLE\ORA92\DATABASE (parâmetros e senhas). Uma vez criado o Banco, nada impede que se implementem os ditames do padrão OFA para melhorar o acesso a disco (mais detalhes no Capítulo 20, item 20.2).
G.6 - Instalação no Cliente Ao instalar em Clientes Oracle, deve-se escolher o tipo de instalação Client. Opcionalmente, podem-se instalar as ferramentas de apoio à administração, tal como Enterprise Manager Console. Uma vez concluída a instalação, deve-se criar uma Host String, tal como explicado no Capítulo 26, item 26.3.
Oracle 9i Fundamental
437