Banco de Dados - Teoria e Desenvolvimento
Banco de Dados - Teoria e Desenvolvimento
Banco de Dados - Teoria e Desenvolvimento
Teoria e Desenvolvimento
Banco de Dados
Teoria e Desenvolvimento
1
Seja Nosso Parceiro no Combate à Cópia Ilegal
A cópia ilegal é crime. Ao efetuá-la, o infrator estará cometendo um grave erro, que é inibir
a produção de obras literárias, prejudicando profissionais que serão atingidos pelo crime
praticado.
Junte-se a nós nesta corrente contra a pirataria. Diga não à cópia ilegal.
Ao preencher e remeter a ficha de cadastro constante em nosso site, você passará a rece-
ber informações sobre nossos lançamentos em sua área de preferência.
Conhecendo melhor nossos leitores e suas preferências, vamos produzir títulos que aten-
dam suas necessidades.
Fale Conosco!
1. E-mail: producao@erica.com.br
3. Carta: Rua São Gil, 159 - Tatuapé - CEP 03401-030 - São Paulo - SP
Banco de Dados
Teoria e Desenvolvimento
1ª Edição
São Paulo
Editora Érica Ltda.
3
Copyright © 2009 da Editora Érica Ltda.
Todos os direitos reservados. Proibida a reprodução total ou parcial, por qualquer meio ou processo,
especialmente por sistemas gráficos, microfílmicos, fotográficos, reprográficos, fonográficos, videográficos,
internet, e-books. Vedada a memorização e/ou recuperação total ou parcial em qualquer sistema de
processamento de dados e a inclusão de qualquer parte da obra em qualquer programa juscibernético. Essas
proibições aplicam-se também às características gráficas da obra e à sua editoração. A violação dos direitos
autorais é punível como crime (art. 184 e parágrafos, do Código Penal, conforme Lei no 10.695, de 07.01.2003)
com pena de reclusão, de dois a quatro anos, e multa, conjuntamente com busca e apreensão e indenizações
diversas (artigos 102, 103 parágrafo único, 104, 105, 106 e 107 itens 1, 2 e 3 da Lei no 9.610, de 19.06.1998,
Lei dos Direitos Autorais).
O Autor e a Editora acreditam que todas as informações aqui apresentadas estão corretas e podem ser utilizadas
para qualquer fim legal. Entretanto, não existe qualquer garantia, explícita ou implícita, de que o uso de tais
informações conduzirá sempre ao resultado desejado. Os nomes de sites e empresas, porventura mencionados,
foram utilizados apenas para ilustrar os exemplos, não tendo vínculo nenhum com o livro, não garantindo a sua
existência nem divulgação. Eventuais erratas estarão disponíveis para download no site da Editora Érica.
Conteúdo adaptado ao Novo Acordo Ortográfico da Língua Portuguesa, em execução desde 1º de janeiro de 2009.
“Algumas imagens utilizadas neste livro foram obtidas a partir do CorelDRAW X3 e X4 e da Coleção do
MasterClips/MasterPhotos© da IMSI, 100 Rowland Way, 3rd floor Novato, CA 94945, USA.”
Bibliografia.
ISBN: 978-85-365-1168-9
Produto: Oracle
Fabricante: Oracle Corporation
Site: http://www.oracle.com/global/br/index.html
Produto: MySQL
Fabricante: Sun Microsystems, Inc.
Site: http://br.sun.com
Produto: PostgreSQL
Fabricante: PostgreSQL, Inc.
Site: www.postgresql.com
5
Requisitos de Hardware e de Software
Requisitos de Software (para utilização dos exemplos abordados nos capítulos 4, 5 e 17)
Sistema operacional Windows XP ou superior
Compilador de linguagem C/C++, como o Turbo C/Turbo C++ da Embarcadero
Compilador da linguagem Pascal, como o Turbo Pascal da Embarcadero
Especialmente à minha querida esposa Lucimara e aos meus dois filhos Brian e Liam;
Às pessoas que direta ou indiretamente influenciaram meu modo de ser e de pensar: meus pais pela
educação que me deram, meus irmãos que sempre estiveram ao meu lado nos momentos difíceis
(quando solteiro), meus demais familiares e os de minha esposa;
Não poderia esquecer meus avós (paternos e maternos), meu sogro e minha sogra que já partiram
desta vida;
Por fim, ao leitor ávido por conhecimentos e aprimoramento profissional.
7
Agradecimentos
A DEUS por tudo que me tem proporcionado diariamente e por me mostrar o caminho certo. Sua
presença é fundamental para que eu possa realizar meus trabalhos e concretizar minhas ideias;
Em igual medida a todos da Editora Érica (sem exceção) pelos votos de confiança nesses doze anos
de convivência. Muito obrigado mesmo, meus eternos amigos.
9
Capítulo 6 - Meios de Armazenamento de Dados ..................................................................... 104
6.1. Os Tipos de Memórias......................................................................................................................104
6.2. As Organizações dos Arquivos........................................................................................................105
6.3. Exercícios ...........................................................................................................................................107
11
17.6. Dificuldades na Implantação de um Ambiente Cliente/Servidor.............................................220
17.7. Exercícios .........................................................................................................................................222
Bibliografia..................................................................................................................................................... 281
Não há como negar que os sistemas de bancos de dados são os principais softwares na área de
informática e os responsáveis pela existência de incontáveis aplicativos gerenciais. A demanda por
mais recursos e melhor desempenho tem levado os produtores a implementar aprimoramentos em
seus produtos em tempo cada vez mais curto.
Praticamente todo tipo de informação que existe no mundo real é passível de ser armazenado num
banco de dados, seja uma pequena coleção de CDs do acervo pessoal de músicas, o cadastro de
funcionários de uma grande empresa nacional ou um sistema de gestão comercial e financeira.
Este livro foi planejado tendo em vista o profissional de informática que deseja saber mais como
funciona um banco de dados, e não ser apenas um usuário do sistema. É uma versão revisada da obra
anterior, Fundamentos de Banco de Dados, com os capítulos reorganizados e assuntos novos
adicionados, como álgebra relacional, organização de arquivos de dados, projeto conceitual de banco
de dados e diagrama entidade-relacionamento.
Um assunto interessante, principalmente aos programadores, são os métodos de ordenação e de
pesquisa de dados abordados nos capítulos 4 e 5, com apresentação de códigos-fonte escritos nas
linguagens C e Pascal que demonstram a aplicação prática dos conceitos relacionados com essas
técnicas.
Por ser bastante didático, o texto é de fácil entendimento, uma vez que se procurou evitar o uso de
termos técnicos em inglês ou mesmo fórmulas e expressões matemáticas para explicar determinados
assuntos. Assim, sempre que possível, o termo foi substituído por seu similar na língua portuguesa.
Mesmo os apresentados em inglês aparecem destacados e com a tradução literal entre parênteses.
São apresentados também exercícios ao fim de cada capítulo, com o objetivo de revisar os conceitos
estudados. No final do livro há um glossário que pode auxiliar bastante em caso de dúvidas referentes
a siglas ou termos técnicos.
Essas características tornam o material indicado para adoção em cursos ligados à área de informática,
mas também não deixa de ser uma opção para o profissional que deseja aprofundar-se no estudo de
bancos de dados.
Espero, realmente, que a viagem que você inicia agora seja bem apreciada. Boa sorte!
O autor
13
Sobre o Material Disponível na Internet
O material disponível no site da Editora Érica contém respostas dos exercícios, os códigos-fonte dos
exemplos abordados nos capítulos 4 e 5 em C e Pascal, um programa executável que demonstra de
forma animada os métodos de ordenação abordados no capítulo 4 e uma planilha em Excel com a
normalização de dados na primeira, segunda e terceira formas normais.
É necessário ter instalados na máquina um compilador C e Pascal (como o Turbo C/Turbo C++ e o
Turbo Pascal), Excel 2000 ou versão mais recente e AcrobatReader 8 (ver requisitos da página 6).
Exercicios.exe - 369 KB
William Pereira Alves é autor de diversos livros da área de informática desde 1992, já conta com
mais de 50 obras escritas que abrangem, principalmente, as áreas de linguagens de programação
(Delphi, C/C++, Visual Basic), bancos de dados (Access), editoração gráfica (CorelDRAW, Flash,
Fireworks e Blender), desenvolvimento de sites (Dreamweaver e GoLive) e de aplicações para
Palm/Pocket PC.
Atuante da área de informática desde 1984, trabalhou na Cia. Energética de São Paulo (CESP) e na
Eletricidade e Serviços S.A. (Elektro) no desenvolvimento de sistemas aplicativos para os departamen-
tos comercial e de suprimento de materiais, inclusive com a utilização de coletores de dados eletrô-
nicos e leitura de códigos de barras.
Criou e implantou um sistema completo de leitura de medidores de energia que utiliza equipamentos
portáteis (Palms), para uma concessionária de energia elétrica.
15
16 Banco de Dados - Teoria e Desenvolvimento
Parte I
História e Fundamentos
de Banco de Dados
O homem começou a fazer registro de informações em O papel e os livros ainda são os meios mais comuns de Regis-
pinturas e inscrições nas paredes. trar e divulgar informações.
FIGURA 1.1 FONTE: WWW.SXC.HU FIGURA 1.2 FONTE: WWW.SXC.HU
FIGURA 1.3
Com a invenção dos computadores tudo ficou bem mais fácil. Essa maravilha tecnológica permite que
qualquer informação seja armazenada e recuperada com grande rapidez e facilidade.
Programas de banco de dados talvez sejam os mais antigos já desenvolvidos para computadores.
Antes do desenvolvimento desse tipo de software aplicativo, os programas trabalhavam com arquivos
sequenciais, utilizando os recursos disponíveis no sistema operacional para gravação e leitura dos
dados em disco. Nessa arquitetura, cada aplicação era responsável pela definição e gerenciamento dos
dados, apesar de ainda apresentar vários inconvenientes, sendo os principais:
Ausência de controle de acesso concorrente de vários usuários.
Impossibilidade de se executar mais de um processo ao mesmo tempo num arquivo de dados.
A definição da estrutura do arquivo armazenada no próprio código do aplicativo, o que
significa que os programas controlavam as tarefas de gravação e leitura dos dados no arquivo.
Isso ocasionava uma dependência entre o banco de dados e a aplicação, tornando muito
complexo o processo de manutenção de todo o sistema.
Inconsistência, redundância, dificuldade de acesso e isolamento de dados.
Problemas relativos à segurança dos dados.
Duplicidade de informações entre os vários arquivos.
Aplicação dependente dos dados.
Incompatibilidade dos formatos de arquivos.
FIGURA 1.4
FIGURA 1.5
Outra característica particular desses sistemas é o método de acesso ao arquivo de dados, que fazia
parte do código-fonte, ou seja, as rotinas de leitura e escrita dos dados se encontravam inseridas no
próprio programa. Isso ocasionava uma despadronização total, uma vez que cada aplicativo poderia
trabalhar de forma diferente em relação à metodologia empregada no acesso aos arquivos.
FIGURA 1.6
Informação Dado
Está muito quente A temperatura hoje é de 38 graus
hoje Celsius
Definição Especificação dos tipos de dados, das estruturas das tabelas e das restrições que devem ser impostas aos
dados que serão armazenados.
Construção Processo de acumular os dados num meio de armazenamento totalmente controlado pelo SGBD.
Manipulação Operações como atualização do banco de dados (inclusão, exclusão e alteração de registros) e extração de
dados, como consultas e relatórios impressos.
Um SGBD deve ainda permitir que bancos de dados sejam excluídos ou que sua estrutura seja altera-
da, como adição de novas tabelas/arquivos.
Alguns sistemas de bancos de dados são genéricos, ou seja, permitem que praticamente qualquer tipo de
dado seja armazenado, uma vez que o próprio usuário define a estrutura do arquivo. Este é o caso de
programas como Access, Interbase, MySQL, Oracle etc. Eles são mais flexíveis e poderosos, capazes de
FIGURA 1.9
FIGURA 1.10
Um detalhe importante em bancos de dados relacionais é que pode ser necessário um campo comum
em diversas tabelas, para que seja possível definir relacionamentos entre elas. Para um melhor enten-
dimento, acompanhe os detalhes da Figura 1.11.
FIGURA 1.12
Cada ocorrência num tipo de conjunto relaciona um registro do tipo de registro proprietário com um
ou mais registros (ou mesmo nenhum) do tipo de registro membro. Isso significa que uma ocorrência
pode ser identificada por um registro proprietário ou por qualquer registro membro. A Figura 1.13
apresenta duas ocorrências do tipo de conjunto DEP_FUNC da Figura 1.12.
FIGURA 1.13
Tecnicamente pode-se dizer que o registro proprietário possui um ponteiro que "aponta" para um
registro membro. Esse registro, que é o primeiro do conjunto, "aponta" para outros que também se
relacionam com o mesmo registro proprietário, como numa lista encadeada. Veja a apresentação da
Figura 1.14.
Neste exemplo, o registro de valor "Vendas", do tipo de registro DEPARTAMENTO, aponta para o
primeiro registro do tipo de registro FUNCIONÁRIO, que no caso contém o valor "Bruno de
Almeida". Este aponta para o segundo registro, cujo valor é "Álvaro Dias", que aponta para o terceiro
("Ana Gonçalves") e assim por diante. O último registro ("Dimitry Wavolsk") aponta de volta para o
registro de DEPARTAMENTO, fechando assim o ciclo. Quando um novo registro for adicionado a
FUNCIONÁRIO, ele ocupará a última posição e o ponteiro do registro de valor "Dimitry Wavolsk"
será direcionado a ele.
FIGURA 1.16
FIGURA 1.17
Natureza autodescritiva
Processamento de transações
Ainda com relação aos bancos de dados multiusuários, devido a essa característica de suporte a vários
usuários simultâneos, é preciso que o sistema de gerenciamento possua capacidade de controlar o
acesso concorrente para assegurar que as atualizações efetuadas pelos diversos usuários sejam execu-
tadas de maneira controlada para não ocorrerem erros nos dados.
1.5. Exercícios
1) Qual a forma de registro de informações mais utilizada em todos os tempos (inclusive atual-
mente)?
2) Em que consistia o cartão perfurado?
3) Defina bancos de dados.
4) Que são sistemas gerenciadores de bancos de dados?
5) Quais os tipos de bancos de dados conhecidos?
6) Quais são os critérios para classificar um banco de dados?
7) Quais são as regras definidas por Edgard F. Codd para bancos de dados relacionais?
8) Quais as características do enfoque dos bancos de dados?
FIGURA 2.1
Na segunda categoria encontramos os modelos de dados representativos, cujos conceitos são fáceis de ser
entendidos pelos usuários finais, sem, no entanto, distanciar-se do modo de organização dos dados no
disco. Nessa categoria podemos destacar o modelo de dados relacional muito utilizado pelos principais
SGBDs, desde os gratuitos, como MySQL e PostgreSQL, até os pagos, como Oracle ou SQL Server.
Já nos modelos de baixo nível ou modelos físicos, a descrição da estrutura está mais relacionada com a
maneira utilizada no armazenamento dos dados em disco. Esses modelos normalmente têm como
público-alvo os profissionais da área de informática, como engenheiros, técnicos, analistas, progra-
madores etc.
A descrição da estrutura do banco de dados mencionada anteriormente também é conhecida como
esquema do banco de dados. Ele é definido na fase de projeto do banco de dados, e normalmente não
sofre alterações com tanta frequência. Esses esquemas podem ser representados por diagramas, como
o exemplo da Figura 2.2.
É importante destacar que num diagrama do esquema do banco de dados os atributos que formam as
entidades são apresentados apenas sob os aspectos mais simplificados, sem a preocupação de detalhar
o tipo de dado de cada um dos atributos ou mesmo as relações que devem existir entre as entidades.
FIGURA 2.2
Logo após sua criação física, o banco de dados está completamente vazio, ou seja, não possui nenhum
tipo de dado armazenado. Nessa situação, diz-se que o banco de dados está no estado vazio. Quando
alguns dados são gravados na primeira vez, o banco de dados passa para o estado inicial. A partir de
então, toda vez que o banco de dados sofre qualquer alteração, seja adição de novos registros ou
alteração/exclusão dos que já existem, teremos o estado atual.
Em vista das alterações que o banco de dados sofre periodicamente, os dados existentes num
determinado momento recebem o nome de retrato ou snapshot.
Para tornar mais fácil a visualização das três características importantes dos bancos de dados, a saber,
isolamento de dados e programas, suporte a múltiplas visões e utilização de catálogos, existe o que
chamamos de arquitetura de três esquemas, que tem como objetivo separar aplicações e banco de dados.
A Figura 2.3 apresenta um diagrama que demonstra os níveis em que essa arquitetura pode ser dividida.
FIGURA 2.3
FIGURA 2.4
Há sistemas de banco de dados, como é o caso de alguns servidores SQL, que permitem a criação de
campos calculados. Esse tipo de campo é formado por uma expressão matemática, que envolve outros
campos da própria tabela ou mesmo constantes numéricas. Seu valor é o resultado obtido por meio
dessa expressão. Por exemplo, suponhamos que você tenha uma tabela de pedidos de clientes e nessa
tabela constem campos para entrada da quantidade do produto e o preço unitário. O preço total do
item poderia simplesmente ser obtido multiplicando o valor do campo de quantidade pelo valor do
campo de preço unitário. Em termos simples, a especificação do campo seria parecida com a seguinte
instrução fictícia:
Em alguns sistemas também é possível definir um valor padrão para o campo, o que significa que se o
usuário não fornecer um valor, será assumido o padrão.
Os sistemas mais recentes incluem um novo tipo de dado chamado BLOB (Binary Large Objects -
Objetos Binários Grandes) e permitem o armazenamento de dados não estruturados, como imagens,
sons, vídeos etc. Geralmente os valores de campos BLOB são armazenados separadamente dos
respectivos registros no arquivo de dados, e um ponteiro no registro faz referência a esses valores.
Diversos sistemas permitem que campos do tipo caractere sejam definidos com tamanho fixo ou
variável. No caso de tamanhos fixos, se o usuário entrar com dados cujo comprimento seja menor que
o especificado para o campo, os bytes extras são preenchidos com espaços em branco. Já com campos
de tamanho variável, somente os caracteres fornecidos pelo usuário serão efetivamente armazenados.
Veja a comparação da Figura 2.5.
A definição de nome e atributos (tipos de dados e tamanhos) dos campos constitui o que chamamos
de formato de registro.
FIGURA 2.6
FIGURA 2.8
As aplicações normalmente utilizam várias tabelas do banco de dados para consolidar e retornar
informações nas quais o usuário tem interesse (como na geração de um relatório de vendas no mês ou
o boletim escolar dos alunos).
2.3.1. Índices
Quando precisamos procurar um determinado assunto num livro ou em uma enciclopédia, geralmente
recorremos ao índice para saber em que volume e página se encontra a informação e assim tornar mais
rápida nossa pesquisa. Os índices nos bancos de dados têm a mesma funcionalidade, ou seja, permi-
tem que os registros com dados sejam encontrados com extrema rapidez. Eles também oferecem uma
maneira de acesso alternativo aos registros sem que sua posição física dentro do banco de dados seja
modificada. Por exemplo, se desejarmos listar na impressora todos os clientes em ordem alfabética de
nome, podemos utilizar um índice com base nesse campo.
Um índice pode ser simples (quando é formado por um só campo) ou composto (formado por vários
campos da tabela). Os campos que são utilizados na definição de índices denominam-se campos de
indexação. Os índices não contêm dados propriamente ditos, mas apenas o valor do campo de
indexação e "ponteiros" que direcionam para o registro adequado dentro da tabela. A informação
contida neles é automaticamente atualizada, ou seja, se inserirmos ou excluirmos um registro, o índice
também será modificado.
FIGURA 2.9
Maiores detalhes técnicos são abordados num capítulo especificamente dedicado a este assunto.
FIGURA 2.10
Nesse caso, o campo CodigoCategoria é chave primária na tabela Categorias e chave estrangeira na
tabela Produtos. O vínculo entre as duas tabelas é efetuado por meio desses dois campos. Da mesma
maneira, o campo CodigoFornecedor é chave primária em Fornecedores e chave estrangeira em
Produtos.
Outro uso muito comum de chaves estrangeiras, além da ligação entre tabelas, é no fornecimento de
valores de outra tabela (a que contém a chave primária). Por exemplo, poderíamos utilizar uma caixa
de listagem para escolha da categoria de produtos numa tela de cadastro de produtos, evitando assim
que o usuário entre com informações indevidas, como código de categoria inexistente.
Apesar de normalmente o nome do campo (ou conjunto de campos) que define a chave primária e a
chave estrangeira ser o mesmo, é perfeitamente possível nomeá-los de forma distinta.
2.3.5. Domínios
O domínio é um tipo de conceito até certo ponto difícil de demonstrar. A melhor maneira de entendê-
-lo é com exemplos concretos. Os domínios se prestam a dois objetivos básicos: definição de tipos de
dados e especificação de valores que podem ser aceitos pelos campos. Nem todos os sistemas de
bancos de dados suportam a criação e uso de domínios. Em geral, todos os sistemas padrão SQL dão
suporte total.
Uma das maiores vantagens de utilizar domínios na construção de bancos de dados é o fato de poder-
mos padronizar os atributos de campos que existem em várias tabelas do banco de dados. Vamos
supor que precisamos definir cinco campos para armazenar o endereço, bairro, cidade, estado e CEP.
O formato desses campos é apresentado na seguinte tabela:
Apesar de a informação do CEP ser composta apenas por números, devemos definir o campo como
sendo caractere para que seja possível armazenar zeros apresentados à esquerda e o traço de separa-
ção, como, por exemplo, "00123-456".
Continuando com o exemplo, esses campos serão criados em três tabelas: cadastro de funcionários,
cadastro de clientes, cadastro de fornecedores. A probabilidade de definirmos um ou mais campos
com tamanho diferente é grande.
Com os domínios essa probabilidade de erro pode ser evitada. Para isso devemos criá-los, especi-
ficando os atributos necessários a cada campo, e depois empregá-los na definição dos campos. Vamos
utilizar uma linguagem imaginária para demonstrar a criação de domínios para esses campos:
Na criação da tabela de dados, devemos fazer referência a esses domínios da seguinte maneira (lingua-
gem imaginária):
O mesmo método seria empregado para as outras duas tabelas de dados. Com isso não há como
esquecermos as propriedades para um determinado campo, como, por exemplo, seu tamanho em
caracteres.
O segundo uso dos domínios, como já mencionado, é na especificação de valores limites ou faixa de
dados válidos. Por exemplo, podemos criar um domínio para não permitir que o usuário tente entrar
com um valor menor ou igual a zero no campo de salário do funcionário. Utilizando nossa linguagem
imaginária, teríamos:
A regra principal por trás dos domínios é similar à da programação orientada a objetos: defina uma
vez, use várias vezes.
FIGURA 2.12
FIGURA 2.17
Há ainda regras de integridade que podem ser definidas através de rotinas criadas pelo desenvolvedor,
como é o caso das Stored Procedures e Triggers do padrão SQL.
FIGURA 2.18
2.7. Exercícios
1) Quais são as categorias em que podem ser divididos os modelos de dados?
2) Quais são os estados que podem ser encontrados num sistema de banco de dados?
3) Quais são os níveis da arquitetura de três esquemas ?
4) Quais são os objetos que compõem um banco de dados?
5) Qual a definição de índices, chaves primárias, chaves estrangeiras, chaves candidatas e domí-
nios?
6) Quais são os principais tipos de dados que podem ser atribuídos a campos?
7) Liste os tipos de integridade de bancos de dados conhecidos.
3.2.1. Os Índices
Uma das principais características do padrão ISAM é fazer uso de índices para manipular as informa-
ções num banco de dados. Vejamos maiores detalhes do seu funcionamento.
Já sabemos que o uso mais comum que se faz dos computadores, desde o seu surgimento, é o
armazenamento de grandes quantidades de informações. E por esse motivo, é preciso um método
eficiente de localização de um determinado item de informação dentro desse mar de dados. Os índices
servem justamente para isso.
Tomemos como exemplo de comparação uma biblioteca com sua variedade enorme de livros e
enciclopédias. Vamos supor que você deseje localizar o livro "Dom Casmurro", do magistral Machado
de Assis. Você tem duas opções: a primeira seria vasculhar a biblioteca inteira, passando por todas as
estantes e vendo cada um dos livros (algo nada prático, diga-se de passagem); a segunda seria utilizar
um catálogo que lhe desse a informação exata da estante em que se encontra o referido livro. Esse
catálogo nada mais é do que um índice para a pesquisa.
A biblioteca, para facilitar ainda mais, pode possuir mais de um catálogo, cada um com um tipo de
ordenação diferente. Um catálogo contém informações indexadas por autor, outro por título da obra,
outro ainda pela editora etc. Da mesma forma, sistemas de bancos de dados computadorizados podem
apresentar vários índices para um mesmo grupo de registros (tabela). Essa característica (múltiplos
índices) é totalmente suportada pelo padrão ISAM.
No arquivo do computador, poderíamos ter a seguinte relação de nome de escritores, de acordo com
a ordem em que os dados foram adicionados:
Agora, para ordenar a lista pelo nome, podemos criar um índice no qual apenas o número de registro
é armazenado conforme a ordem em que os registros deverão ser mostrados. Desta forma, a
classificação torna-se mais rápida e ocupa menos espaço em disco, tendo em vista que um valor
numérico é tratado em vez de uma enorme cadeia de caracteres. Acompanhe pela seguinte tabela:
Para listar os nomes em ordem alfabética, simplesmente verificamos as informações contidas no índice.
Desta forma, o primeiro registro a ser apresentado é o de número 7, depois o de número 2 e assim por
diante. Se o índice for desativado, o sistema deve considerar a ordem definida no momento da adição dos
registros.
Outra forma de indexar esses dados é utilizar um posicionamento relativo. Nesse método, em vez de
ser armazenado o número do registro no índice, ele conterá uma informação que diz onde encontrar o
registro seguinte. Uma informação extra, no entanto, é necessária. Ela indica o registro a partir do qual
podemos encontrar os demais. Veja a tabela em seguida:
(Registro inicial = 7)
Número do registro Nome do escritor
Índice de ordenação
1 Euclides da Cunha 8
2 Bento Teixeira 3
3 Bernardo Guimarães 5
4 Machado de Assis 6
5 Castro Alves 1
6 Raul Pompeia FIM
7 Álvares de Azevedo 2
8 José de Alencar 4
Repare que em vários casos os valores diferem do método anterior. No caso podemos interpretar da
seguinte maneira: o primeiro registro está armazenado na posição de número 7 dentro do índice; informa
ainda que devemos ir para a posição 2, pois nela encontramos o próximo registro; a informação nos leva à
posição 3, que contém o valor do próximo registro (no caso 5). A posição 5 do índice informa que o
próximo registro é o de número 1 e assim por diante. Devemos notar que a posição de número 6 contém
a cadeia de caracteres "FIM", indicando que não há mais dados, pois este é o último registro no índice.
Quando ocorre uma operação de inserção de um novo elemento na fila, ele é posicionado no fim,
fazendo com que o tamanho da fila aumente. Na remoção acontece o contrário, o elemento do início
é retirado e o tamanho diminuído. Os elementos restantes são deslocados uma posição à frente. As
Figuras 3.3 e 3.4 mostram esse processo.
É bastante frequente a utilização desse tipo de estrutura na implementação de filas de impressão, em
que todos os documentos a serem impressos são enfileirados, e quando a impressora termina de
imprimir um documento, o software de gerenciamento de impressão do sistema operacional envia o
documento seguinte (se houver algum).
A pilha é outro tipo de lista linear em que os elementos são inseridos e removidos a partir da extre-
midade final. Sua semelhança com uma pilha de objetos (como pratos, caixas ou tijolos) na vida real
não é por acaso, Figura 3.5.
O último elemento a ser adicionado à pilha sempre será o primeiro a ser retirado, por isso também ela é
denominada de lista LIFO (Last In/First Out). Observando a Figura 3.6, podemos ter uma ideia geral do
seu funcionamento. O uso mais comum de pilhas está em rotinas internas de avaliação de expressões
matemáticas e de controle de chamadas e retorno de funções de um programa aplicativo.
3.3.2. Árvores
As árvores são estruturas de dados cujos itens são organizados de forma hierárquica. Elas são assim cha-
madas devido ao fato de se assemelharem a uma árvore na vida real, possuindo um nó principal chamado
"raiz", nós secundários denominados "nós interiores" e nós terminais, identificados como "folhas". Veja a
Figura 3.7.
Cada nó da árvore possui uma chave para organizar as informações, e os dados propriamente ditos.
No entanto, algumas partes dos dados não são de fato armazenadas na árvore.
O nó superior é denominado de "pai" e o inferior, de "filho". Para exemplificar, vamos assumir que
temos uma relação de sete nomes de funcionários com seus respectivos códigos. A Figura 3.8 mostra
a aparência que deveria ter uma árvore com essas informações. Note que os dados são organizados em
função do código e não do nome.
FIGURA 3.8
Para saber qual é o elemento da raiz, devemos encontrar aquele que ocupa a posição central dentro da
relação, e isso é fácil porque os dados estão ordenados por código. Pegando o número total de
registros e dividindo por dois, é possível obter o elemento central. Se o total de registros for um valor
ímpar (como em nosso exemplo), devemos considerar somente a parte inteira (já que o resultado da
divisão será fracionária) e somar um. Veja o diagrama da Figura 3.9.
De posse desse elemento da raiz, precisamos agora determinar os nós à direita e à esquerda dela. Os
nós da esquerda conterão valores menores que o da raiz, enquanto os da direita armazenarão os
elementos com valor maior que o da raiz.
Vamos primeiramente gerar os nós à esquerda da raiz (mas poderíamos gerar também os da direita).
Para isso devemos encontrar a posição do elemento central dos itens restantes desse lado da árvore.
Este será o elemento a ser adicionado como nó filho, Figura 3.10.
FIGURA 3.10
O processo para determinar os próximos nós é semelhante. Uma vez que o item à esquerda é único
(não possui mais itens antes dele), ele será adicionado ao nó da esquerda, Figura 3.11. Agora passamos
aos elementos a serem adicionados à direita do nó denominado "Henrique". Como somente há um
item, ele é que será inserido, Figura 3.12.
FIGURA 3.11
Como não há mais itens do lado esquerdo da raiz, passamos à adição dos que restam à direita. O
processo em si é o mesmo, conforme podemos verificar nas Figuras 3.13, 3.14. e 3.15.
Isso, no entanto, não é tudo. Precisamos considerar os casos em que o número de elementos é par.
Vamos supor que tenhamos oito registros de funcionários. Para encontrar o elemento da raiz da
árvore, utilizamos novamente a divisão do total de itens por dois, o que nos leva ao registro do
funcionário de código 0011 (Karina). Os elementos à esquerda, cujos códigos são menores que o da
raiz, são definidos da mesma forma estudada anteriormente.
O processo muda quando partimos para a análise dos itens à direita da raiz. Como agora resta uma quan-
tidade par de itens, devemos proceder de forma diferente. Dividimos a quantidade por dois e "pegamos" o
elemento à direita do que ocupa a posição resultante dessa divisão, como mostra a Figura 3.16.
FIGURA 3.13
FIGURA 3.15
FIGURA 3.16
FIGURA 3.17
FIGURA 3.18
Como ficou faltando só um elemento, ele é adicionado à ramificação à direita do nó do código 0045,
Figura 3.19.
O tipo de árvore que acabamos de ver é denominado árvore binária, pois não há mais do que duas
ramificações em cada nó.
Árvores binárias são muito práticas para a localização de itens/registros. Suponhamos que você deseje
visualizar os dados do funcionário de código 0018 (Washington). De posse desse código, que
chamamos de chave de pesquisa, o sistema inicia comparando-o com o valor do registro localizado na
raiz da árvore (que representa a posição central dentro do banco de dados). Se o valor da chave de
pesquisa for maior que o valor da raiz, a pesquisa continua com a ramificação à direita; caso contrário,
parte para o nó à esquerda. Novamente é efetuada uma comparação com o valor do próximo nó. Se
for maior, uma nova comparação é feita com o nó à direita. Em nosso caso, como a chave de pesquisa
é menor (0018 contra 0025), a direção a ser seguida é a esquerda.
O processo continua até que durante a comparação o valor seja encontrado. Se toda a árvore for
varrida e nenhum nó que contenha o valor da chave de pesquisa for localizado, então significa que ele
não está armazenado no banco de dados. Veja o esquema da Figura 3.20.
FIGURA 3.20
4.1. Ordenação
O capítulo anterior mostrou como é possível utilizar índices para aplicar uma determinada ordem a
um conjunto de registros. Vimos também estruturas de dados baseadas em filas, pilhas e árvores. Para
a implementação da última estrutura (árvore) é necessário que as informações também sejam colo-
cadas numa determinada ordem.
Tendo em vista que as operações de classificação/ordenação de dados são as mais corriqueiras e im-
portantes de um sistema de computador, é imprescindível que técnicas e métodos altamente eficientes
sejam desenvolvidos, com o objetivo de obter o máximo desempenho no menor tempo possível. De
acordo com algumas pesquisas, os computadores chegam a empregar cerca de 30% de seu poder de
processamento nessas tarefas. Este capítulo traz alguns métodos bastante simples, mas que oferecem
bons resultados.
FIGURA 4.1
Começando da extremidade esquerda dessa fileira, comparamos o primeiro cartão com o segundo,
Figura 4.2. Se o cartão da esquerda tiver um número maior que o da direita, trocamos as suas
posições. A seguir, comparamos novamente o primeiro cartão com o terceiro, Figura 4.3, e se estive-
rem fora de ordem, fazemos a troca. E assim vamos fazendo essa comparação do primeiro cartão com
todos os demais até atingirmos a extremidade direita (último cartão da fileira). Veja a sequência de
Figuras de 4.4 a 4.9.
Ao final dessa primeira varredura, teremos na extremidade esquerda o cartão com o menor valor.
Sendo assim, iniciamos o processo de comparação a partir do segundo cartão da fileira. A regra é a
mesma, sempre verificamos seu valor com cada um dos cartões restantes à direita e se for necessário,
fazemos a troca de posição. Acompanhe pelas Figuras 4.10 a 4.16.
FIGURA 4.10
O cartão que ocupa a terceira posição na fileira passa a ser o ponto inicial da próxima varredura. Veja
pelas Figuras 4.17, 4.18 e 4.19 duas substituições efetuadas nessa passagem. As Figuras 4.20, 4.21 e
4.22 mostram como ficará a disposição dos cartões após a passagem pela quarta, quinta e sexta
posições. O resultado final da ordenação pode ser visto na Figura 4.23.
Escrever um programa que faça essa ordenação é bastante simples, pois são necessários apenas dois
laços de repetição, sendo um para contar a posição do cartão inicial da comparação e outro para indi-
car os cartões à direita que serão utilizados. Vamos demonstrar essa técnica através de duas linguagens
bastante conhecidas: Pascal e C. Os compiladores utilizados neste livro são o Turbo Pascal 5.5 e o
Turbo C 2.01, produzidos antigamente pela Borland e que hoje pertencem à empresa Embarcadero.
FIGURA 4.24
FIGURA 4.25
Pois bem, com as ferramentas de programação já instaladas e rodando, vamos criar os programas que
vão servir de exemplo. Execute o compilador Turbo Pascal e digite o seguinte código:
program OrdenacaoBolha;
uses CRT;
var
chrCartas: array[1..9] of char;
procedure ImprimeMatriz;
var
intContador: integer;
begin
for intContador := 1 to 9 do
begin
write(chrCartas[intContador]);
write(' ');
end;
writeln('');
writeln('');
end;
procedure OrdenaMatriz;
var
intEsquerda,intDireita: integer;
begin
chrCartas[1] := '4';
chrCartas[2] := '1';
chrCartas[3] := '5';
chrCartas[4] := '7';
chrCartas[5] := '3';
chrCartas[6] := '2';
chrCartas[7] := '6';
chrCartas[8] := '9';
chrCartas[9] := '8';
clrscr;
OrdenaMatriz;
end.
Uma matriz de nove caracteres é criada inicialmente, a qual representa os nove cartões do exemplo
que acabamos de abordar. Dois procedimentos são definidos em seguida. O primeiro, denominado
ImprimeMatriz, simplesmente varre toda a matriz de dados e apresenta seus valores no vídeo. O
segundo procedimento (OrdenaMatriz) é o que realmente executa a operação de ordenação dos
elementos da matriz.
O núcleo do procedimento OrdenaMatriz reside em dois laços de repetição. O laço externo,
controlado pela variável intEsquerda, determina o elemento inicial da comparação, contado a partir
da extremidade esquerda da matriz. No laço interno varremos os demais elementos, começando pelo
que está imediatamente à direita do elemento inicial (por isso a variável de controle é inicializada com
o valor de intEsquerda mais 1). Se o valor do elemento apontado por intEsquerda for maior que o
apontado por intDireita, salvamos esse valor numa variável temporária e fazemos a substituição.
Ao final desse laço, imprimimos o valor da matriz para mostrar como ela fica após cada passagem.
O corpo principal do programa armazena os valores de cada elemento da matriz e depois chama o
procedimento para ordená-los. Após compilar o programa, você pode rodá-lo numa janela de
comando (Prompt de comando) e deve ver a tela da Figura 4.26. Note que sempre será necessário um
número de passos igual ao número de elementos envolvidos na ordenação, menos um.
#include <stdio.h>
#include <conio.h>
char chrCartas[9];
void ImprimeMatriz(void)
{
int intContador;
for (intContador = 0;intContador < 9;intContador++)
printf("%c ",chrCartas[intContador]);
printf("\n");
printf("\n");
}
void OrdenaMatriz(void)
{
int intEsquerda,intDireita;
char chrCartaTemp;
Agora repetimos o procedimento com os próximos cartões. Veja que os de número 5 e 7 foram
posicionados à direita, Figura 4.29.
Chegamos ao cartão de número 3, e as coisas nesse ponto se complicaram um pouco. Como ele é
menor que o cartão no fim da segunda fileira (número 7), ele deve ser deslocado para a direita, Figura
4.30, e então efetuamos a comparação com o próximo cartão à esquerda. Novamente, por ser maior
(número 5), há um deslocamento para o lado direito. Com o cartão de número 4 acontece o mesmo,
Figura 4.31. Assim encontramos a posição para o cartão "3".
O processo é então repetido para o próximo cartão, que agora contém o número 2. Desta forma
todos os cartões à direita do número 1 devem ser deslocados, para que seja encaixado o número 2,
conforme a Figura 4.32.
Veja nas Figuras 4.33 e 4.34 as etapas finais até chegarmos à ordenação completa da Figura 4.35.
A seguir, são apresentadas as listagens para Turbo Pascal e Turbo C que implementam esse método de
ordenação. A Figura 4.36 mostra o resultado após a execução dos programas. Talvez você consiga
notar a velocidade maior de processamento.
uses CRT;
var
chrCartas: array[1..9] of char;
procedure ImprimeMatriz;
var
intContador: integer;
begin
for intContador := 1 to 9 do
begin
write(chrCartas[intContador]);
write(' ');
end;
writeln('');
writeln('');
end;
procedure OrdenaMatriz;
var
intPassagem,intItem,intContador: integer;
chrCartaTemp: char;
blnTrocou: boolean;
begin
intPassagem := 0;
for intItem := 2 to 9 do
begin
blnTrocou := False;
chrCartaTemp := chrCartas[intItem];
intContador := intItem;
while chrCartas[intContador-1] > chrCartaTemp do
begin
blnTrocou := True;
chrCartas[intContador] := chrCartas[intContador-1];
Dec(intContador);
if intContador <= 0 then
exit;
end;
chrCartas[intContador] := chrCartaTemp;
if blnTrocou then
begin
Inc(intPassagem);
writeln('Passagem no. ',intPassagem);
ImprimeMatriz;
end;
end;
end;
begin
chrCartas[1] := '4';
chrCartas[2] := '1';
chrCartas[3] := '5';
chrCartas[4] := '7';
chrCartas[5] := '3';
chrCartas[6] := '2';
chrCartas[7] := '6';
chrCartas[8] := '9';
chrCartas[9] := '8';
clrscr;
OrdenaMatriz;
end.
char chrCartas[9];
void ImprimeMatriz(void)
{
int intContador;
for (intContador = 0;intContador < 9;intContador++)
printf("%c ",chrCartas[intContador]);
printf("\n");
printf("\n");
}
void OrdenaMatriz(void)
{
int intPassagem,intItem,intContador;
char chrCartaTemp,chrTrocou;
intPassagem = 0;
for (intItem = 1;intItem < 9;intItem++)
{
chrTrocou = 'N';
chrCartaTemp = chrCartas[intItem];
intContador = intItem;
while (chrCartas[intContador-1] > chrCartaTemp)
{
chrTrocou = 'S';
chrCartas[intContador] = chrCartas[intContador-1];
intContador--;
if (intContador <= 0)
break;
}
chrCartas[intContador] = chrCartaTemp;
if (chrTrocou == 'S')
{
intPassagem++;
printf("Passagem no. %d\n",intPassagem);
ImprimeMatriz();
}
}
}
void main(void)
{
chrCartas[0] = '4';
chrCartas[1] = '1';
chrCartas[2] = '5';
chrCartas[3] = '7';
chrCartas[4] = '3';
chrCartas[5] = '2';
chrCartas[6] = '6';
chrCartas[7] = '9';
chrCartas[8] = '8';
clrscr();
OrdenaMatriz();
}
FIGURA 4.35
FIGURA 4.36
Programa em Pascal
program OrdenacaoQuickSort;
uses CRT;
var
chrCartas: array[1..9] of char;
procedure ImprimeMatriz;
var
intContador: integer;
begin
for intContador := 1 to 9 do
begin
write(chrCartas[intContador]);
write(' ');
end;
writeln('');
end;
begin
chrCartas[1] := '4';
chrCartas[2] := '1';
chrCartas[3] := '5';
chrCartas[4] := '7';
chrCartas[5] := '3';
chrCartas[6] := '2';
chrCartas[7] := '6';
chrCartas[8] := '9';
chrCartas[9] := '8';
clrscr;
QuickSort(9);
ImprimeMatriz;
end.
Programa em C
#include <stdlib.h>
#include <stdio.h>
char chrCartas[9];
intLadoEsquerdo = intEsquerda;
intLadoDireito = intDireita;
intPivo = chrVetor[intEsquerda];
while (intEsquerda < intDireita)
{
while ((chrVetor[intDireita] >= intPivo) && (intEsquerda < intDireita))
void ImprimeMatriz(void)
{
int intContador;
for (intContador = 0;intContador < 9;intContador++)
printf("%c ",chrCartas[intContador]);
printf("\n");
}
void main(void)
{
chrCartas[0] = '4';
chrCartas[1] = '1';
chrCartas[2] = '5';
chrCartas[3] = '7';
chrCartas[4] = '3';
chrCartas[5] = '2';
chrCartas[6] = '6';
chrCartas[7] = '9';
chrCartas[8] = '8';
clrscr();
QuickSort(chrCartas,9);
ImprimeMatriz();
}
Procedemos da mesma maneira com os cartões "1" e "2", "5" e "6", "7" e "9". Como todos estão em
ordem crescente, nenhuma posição é alterada.
Finalizada essa primeira passagem, reduzimos o tamanho do incremento, dividindo-o por dois. Desta
forma devemos fazer a comparação entre os cartões assinalados na Figura 4.55. Nessa nova varredura,
haverá a troca dos cartões "5" e "4", Figura 4.56, e "2" e "7", Figura 4.57.
Depois de todos os itens terem sido passados, novamente reduzimos o incremento e repetimos o
processo, que ocorrerá até que o valor do incremento seja menor que 1. Veja na Figura 4.58 o
esquema da nova passagem pelo conjunto.
Podemos ver na Figura 4.59 que o primeiro cartão (número 3) será trocado apenas pelo de número 1.
Na comparação do segundo cartão, ele é trocado com o da quarta posição, cujo valor é 2, Figura 4.60.
Por fim temos a troca dos cartões "4" e "3", "9" e "8", como mostram as Figuras 4.61 e 4.62.
Os códigos em linguagem Pascal e C que implementam esse algoritmo são apresentados em seguida.
Programa em Pascal
program OrdenacaoShellSort;
uses CRT;
var
chrCartas: array[1..9] of char;
procedure ShellSort(intTamanho: integer);
var
intContador1,intContador2,intIncremento: integer;
chrCartaTemp: char;
begin
intIncremento := intTamanho div 2;
while intIncremento > 0 do
begin
intContador1 := 1;
while intContador1 < intTamanho do
begin
chrCartaTemp := chrCartas[intContador1];
intContador2 := intContador1+intIncremento;
while intContador2 <= intTamanho do
begin
if chrCartas[intContador2] < chrCartaTemp then
begin
chrCartas[intContador1] := chrCartas[intContador2];
chrCartas[intContador2] := chrCartaTemp;
chrCartaTemp := chrCartas[intContador1];
end;
intContador2 := intContador2+intIncremento;
end;
Inc(intContador1);
if (intContador1+intIncremento) > intTamanho then
intContador1 := intTamanho+1;
end;
intIncremento := intIncremento div 2;
end;
end;
procedure ImprimeMatriz;
var
intContador: integer;
begin
for intContador := 1 to 9 do
begin
write(chrCartas[intContador]);
write(' ');
end;
writeln('');
end;
begin
Programa em C
#include <stdlib.h>
#include <stdio.h>
char chrCartas[9];
intIncremento = intTamanho/2;
while (intIncremento > 0)
{
intContador1 = 0;
while (intContador1 < (intTamanho-1))
{
chrCartaTemp = chrCartas[intContador1];
intContador2 = intContador1+intIncremento;
while (intContador2 <= (intTamanho-1))
{
if (chrCartas[intContador2] < chrCartaTemp)
{
chrCartas[intContador1] = chrCartas[intContador2];
chrCartas[intContador2] = chrCartaTemp;
chrCartaTemp = chrCartas[intContador1];
}
intContador2 = intContador2+intIncremento;
}
intContador1++;
if ((intContador1+intIncremento) > (intTamanho-1))
break;
}
intIncremento = intIncremento/2;
}
}
void ImprimeMatriz(void)
{
int intContador;
for (intContador = 0;intContador < 9;intContador++)
printf("%c ",chrCartas[intContador]);
printf("\n");
}
void main(void)
{
ShellSort(9);
ImprimeMatriz();
}
No site da Editora Érica (www.editoraerica.com.br) o leitor pode fazer o download desses códigos e
também de um programa executável escrito em Delphi que demonstra esses métodos para melhor
entendimento.
4.6. Exercícios
1) O que é ordenação?
2) Em que consiste o método bolha (Bubble Sort)?
3) Como funciona o método de inserção direta?
4) Como funciona o método QuickSort?
5) Como funciona o método Shell?
Pesquisa de Dados
5.1. O Conceito
Um sistema de banco de dados não teria muita utilidade se não fosse possível localizar e recuperar
suas informações. Para facilitar e agilizar a execução dessas operações, foram desenvolvidos durante
anos diversos algoritmos/métodos, uns mais eficientes que outros.
A forma mais primitiva de pesquisa é aquela em que o valor de cada item do conjunto é analisado,
iniciando no primeiro e finalizando assim que for encontrado um valor que seja igual ao que se está
procurando. Esse método é denominado de pesquisa sequencial, e como se pode perceber, é bem fácil
desenvolver uma rotina que a execute, mas ela não é de forma nenhuma eficiente, consumindo um tempo
enorme se o item a ser localizado estiver próximo do fim do conjunto de dados.
O pior caso é aquele em que não existe o item dentro do conjunto, pois todo esse conjunto será
lido/pesquisado, ou seja, se tivermos 12.000 itens, serão efetuadas 12.000 comparações. A única vantagem
(se é que se pode chamar assim) é que na pesquisa sequencial não há necessidade de os dados estarem
ordenados.
Os engenheiros de sistema têm procurado desenvolver uma maneira de gastar o menor tempo
possível na localização de um registro dentro de um banco de dados, utilizando o menor número de
operações de comparação.
A seguir temos as listagens de códigos em Pascal e C que efetuam pesquisa sequencial:
Programa em Pascal
program ExemploPesquisaSequencial;
uses CRT;
var
chrCartas: array[1..9] of char;
begin
intIndice := 1;
blnAchou := False;
Pesquisa de Dados 85
while (intIndice < 10) and (not blnAchou) do
begin
if chrCartas[intIndice] = chrChave then
blnAchou := True
else
Inc(intIndice);
end;
if blnAchou then
writeln('Posicao do elemento e: ',intIndice)
else
writeln('Elemento nao encontrado!');
end;
begin
chrCartas[1] := '1';
chrCartas[2] := '2';
chrCartas[3] := '3';
chrCartas[4] := '4';
chrCartas[5] := '5';
chrCartas[6] := '6';
chrCartas[7] := '7';
chrCartas[8] := '8';
chrCartas[9] := '9';
clrscr;
PesquisaSequencial('8');
end.
Programa em C
#include <stdio.h>
#include <conio.h>
#define TRUE 1
#define FALSE 0
char chrCartas[9];
intIndice = 0;
intAchou = FALSE;
if (intAchou == TRUE)
printf("Posicao do elemento e: %d",intIndice);
else
printf("Elemento nao encontrado!");
}
void main(void)
{
chrCartas[0] = '1';
chrCartas[1] = '2';
FIGURA 5.1
Pesquisa de Dados 87
Vejamos de forma mais ilustrativa como isso é feito. Considere o conjunto de cartões numerados que
abordamos no capítulo anterior, dispostos ordenadamente. Agora vamos supor que desejamos
localizar a posição do cartão de número 8, utilizando esse método.
Primeiramente encontramos o elemento intermediário, ou seja, aquele que ocupa a posição central do
grupo. Como temos nove itens, a divisão por 2 dará como resultado 4,5. Tomando apenas a parte
inteira, podemos separar o conjunto, agrupando os elementos à esquerda e à direita dessa posição,
como mostra a Figura 5.2.
Agora verificamos se o valor procurado, no caso "8", é menor ou maior que o valor da posição
central. Como no exemplo o valor é maior, já que a posição central contém o número 4, passamos a
trabalhar com o grupo da direita. Se fosse menor, trabalharíamos com os elementos da esquerda. Veja
a Figura 5.3.
Com esse grupo efetuamos também uma divisão do número de itens por dois para encontrarmos a
posição central e separá-lo em dois, Figura 5.4. Outra comparação é então efetuada entre o valor de
pesquisa e o valor intermediário desse novo subgrupo. Como ele é maior, a pesquisa seguirá com o
subgrupo da direita, Figura 5.5.
A separação em dois grupos é efetuada novamente, Figura 5.6, e na comparação, verificamos que o
valor procurado é encontrado no subgrupo da direita (primeiro elemento), conforme a Figura 5.7.
O que ocorre se tentarmos fazer a pesquisa com um valor que não existe no conjunto? Vejamos o
exemplo em que o valor a ser encontrado é "10". Como ele é maior que o item central, passamos a
trabalhar com o subgrupo à direita, como já havíamos feito anteriormente, Figura 5.8.
O processo continua normalmente, como mostram as Figuras 5.9 e 5.10. Na Figura 5.11 podemos ver
que o subgrupo ainda é dividido ao meio. O valor de pesquisa ainda é maior que o item da direita,
Figura 5.12, e como não há mais itens, chegamos à conclusão de que o elemento pesquisado não
existe no conjunto.
A seguir são apresentadas as listagens dos códigos-fonte em Pascal e C que implementam esse método
de pesquisa:
Programa em Pascal
program ExemploPesquisaBinaria;
uses CRT;
var
chrCartas: array[1..9] of char;
procedure PesquisaBinaria(chrChave: char);
var
intMeio,intLimInferior,intLimSuperior: integer;
blnAchou: boolean;
begin
intLimInferior := 1;
intLimSuperior := 9;
blnAchou := False;
while (intLimInferior <= intLimSuperior) and (not blnAchou) do
begin
intMeio := (intLimInferior+intLimSuperior) div 2;
if chrCartas[intMeio] > chrChave then
intLimSuperior := intMeio - 1
else if chrCartas[intMeio] < chrChave then
intLimInferior := intMeio + 1
else if chrCartas[intMeio] = chrChave then
blnAchou := True;
end;
if blnAchou then
writeln('Posicao do elemento e: ',intMeio)
else
writeln('Elemento nao encontrado!');
end;
begin
chrCartas[1] := '1';
chrCartas[2] := '2';
chrCartas[3] := '3';
chrCartas[4] := '4';
chrCartas[5] := '5';
Pesquisa de Dados 89
chrCartas[6] := '6';
chrCartas[7] := '7';
chrCartas[8] := '8';
chrCartas[9] := '9';
clrscr;
PesquisaBinaria('8');
end.
Programa em C
#include <stdio.h>
#include <conio.h>
#define TRUE 1
#define FALSE 0
char chrCartas[9];
intLimInferior = 0;
intLimSuperior = 8;
intAchou = FALSE;
if (intAchou == TRUE)
printf("Posicao do elemento e: %d",intMeio);
else
printf("Elemento nao encontrado!");
}
void main(void)
{
chrCartas[0] = '1';
chrCartas[1] = '2';
chrCartas[2] = '3';
chrCartas[3] = '4';
chrCartas[4] = '5';
chrCartas[5] = '6';
chrCartas[6] = '7';
chrCartas[7] = '8';
chrCartas[8] = '9';
clrscr();
PesquisaBinaria('8');
}
No diagrama da Figura 5.15 podemos ver que o nome "Nikolai Sergei Ishnov" fora localizado
primeiramente no índice e com base na informação do número de registro, o sistema posicionou o
ponteiro no registro de número 7 no arquivo que contém os dados.
FIGURA 5.15
Pesquisa de Dados 91
A partir de opções de alteração e pesquisa, o programa efetua a localização de um registro utilizando
essas matrizes que servem de índices dos dados armazenados na memória. Isso também acontece nas
opções de impressão dos dados.
Veja a listagem do código:
program Controle_de_Notas;
uses CRT;
const
MAXIMO = 30;
var
RegistroNome,
RegistroCod : array[1..MAXIMO] of integer;
NomeAluno : array[1..MAXIMO] of string;
CodigoAluno : array[1..MAXIMO] of integer;
NotaAluno : array[1..MAXIMO] of real;
intContador : integer;
chrOpcao : char;
(************************************
* Rotina para criacao de molduras. *
************************************)
procedure MOLDURA(intTopo,intEsquerda,intFundo,intDireita: integer);
var
intLinha,intColuna: integer;
begin
if intFundo > 24 then
intFundo := 24;
{ Desenha os cantos }
GotoXY(intEsquerda,intTopo);
Write('+');
GotoXY(intEsquerda,intFundo);
Write('+');
GotoXY(intDireita,intTopo);
Write('+');
GotoXY(intDireita,intFundo);
Write('+');
{ Desenha as laterais }
for intLinha := intTopo+1 to intFundo-1 do
begin
GotoXY(intEsquerda,intLinha);
Write('|');
GotoXY(intDireita,intLinha);
Write('|');
end;
end;
(******************************************************
* Rotina de ordenacao dos dados por CODIGO DE ALUNO. *
******************************************************)
procedure ORDEM_CODIGO;
var
intTemporario,intRepete,intTamanho: integer;
begin
ClrScr;
moldura(8,20,10,59);
GotoXY(23,9);
Write('Processando os dados...');
Pesquisa de Dados 93
end;
Dec(intTamanho);
end;
end;
(*********************************
* Rotina de inclusao de alunos. *
*********************************)
procedure INCLUSAO;
var
blnIncluir,blnSair,blnRepete: boolean;
chrResposta,chrContinua: char;
strValor,strNome: string;
intLetra,intTamanho,intErro: integer;
begin
blnIncluir := True;
while blnIncluir do
begin
if intContador > MAXIMO then
begin
moldura(8,20,10,59);
GotoXY(22,9);
Write('ARQUIVO CHEIO ! IMPOSSIVEL INCLUIR.');
chrContinua := ReadKey;
blnIncluir := False;
end
else
begin
blnSair := False;
while not blnSair do
begin
ClrScr;
moldura(1,2,24,79);
GotoXY(5,5);
Write('Registro No.: ',intContador);
Val(strValor,CodigoAluno[intContador],intErro);
if (intErro = 0) and (CodigoAluno[intContador] > 0) then
blnRepete := FALSE
else
begin
GotoXY(5,7);
Write(' ');
end;
intTamanho := length(strNome);
for intLetra := 1 to intTamanho do
strNome[intLetra] := upcase(strNome[intLetra]);
NomeAluno[intContador] := strNome;
GotoXY(5,18);
Write('CONTINUA ? <S/N>');
chrContinua := ReadKey;
if upcase(chrContinua) <> 'S' then
begin
ordem_nome;
ordem_codigo;
blnIncluir := False;
end
else
Inc(intContador);
end;
end;
end;
(*********************************
* Rotina de alteracao de dados. *
*********************************)
procedure ALTERACAO;
var
blnFlag,blnRepete: boolean;
chrResposta,chrContinua: char;
strValor,strNome: string;
intPosicao,intTamanho,intLetra,intAlto,intBaixo,intMeio,intErro,intBusca:
integer;
begin
ClrScr;
moldura(1,2,24,79);
strValor := '';
blnRepete := True;
while blnRepete do
begin
GotoXY(5,5);
Pesquisa de Dados 95
Write('CODIGO DO ALUNO: ');
ReadLn(strValor);
if strValor = '' then
blnRepete := False
else
begin
Val(strValor,intBusca,intErro);
if (intErro = 0) and (intBusca > 0) then
blnRepete := False
else
begin
GotoXY(5,5);
Write(' ');
end;
if intBusca > 99999 then
begin
blnRepete := True;
GotoXY(5,5);
Write(' ');
end;
end;
end;
blnFlag := False;
intBaixo := 1;
intAlto := intContador;
while intBaixo <= intAlto do
begin
intMeio := (intBaixo+intAlto) div 2;
intPosicao := RegistroCod[intMeio];
if intBusca < CodigoAluno[intPosicao] then
intAlto := intMeio - 1
else if intBusca > CodigoAluno[intPosicao] then
intBaixo := intMeio + 1
else
begin
blnFlag := True;
intBaixo := intAlto + 1;
end;
end;
blnRepete := True;
while blnRepete do
begin
GotoXY(5,8);
Write('CODIGO DO ALUNO: ');
ReadLn(strValor);
Val(strValor,intBusca,intErro);
if (intErro = 0) and (intBusca > 0) then
blnRepete := False
else
begin
GotoXY(5,8);
Write(' ');
end;
if intBusca > 99999 then
begin
blnRepete := True;
GotoXY(5,8);
Write(' ');
end;
end;
GotoXY(5,10);
Write('NOME DO ALUNO: ');
ReadLn(strNome);
blnRepete := True;
while blnRepete do
begin
GotoXY(5,12);
Write('NOTA DO ALUNO: ');
ReadLn(NotaAluno[intPosicao]);
if (NotaAluno[intPosicao] < 0) or (NotaAluno[intPosicao] > 10)
then
begin
GotoXY(5,12);
Write(' ');
end
else
blnRepete := FALSE;
end;
GotoXY(5,18);
Write('DADOS CORRETOS ? <S/N>');
chrResposta := readkey;
blnFlag := (upcase(chrResposta) = 'N');
end;
intTamanho := length(strNome);
for intLetra := 1 to intTamanho do
strNome[intLetra] := upcase(strNome[intLetra]);
NomeAluno[intPosicao] := strNome;
CodigoAluno[intPosicao] := intBusca;
ordem_nome;
ordem_codigo;
end;
end;
Pesquisa de Dados 97
(*********************************
* Rotina de pesquisa de alunos. *
*********************************)
procedure PESQUISA;
var
blnFlag: boolean;
chrContinua: char;
strNome: string;
intBaixo,intAlto,intMeio,intPosicao,intLetra,intTamanho: integer;
begin
ClrScr;
strNome := '';
moldura(1,2,24,79);
GotoXY(5,5);
Write('NOME DO ALUNO: ');
ReadLn(strNome);
blnFlag := False;
intBaixo := 1;
intAlto := intContador;
while intBaixo <= intAlto do
begin
intMeio := (intBaixo+intAlto) div 2;
intPosicao := RegistroNome[intMeio];
if strNome < NomeAluno[intPosicao] then
intAlto := intMeio - 1
else if strNome > NomeAluno[intPosicao] then
intBaixo := intMeio + 1
else
begin
blnFlag := True;
intBaixo := intAlto + 1;
end;
end;
(**********************************************
* Rotina de impressao de relatorio por NOME. *
**********************************************)
procedure IMPR_NOME;
var
intRegistro: integer;
chrTecla: char;
begin
for intRegistro := 1 to intContador do
begin
ClrScr;
GotoXY(1,1);
Write('Registro No.: ',intRegistro);
GotoXY(1,2);
Write('CODIGO: ',CodigoAluno[RegistroNome[intRegistro]]);
GotoXY(1,3);
Write('ALUNO: ',NomeAluno[RegistroNome[intRegistro]]);
GotoXY(1,4);
Write('NOTA: ',NotaAluno[RegistroNome[intRegistro]]:2:2);
GotoXY(15,5);
Write('TECLE [ENTER] PARA RETORNAR');
chrTecla := ReadKey;
end;
end;
begin
intContador := 1;
while True do
begin
ClrScr;
moldura(1,2,24,79);
moldura(6,20,17,59);
GotoXY(27,08);Write('1 - INCLUIR ALUNOS.');
GotoXY(27,09);Write('2 - ALTERAR DADOS.');
GotoXY(27,10);Write('3 - PESQUISAR ALUNO.');
Pesquisa de Dados 99
GotoXY(27,11);Write('4 - RELATORIO POR CODIGO.');
GotoXY(27,12);Write('5 - RELATORIO POR NOME.');
GotoXY(27,13);Write('0 - SAIR.');
end;
Dec(intTamanho);
end;
blnFlag := False;
intBaixo := 1;
intAlto := intContador;
while intBaixo <= intAlto do
begin
intMeio := (intBaixo+intAlto) div 2;
intPosicao := RegistroCod[intMeio];
if intBusca < CodigoAluno[intPosicao] then
intAlto := intMeio - 1
else if intBusca > CodigoAluno[intPosicao] then
intBaixo := intMeio + 1
else
begin
blnFlag := True;
intBaixo := intAlto + 1;
end;
end;
blnFlag := False;
intBaixo := 1;
intAlto := intContador;
while intBaixo <= intAlto do
begin
intMeio := (intBaixo+intAlto) div 2;
intPosicao := RegistroNome[intMeio];
FIGURA 5.16
FIGURA 5.17
FIGURA 5.18
FIGURA 5.20
5.4. Exercícios
1) Cite três tipos de pesquisa.
2) Qual é o princípio de funcionamento da pesquisa binária?
3) Como funciona a pesquisa com índices?
Nos meios de armazenamento secundário podem ser mencionados os discos rígidos, os discos ópticos
(CD-ROM ou DVD-ROM) e as fitas magnéticas. A principal diferença entre os diversos tipos de
armazenamento secundário de massa é a forma como os dados são gravados. Enquanto nos discos
rígidos e nas fitas magnéticas a gravação é efetuada mudando a orientação das partículas magnéticas
presente na superfície do disco ou fita, nos CD-ROMs e DVD-ROMs os dados são gravados através
de um feixe de raio laser que “queima” a superfície do disco, deixando depressões microscópicas.
Esses dispositivos são conhecidos também como memória não volátil ou de longo prazo.
6.2.3. O Hashing
A terceira técnica é denominada de arquivo hash, no qual o índice é substituído por um algoritmo que
gera um número (o hash) a partir do valor de um campo-chave. Esse número representa a posição em
que o registro deve ser armazenado no arquivo.
Podem ser definidas fórmulas diferentes de acordo com o tipo de informação do campo-chave.
Tomemos como exemplo um cadastro de fornecedores que tem como campo-chave o CNPJ. A
função que calcula o número do registro poderia ser projetada para multiplicar cada dígito do número
do CNPJ por um valor, que varia de 1 a 9, iniciando a partir da direita e aumentando em direção à
esquerda. Se o valor da multiplicação for maior ou igual a 10, deve-se considerar apenas o último
dígito. Esses valores devem então ser somados para se obter a posição do registro. A Figura 6.8
contém um exemplo para melhor entendimento.
Como não existem números de CNPJ repetidos, os registros sempre serão armazenados em diferentes
posições.
FIGURA 6.8
Diferentemente dos índices, o hashing só pode ter um campo-chave por arquivo. Embora seja menos
flexível que o processo de indexação, ele é mais rápido, pois a posição do registro é encontrada
automaticamente através do algoritmo presente na função.
6.2.4. Árvores-B
Esse último tipo de organização de arquivo foi desenvolvido por Rudolf Bayer e consiste num
agrupamento de nós que seguem uma regra para a formação da árvore. Cada nó possui um nó pai e
diversos nós filhos. Isso só não se aplica ao nó raiz, que tem apenas nós filhos.
6.3. Exercícios
1) Como são classificados os dispositivos de armazenamento de dados em computadores?
2) Cite três tipos de memórias primárias.
3) Qual a diferença na forma de gravação dos dados entre os discos magnéticos (disquetes, HD)
e os discos ópticos (CD-ROM DVD-ROM)?
4) Quais são as técnicas utilizadas no armazenamento e organização de arquivos em disco?
Índices e RAID
FIGURA 7.1
Como os arquivos de índices contêm poucas informações, eles são menores que os arquivos de dados.
Com pesquisa binária é fácil localizar um registro dentro do arquivo de índices e por meio do ponteiro
armazenado nele, posicionar no registro correspondente.
Basicamente podemos classificar os índices em primários, secundários, densos, esparsos, nível único e
multinível.
Já em bancos de dados padrão SQL, a criação de índices secundários é efetuada com o comando
CREATE INDEX. Também é possível especificar nesse comando a cláusula UNIQUE que não
permite a existência de valores duplicados no campo do índice.
7.2. RAID
RAID é sigla de Redundant Array Inexpensive/Independent Disk (Conjunto Redundante de
Discos Econômicos/Independentes) e compreende um agrupamento de discos rígidos que
funcionam de forma concomitante ou paralela, com o objetivo de reduzir os riscos de danos causados
a arquivos e aumentar o desempenho no acesso aos dados.
Os discos podem trabalhar independentemente ou de maneira sincronizada, com os dados espalhados
entre eles. O RAID pode ser implementado via software ou por hardware.
Existem vários tipos de configurações disponíveis, denominados de níveis. Eles estão descritos nos
próximos parágrafos.
7.2.1. RAID 0 + 1
O RAID 0 + 1 exige pelo menos quatro discos na implementação, com espelhamento de cada par de
disco e os pares representando o RAID nível 0. Veja a Figura 7.5.
FIGURA 7.5
7.2.2. RAID 0
No RAID 0 são necessários ao menos dois discos. Nele os dados são fragmentados em segmentos
consecutivos gravados sequencialmente em diferentes discos do conjunto. Os segmentos possuem um
tamanho fixo, definido por blocos A Figura 7.6 mostra o funcionamento dessa tecnologia.
7.2.3. RAID 1
O RAID nível 1 também distribui os dados entre os discos, mas nesse caso além do espelhamento, há a
duplicidade de discos, como ilustrado na Figura 7.7. Para implementação são necessários pelo menos dois
discos.
FIGURA 7.7
7.2.4. RAID 2
O RAID nível 2 possui semelhança com o RAID 4, apresentado a seguir, mas exige um disco extra
em que são gravadas informações de controle de erros (ECC - Error Correcting Code). Esse tipo ficou
obsoleto em virtude de os novos drives de disco rígido já possuírem esse controle no próprio circuito.
A Figura 7.8 apresenta o esquema de implementação.
FIGURA 7.8
7.2.5. RAID 3
Esse tipo de RAID possui como característica principal a gravação paralela com paridade. O controle
dos discos é bastante complexo, uma vez que utiliza-se o menor tamanho possível para os segmentos
de dados. Desta forma, é necessário que todos os discos tenham seis eixos perfeitamente sincroni-
zados, a fim de evitar o atraso na transferência dos dados.
7.2.6. RAID 4
A implementação do RAID nível 4 exige um conjunto de discos iguais, com um mínimo de três
unidades. Um dos discos é reservado para gravação das informações de paridade dos dados, como no
FIGURA 7.9
7.2.7. RAID 5
O RAID 5 tem funcionamento similar ao RAID 4, mas em vez de gravar as informações de paridade num
disco extra, elas são distribuídas pelos discos do conjunto, gravando-se um ou mais bits em cada disco.
Veja o exemplo da Figura 7.10.
FIGURA 7.10
7.2.8. RAID 6
Este é um tipo relativamente novo, que trabalha de forma similar ao RAID 5. No entanto, utiliza-se o
dobro de bits de paridade, o que permite que no caso de dois discos apresentarem falha, os dados
ainda permanecerão íntegros.
7.2.9. RAID 50
Os métodos de segmentação dos dados e uso de bits de paridade são unidos nesse tipo de RAID.
7.3. Exercícios
1) Quais são os tipos de índices conhecidos?
2) Qual é a diferença principal entre um índice primário e um secundário?
3) Quais são os níveis conhecidos da tecnologia RAID?
Modelos de Dados e
Projeto de Banco de Dados
FIGURA 8.1
Na terminologia usualmente empregada, uma linha é denominada tupla, os nomes das colunas são
atributos e a tabela em si chama-se relação. A Figura 8.2 apresenta essas nomenclaturas a partir da tabela
Fornecedores.
FIGURA 8.2
Um esquema de relação pode ser representado pela expressão matemática R = {A1, A2, A3,..., An} e
do mesmo modo, uma tupla pode ser representada como conjunto de pares na seguinte forma
(atributo,valor).
Voltando à tabela denominada Fornecedores, a primeira tupla pode ser apresentada da seguinte
maneira:
Como já dito, a ordem em que os atributos de uma tupla são listados não tem importância no contex-
to abstrato ou lógico, enquanto for mantida a correspondência entre esses atributos e seus valores.
Podemos ainda representar essa relação como um esquema composto pelo nome da relação e a lista
de atributos que fazem parte dela, apresentados entre parênteses. Veja o seguinte exemplo:
Fornecedor(CodigoFornecedor,NomeFornecedor,Endereco,Bairro,Cidade,Estado,Telefone)
Naturalmente, surge a dúvida sobre a diferença entre uma tabela e uma relação. Uma tabela somente
pode ser considerada uma relação quando as seguintes condições forem satisfeitas:
A intersecção de uma linha com uma coluna deve necessariamente conter um valor atômico.
Todos os valores de uma coluna devem ser do mesmo tipo de dado.
Cada coluna deve ter um nome único.
Não há duas ou mais linhas idênticas, ou seja, com os mesmos valores em suas colunas.
Temos ainda o termo domínio, que designa o tipo de dado que cada coluna de uma tupla pode conter.
Os valores a serem armazenados numa tupla são ditos atômicos, ou seja, não podem ser divididos em
outros componentes dentro do modelo relacional.
Normalmente, dá-se nome aos domínios como forma de identificá-los e também auxiliar na interpre-
tação dos valores que eles representam. Também são declarados num domínio o tipo de dado que
deve ser aceito e o tamanho da informação. Um exemplo clássico de definição de domínio é o CNPJ,
com 18 dígitos numéricos.
No exemplo de código SQL para criação da tabela Produtos encontramos restrições de integridade de
entidade, assegurada pelo parâmetro NOT NULL à frente de cada campo. Já a restrição de
integridade de chave é definida pela palavra-chave PRIMARY KEY adicionada ao campo
CodigoProduto. Temos também uma restrição denominada PRODUTOSK1 cuja função é definir
que os valores do campo NomeProduto devem ser únicos, ou seja, não podem se repetir.
Já a restrição denominada PRODUTOSFK1 indica que o campo CodigoCategoria é a chave
estrangeira da tabela, que faz referência ao campo de mesmo nome (CodigoCategoria) da tabela
Categorias. Essa restrição ainda define que as operações de exclusão e alteração de dados da tabela
Categorias são aplicadas em cascata à tabela Produtos. Assim não temos registros órfãos remanes-
centes nela.
8.2.1. Superchave
Uma superchave representa uma restrição capaz de prevenir a existência dos mesmos valores em
atributos de duas ou mais entidades diferentes, o que em síntese torna possível identificar uma
entidade unicamente.
FIGURA 8.3
FIGURA 8.4
Nesse diagrama do esquema podemos notar a identificação das chaves primárias das tabelas através do
sublinhado que foi colocado nos nomes dos campos.
Para representar as restrições de integridade referencial no diagrama do esquema do banco de dados,
apresentadas no tópico anterior, podemos empregar setas que saem das chaves estrangeiras em
direção às chaves primárias, como mostra a Figura 8.5.
FIGURA 8.5
Outra forma de representar esse esquema, e a mais aceita dentro dos conceitos de banco de dados
relacional, é a mostrada na Figura 8.6, em que são apresentados os relacionamentos entre as tabelas
Categorias/Produtos e Fornecedores/Produtos.
Embora tenham sido utilizados os mesmos nomes para os campos das tabelas, isso não é uma regra.
Poderíamos ter o campo CodigoCategoria na tabela Categorias e o campo Categoria na tabela
Produtos que o relacionamento não seria afetado. O que importa não é o nome do campo em si, mas
a informação a ser armazenada nele. A Figura 8.7 exibe a tela de definição de relacionamento do
Access 2007.
FIGURA 8.7
FIGURA 8.8
FIGURA 8.9
FIGURA 8.10
8.5. Exercícios
1) Qual a base teórica do modelo de dados relacional?
2) Como está organizado o modelo de dados relacional?
3) Represente a segunda tupla da relação Produtos, apresentada neste capítulo, na forma de um
esquema de relação.
4) Defina restrição de integridade da entidade.
5) Defina restrição de integridade referencial.
6) O que é um esquema de banco de dados?
7) Que são metadados?
8) Defina catálogo do sistema.
Álgebra Relacional
Relação FUNCIONARIOS
Relação CLIENTES
σ CIDADE=”Atibaia” (CLIENTES)
É importante ressaltar que caso o domínio não seja formado por valores numéricos, cadeias de carac-
teres ou datas, somente podem ser empregados os operadores = ou ≠.
Durante a operação algébrica, a condição lógica é aplicada em cada tupla da relação, e caso satisfaça a
condição, ela é selecionada.
O operador de seleção σ somente pode trabalhar com uma única relação, mas é possível encadear
várias expressões, como no seguinte exemplo:
ENDERECO BAIRRO
É possível combinar os dois operadores em
expressões mais complexas, como a mostrada a R. da Saudade,33 Centro
seguir, que lista apenas os campos ENDERECO R. XV de Novembro, 200 Pq. das Américas
e BAIRRO dos clientes que moram na cidade de Av. Santos Dumont, 350 Centro
Atibaia.
Av. São João, 230 Jd. Paulista
Note que a segunda expressão utilizou o nome da primeira no lugar da relação. O resultado é o
mesmo mostrado anteriormente.
Deve-se destacar que, para a perfeita execução da operação, as duas relações precisam possuir o
mesmo tipo de tuplas.
Primeiramente os clientes da cidade de Atibaia são selecionados. Em seguida uma seleção sob a
relação VENDAS é efetuada para extrair apenas o produto com código 123456.
Por fim, os atributos NOME e PRODUTO das tuplas de ambas as relações resultantes, denomi-
nadas CLIENTE1 e VENDA1, são apresentadas. Para melhor entendimento, essa etapa foi dividida
em dois processos. O primeiro gerou o produto cartesiano de CLIENTE1 e VENDA1 e o segundo
extraiu os atributos desejados.
CODCLIENTE NOME ENDERECO BAIRRO CIDADE CODPRODUTO PRODUTO PRECO QUANTIDADE CLIENTE
NOME PRODUTO
Jorge Aparelho de Som Quasar
Jorge Aparelho de Som Quasar
Marcos Aparelho de Som Quasar
Marcos Aparelho de Som Quasar
9.3.2. Junção
A operação JUNÇÃO (ZY) permite que duas relações sejam combinadas através de tuplas relacio-
nadas. Suponha que desejemos listar os produtos que os clientes compraram. Para isso precisamos das
relações CLIENTES e VENDAS. Os atributos que permitem esse vínculo são NOME da relação
CLIENTES e CLIENTE da relação VENDAS.
Para executar esse tipo de operação, a expressão algébrica deve ser:
NOME PRODUTO
Jorge Jogo de dormitório Colibri
Roberto Teclado musical ExpertMusic
Juvenal Aparelho de Som Quasar
Marcos Aparelho de Som Quasar
9.3.3. Divisão
O operador DIVISÃO (÷) tem uma utilidade muito grande no desenvolvimento de expressões que
representam consultas bastante específicas. Tomemos como exemplo uma consulta que deve retornar
todos os clientes que compraram produtos adquiridos pelo cliente MARCOS.
Essa consulta deve ser fracionada em etapas. Primeiramente descobrimos quais produtos MARCOS
comprou através da seguinte expressão:
Então aplicamos o operador de divisão para saber os clientes que compraram os mesmos produtos
que MARCOS:
9.4. Exercícios
1) Qual a utilidade da álgebra relacional?
2) Cite a principal diferença entre os operadores SELEÇÃO e PROJEÇÃO.
3) Descreva o operador JUNÇÃO.
Projeto Conceitual
A partir dos requisitos levantados é criado um esquema conceitual, no qual consta uma descrição
detalhada e concisa dos tipos de entidades, os relacionamentos e as restrições. Para criação desse
esquema é utilizado um modelo de dados de alto nível, como o MER. O esquema conceitual
criado é denominado de Diagrama Entidade-Relacionamento (DER).
FIGURA 10.3
FIGURA 10.4
Podemos ter ainda atributos com valores únicos ou multivalorados. No primeiro caso os atributos
somente admitem um valor, como nome ou data de nascimento. Já os atributos multivalorados se
enquadram nos casos em que podem existir vários valores, como, por exemplo, número do telefone,
formação acadêmica, certificados de cursos de especialização etc.
Outra característica interessante dos atributos é que eles podem conter valores derivados de outros
atributos. Um exemplo clássico é a idade de uma pessoa, que pode ser derivada/calculada a partir da
data de nascimento e da data corrente.
Os atributos também podem conter valores nulos, que não são similares a valor em branco ou zerado.
Um atributo com valor nulo significa que nada, nem mesmo espaço em branco ou zero, se encontra
armazenado nele. Em SQL é possível saber se um determinado campo da tabela não possui valor (é
nulo) utilizando a cláusula IS NULL.
Um atributo especial de uma entidade é o atributo-chave, assim denominado porque identifica de
forma única uma entidade dentro da coleção. O código de um produto é um bom exemplo de
atributo-chave, já que ele não pode se repetir dentro da coleção de entidades PRODUTOS.
Mas como podemos reconhecer uma entidade?
Isso pode ser feito pela análise criteriosa de cada informação levantada com os usuários. É nessa
análise que se procura agrupar as informações conforme suas características, ou que estão relacionadas
a um mesmo assunto.
Vamos supor o caso de um cadastro de funcionários de uma empresa. Além da lista de funcionários,
temos também uma relação de setores em que cada um trabalha. Desta forma podemos identificar de
imediato dois grupos de informações, como mostra a Figura 10.5.
FIGURA 10.5
Normalmente um banco de dados contém diversas entidades que possuem similaridade entre si, como,
por exemplo, entidade de clientes, de fornecedores ou de produtos. Cada entidade armazena um tipo
específico de dado, compartilhando os mesmos atributos, ou seja, enquanto a entidade CLIENTES
contém os atributos NomeCliente, EnderecoCliente, BairroCliente, CidadeCliente, EstadoCliente,
CEPCliente, RGCliente, CPFCliente e TelefoneCliente, a entidade PRODUTOS contém os
10.4. Relacionamentos
Analisando a relação FUNCIONÁRIOS apresentada no capítulo anterior, podemos perceber que
existe um atributo denominado DEPARTAMENTOS que vincula o funcionário a um departamento
da empresa. Por exemplo, o funcionário Felipe está lotado no departamento RH, a funcionária Kátia
está lotada no departamento Contabilidade e assim por diante.
Embora se trate de um atributo que vincula a relação FUNCIONÁRIOS com a relação
DEPARTAMENTOS, em MER devemos representar essa ligação através de um relacionamento.
Esse relacionamento é um conjunto de associações das duas relações ou entidades. A Figura 10.6
ilustra o relacionamento no diagrama entidade-relacionamento (DER).
FIGURA 10.6
FIGURA 10.7
A linha contínua que apresenta o número 1 refere-se ao papel do chefe, enquanto a linha tracejada
identificada com o número 2 representa o papel do subordinado.
Existem ainda certas restrições que podem ser aplicadas aos tipos de relacionamentos. São elas: razão
de cardinalidade, restrição de participação e restrição estrutural.
A razão de cardinalidade é uma restrição para um relacionamento binário que determina quantas vezes
uma entidade pode participar de um relacionamento. No exemplo dos funcionários que estão lotados
nos departamentos, diagrama da Figura 10.6, temos que cada funcionário pode trabalhar apenas num
único departamento. Por outro lado, um departamento pode conter vários funcionários. Para o
primeiro caso temos uma razão de cardinalidade 1:N, enquanto no segundo, encontramos a razão de
cardinalidade N:1.
10.5. Condicionalidade
A condicionalidade refere-se à capacidade de uma entidade poder ter ou não ligação/vínculo com outra.
Isso significa que podem existir ocorrências numa entidade que não possuem um relacionamento ou
associação com ocorrências de outra entidade. No exemplo de cadastro de funcionários, há uma
obrigatoriedade de vincular um funcionário a um departamento. No entanto, não é obrigatório que todos
eles tenham filhos, o que indica que o relacionamento da entidade FUNCIONÁRIOS com uma
entidade denominada FILHOS nem sempre ocorrerá. O exemplo da Figura 10.9 demonstra casos em
que não há nenhum relacionamento.
FIGURA 10.9
Só porque alguns itens não participam do relacionamento não significa que o fato não possa existir.
Isso define dois grupos de relacionamentos: condicionais e incondicionais.
Nos relacionamentos condicionais podemos ter elementos que não participam do relacionamento, ao
contrário dos relacionamentos incondicionais, em que o relacionamento dos elementos entre as
entidades é obrigatório, ou seja, todos os elementos de uma entidade devem se associar com pelo
menos um elemento de outra entidade.
FIGURA 10.10
Nesse diagrama é possível notar que existem duas entidades, identificadas como C1 e C4 e negritadas,
que possuem os mesmos valores em seus atributos. A única forma de distingui-las é pela associação
com a entidade identificadora.
10.7. Agregação
Considere agora a seguinte situação: uma empresa de desenvolvimento de sistemas possui vários
programadores que trabalham em vários projetos, utilizando diversas ferramentas, como linguagens de
programação e gerenciadores de banco de dados. Da mesma forma que um projeto pode abranger no
seu desenvolvimento vários programadores, cada programador também pode dedicar-se a mais de um
projeto. Assim temos uma relação entre programadores e projetos do tipo M:N. Teoricamente
deveríamos ter os diagramas da Figura 10.11.
FIGURA 10.11
Temos uma entidade que participa de dois relacionamentos, Trabalha em e Utiliza. Precisamos na
verdade de uma maneira de unir esses dois diagramas num só, pois temos dois relacionamentos
utilizados para retratar um fato do mundo real.
O que se deseja na verdade é relacionar a entidade Linguagem com o próprio relacionamento
Trabalha em. Só que algo do tipo apresentado na Figura 10.12 não existe na modelagem de dados, já
que temos um relacionamento ligado a outro relacionamento.
Sendo assim, devemos fazer uso de um conceito denominado Agregação. Primeiramente as entidades
Programador e Projeto são agregadas com o relacionamento Trabalha em para terem um
tratamento similar a um bloco único. Isso torna todo o conjunto similar a uma entidade consolidada
por um fato, que no caso são programadores que trabalham em diversos projetos.
Esse bloco então se relaciona com a entidade Linguagem, resultando assim no diagrama mostrado
pela Figura 10.13. Note que é o bloco todo que participa do relacionamento, e não o relacionamento
FIGURA 10.12
FIGURA 10.13
10.8. Exercícios
1) Defina o Modelo de Dados Entidade-Relacionamento.
2) Descreva as etapas de um projeto de banco de dados.
3) O que é modelo conceitual?
4) Defina modelo lógico.
5) Defina atributos e entidades.
6) Qual o papel do relacionamento?
7) Quais são os tipos de restrições existentes para relacionamentos?
8) Explique o significado de condicionalidade de um relacionamento.
9) Descreva a diferença entre entidades fracas e entidades fortes.
10) Qual a restrição para agregar duas entidades?
ESPECIALIDADE
CodigoEspecialidade (numérico)
Descricao (alfanumérico)
MÉDICO
CodigoMedico (numérico)
NomeMedico (alfanumérico)
CRM (alfanumérico)
CodigoEspecialidade (numérico)
Endereco (nome da rua, número do imóvel, bairro, cidade, estado)
Telefone (alfanumérico)
CONVÊNIO
CodigoConvenio (numérico)
NomeConvenio (alfanumérico)
PACIENTE
CodigoPaciente (numérico)
NomePaciente (alfanumérico)
Endereco (nome da rua, número do imóvel, bairro, cidade, estado)
CPF (alfanumérico)
RG (alfanumérico)
Telefone (alfanumérico)
DataNascimento (data no formato DD/MM/AAAA)
CodigoConvenio (numérico)
CodigoConveniado (alfanumérico)
Sexo (M ou F)
EstadoCivil (solteiro, casado, desquitado, divorciado, viúvo)
LocalTrabalho (alfanumérico)
DEPENDENTE
CodigoPaciente (numérico)
NomeDependente (alfanumérico)
TipoRelacao (cônjuge, filho, enteado, pai, mãe)
DataNascimento (data no formato DD/MM/AAAA)
Sexo (M ou F)
FIGURA 11.1
FIGURA 11.2
FIGURA 11.3
FIGURA 11.4
FIGURA 11.5
FIGURA 11.6
Este é um diagrama básico que pode ser aperfeiçoado com a inclusão de entidades e relacionamentos
futuros.
Dependências Funcionais e
Normalização de Dados
FIGURA 12.1
CRM → NomeMedico
CodigoPaciente → { NomePaciente,CPF,RG }
A primeira dependência especifica que o valor do atributo CRM da entidade MEDICO determina de
forma unívoca o valor do atributo NomeMedico dessa mesma entidade. Já o segundo exemplo
mostra que o valor do atributo CodigoPaciente (entidade PACIENTE) determina o nome, o CPF e
o RG do paciente.
É importante notar que apenas o valor dos atributos CRM e CodigoPaciente é necessário para que
seja possível determinar o nome do médico ou nome, CPF e RG do paciente, ou seja, isso caracteriza
uma dependência parcial.
As duas dependências mostradas antes utilizaram um atributo simples para determinar os valores dos
outros atributos. No entanto, podemos ter situações em que ocorre o contrário, ou seja, um atributo
que é dependente funcional da combinação de dois ou mais. Veja o exemplo a seguir retirado da
entidade DEPENDENTE do nosso banco de dados.
{ CodigoPaciente,DataNascimento } → { NomeDependente }
Podemos então deduzir que é possível, a partir do CPF do paciente, recuperar o nome do dependente,
definindo assim a seguinte dependência funcional:
CPF → { NomeDependente }
FIGURA 12.2
Como podemos perceber, os produtos se repetem na ficha de pedido. Se fôssemos armazenar essas
informações num banco de dados sem ter sido feita uma organização prévia, acabaríamos tendo como
resultado algo parecido com o que se vê na Figura 12.3.
Com essa visão dá para detectar várias anomalias, como:
O cliente é relacionado junto com a venda.
Se uma venda inteira for apagada, os dados do cliente também serão.
No caso de exclusão de produto, todos os registros que contiverem informação sobre ele
devem ser apagados.
Se houver alteração nos dados do cliente, como endereço, é necessário refletir essa alteração
em todos os registros em que ele aparecer.
Da mesma forma, se houver alteração em um produto, como preço, essa alteração também
deve ser repassada a todos os registros desse produto constantes no arquivo.
Isso nos leva à conclusão de que do jeito que está é simplesmente impraticável. Assim, é necessário
aplicar a normalização a esse conjunto de dados. É justamente o que faremos nos próximos tópicos.
FIGURA 12.4
Vamos remover os atributos que se repetem, que no caso são CodProduto, Descricao, Quantidade,
PrecoUnit e ValorTotal. Fazendo essa decomposição, chegamos a duas entidades, uma para a ficha
de pedido e outra para os produtos que constam nela. Veja as Figuras 12.5 e 12.6.
FIGURA 12.5
O relacionamento entre essas duas entidades é mostrado no diagrama da Figura 12.7. Uma vez que
um pedido pode conter vários produtos, temos então uma relação Um-para-Muitos (1:N).
A chave primária da entidade Pedido é o número do pedido, que é único para cada registro. Já para a
entidade Item temos uma chave primária formada pelo número do pedido e o código do produto.
FIGURA 12.7
FIGURA 12.8
FIGURA 12.10
FIGURA 12.12
Nessa relação temos os produtos comprados pelos clientes e os fornecedores que abastecerem a loja.
Desta forma existem duas dependências: uma entre os atributos CodigoFornecedor e
CodigoProduto, e outra entre o CodigoFornecedor e CodigoCliente. A atualização dessa entidade,
nesse caso, torna-se difícil, apesar de ela estar na 3FN.
É aí que entra a quarta forma normal (4FN), segundo a qual uma relação deve, além de estar na 3FN,
conter apenas um fato multivalorado - dependência multivalorada. Note que estamos nos referindo a
fato multivalorado e não a atributo multivalorado. Essa dependência multivalorada é uma
consequência natural da 1FN, pois ela não permite conjunto de valores para um atributo.
Essa característica pode levar à seguinte situação: termos de repetir o valor de um dos atributos com o
valor de outro atributo, quando houver dois ou mais atributos multivalorados independentes.
A relação anterior deve ser dividida em duas para estar então na 4FN, da seguinte maneira:
CodigoFornecedor CodigoProduto
1024 12980
1024 01830
1024 10880
1024 12980
1024 01505
2048 08501
512 15715
512 01830
Relação Fornecedor-Cliente
CodigoFornecedor CodigoCliente
1024 0001
1024 0002
1024 0002
2048 0003
512 0004
Produto NumeroPedido
Padrão B2 07801
Padrão B2 07802
Poste Duplot T 9M 07801
NumeroPedido Fornecedor
07801 00341
07801 00108
07802 00108
Entidade Produto-Fornecedor
Produto Fornecedor
Padrão B2 00341
Padrão B2 00108
Poste Duplo T 9M 00108
Se realizarmos uma junção dessas três entidades, utilizando o atributo NumeroPedido como o
determinante, teremos como resultado o seguinte:
Note que o penúltimo registro (destacado na cor cinza) não havia na relação original.
Se a junção for efetuada tomando o atributo Fornecedor, o resultado será:
Um mesmo professor pode ministrar aulas entre cursos e turmas diferentes. Sendo assim, podemos
identificar três chaves candidatas que são determinantes nessa entidade: CodCurso+CodTurma,
CodCurso+CodProfessor e CodTurma+CodProfessor.
O atributo CodProfessor é parcialmente dependente de CodCurso e de CodTurma, mas é
totalmente dependente da chave candidata composta CodCurso+CodTurma.
Desta forma a entidade deve ser desmembrada, resultando em duas, uma que contém os atributos que
descrevem o aluno em si, e outra cujos atributos designam um professor. Veja na Figura 12.14 as
entidades após a normalização.
FIGURA 12.14
12.4. Exercícios
1) Defina dependência funcional.
2) O que é dependência funcional parcial?
3) O que é dependência funcional total?
4) Defina normalização.
5) Quais são as formas normais conhecidas?
Comando Função
CREATE DATABASE Criar uma base de dados totalmente vazia.
ALTER DATABASE Permitir alterações em algumas caraterísticas da base de dados.
DROP DATABASE Apagar um banco de dados existente (deve ser utilizado com muito cuidado).
CREATE TABLE Criar uma tabela de dados (também há necessidade de cuidado na utilização).
ALTER TABLE Permitir alterações na estrutura de uma tabela existente.
DROP TABLE Apagar uma tabela de dados existente.
CREATE INDEX Criar índices secundários para uma tabela.
DROP INDEX Apagar um índice existente.
CREATE DOMAIN Criar um domínio para campos das tabelas.
DROP DOMAIN Apagar um domínio existente.
CREATE VIEW Criar uma visão com base em uma ou mais tabelas.
DROP VIEW Apagar uma visão existente.
em que nome_base refere-se à especificação completa do caminho (diretório) e nome do arquivo que
deve ser dado à base de dados. Por exemplo:
Alguns sistemas permitem que sejam especificadas algumas propriedades, como nome do usuário e
sua senha (o que define o proprietário do banco de dados), tabela de caracteres, dialeto utilizado,
tamanho de páginas do banco de dados etc. Outros ainda possibilitam a criação do banco de dados de
forma interativa, em vez de utilizar comandos, como é o caso do MySQL, do InterBase e do SQL
Server 2008, por meio de ferramentas gráficas.
Com o comando ALTER DATABASE podemos alterar algumas propriedades de um banco de
dados já criado, como, por exemplo, o conjunto de caracteres que o sistema deve utilizar.
O comando DROP DATABASE faz com que o banco de dados especificado seja apagado do disco.
Por esse motivo deve ser utilizado com extremo cuidado, pois uma vez apagado não será possível
recuperá-lo, a não ser com o uso de softwares especializados na recuperação de arquivos. Na verdade,
todos os comandos DROP merecem bastante atenção no seu uso para evitar possíveis dores de
cabeça futuras. Em alguns SGBDs essa exclusão pode ser efetuada interativamente.
nome_campo é uma cadeia de caracteres iniciada com uma letra que nomeia um campo da tabela de
dados. Já atributo especifica o tipo de dados do campo e outras características, como não permissão
de valores nulos, se o campo for chave primária, se há uma verificação de valores válidos etc. Veja um
exemplo:
Além dos tipos de dados definidos pelo padrão ANSI/ISO, podemos encontrar outros que foram
acrescentados pelos produtores em vista das novas tecnologias que foram surgindo com o tempo.
Veja na tabela seguinte os principais tipos:
Se depois de ter sido definida a estrutura de uma tabela percebermos a necessidade de efetuar algumas
alterações nela, como adicionar novos campos ou apagar alguns que não serão mais úteis, devemos
recorrer ao comando ALTER TABLE. Existe uma limitação no seu uso: ele não permite a alteração
do tipo de dado ou do tamanho de um campo. Se for necessário esse tipo de mudança, devemos criar
um campo temporário com o novo tamanho, transportar os dados do campo antigo para o novo,
apagar esse campo antigo e recriá-lo com o novo tamanho e por fim, transportar de volta os dados do
campo temporário para esse novo campo definitivo.
Para adicionar um campo a uma tabela existente, utilizamos o comando com a seguinte sintaxe:
Veja o exemplo:
O comando DROP TABLE funciona de forma similar a DROP DATABASE, com a diferença que
ele apaga uma tabela inteira do banco de dados. Se houver outras tabelas que estão relacionadas com a
que se deseja excluir (por meio de chaves estrangeiras), o servidor não vai permitir a operação.
Para excluir um índice, simplesmente especificamos o nome do índice após o comando DROP
INDEX:
Na definição da estrutura das tabelas, utilizamos o domínio no lugar dos atributos isolados do campo,
como no exemplo:
Quando estivermos tentando apagar um domínio que é utilizado na definição de campo de uma ou
mais tabelas, a operação não será executada, sendo relatado um erro pelo próprio sistema. Devemos
então apagar primeiramente o campo que é dependente desse domínio.
Com esse comando criamos uma visão que retorna todos os registros de faturamento superiores a
R$ 5.000,00.
A exclusão de uma visão é feita com o comando DROP VIEW nome_visao.
Para utilizar essa visão, devemos passar ao comando SELECT o nome da visão no lugar da tabela real.
Comando Função
INSERT INTO Inserir um novo registro na tabela de dados.
DELETE FROM Apagar um ou mais registros de uma tabela de dados.
UPDATE Permitir que os dados de um registro sejam atualizados.
SELECT FROM Selecionar um conjunto de registros a partir de uma condição e retorná-los ao usuário.
Se for necessário atribuir valor a todos os campos da tabela, a lista de campos pode ser suprimida,
como mostra o exemplo:
Nesse caso específico, a ordem dos valores deve seguir rigorosamente a que está definida para os
campos dentro da tabela.
Nesse caso, os produtos cujo campo Ativo apresenta o caractere "N" serão apagados da tabela.
A tabela em si ainda existe, mas não possui registros armazenados (está vazia), portanto deve-se ter
muito cuidado ao utilizar o comando dessa forma.
13.4.3. UPDATE
O comando UPDATE é utilizado para atualizar os valores armazenados nos campos de uma tabela.
Sua sintaxe é bastante simples:
Se tivermos vários campos para serem atualizados, eles podem ser especificados em sequência e
separados por vírgula. Veja os dois exemplos mostrados em seguida:
A cláusula WHERE também pode ser utilizada no caso de desejarmos atualizar apenas um grupo de
registros, como no exemplo a seguir em que somente os produtos da categoria ‘035’ (campo
CODIGOCATEGORIA= ‘035’) terão o valor do campo MARGEMLUCRO alterado para 18,50:
Para especificar todos os campos da tabela, utilizamos um asterisco (*), como mostra o seguinte
exemplo:
Se desejarmos saber apenas os nomes dos clientes cujo limite de compra seja superior a R$ 3.000,00,
devemos executar o comando:
Vamos supor agora que esses mesmos registros devam ser apresentados em ordem decrescente. O
comando seria:
SELECT NOMECLIENTE FROM CAD_CLIENTES WHERE ESTADO = ‘SP’ AND LIMITECOMPRA >= 3000;
Um operador muito utilizado é o de comparação LIKE. Ele permite que parte de uma cadeia de
caracteres seja fornecida para que os dados sejam recuperados. Por exemplo, para listar todos os
clientes cujo nome comece com a expressão caractere "JON", teríamos de executar o comando:
Dessa maneira seriam apresentados todos os registros cujo valor do campo NOMECLIENTE
começa com as letras "JON", independentemente do que vem após elas. Assim seriam válidos nomes
como "JONAS", "JONATAS" e "JONNY".
Se utilizarmos o nome de uma visão no lugar do nome da tabela, ela será tomada como base para
geração dos registros retornados.
Bem, com esta pequena introdução à linguagem SQL foi possível ter uma ideia do que ela oferece e o
que é possível fazer com ela.
direitos: indica os direitos que podem ser concedidos ao usuário. São eles: ALL
PRIVILEGES, SELECT, INSERT, UPDATE e DELETE.
nome_tabela: é a tabela de dados ou visão na qual será aplicada a concessão dos direitos.
identificação: identificação da autorização para a qual os privilégios foram concedidos.
A sintaxe para o comando REVOKE é um pouco parecida:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import java.sql.*;
int intTotalRegistros,intNumRegistro,intRegistro;
String NomeColuna[] =
{"Registro","Nome","Endereço","Bairro","Cidade","Estado","CEP","Telefone"};
String Campo[] = new String[8];
String EnderecoDB;
java.sql.Connection Conexao;
java.sql.Statement Comando;
java.sql.ResultSet rsRegistro;
public AgendaEnderecos() {
try {
Class.forName("com.mysql.jdbc.Driver");
EnderecoDB = "jdbc:mysql://localhost:3306/agenda_enderecos";
Conexao = DriverManager.getConnection(EnderecoDB,"root","william");
}
catch (Exception Excecao) {
JOptionPane.showMessageDialog(null,"SQLException: " +
Excecao.getMessage(),"Erro: Construtor",JOptionPane.INFORMATION_MESSAGE);
}
}
rsRegistro.beforeFirst();
intTotalRegistros = 0;
while (rsRegistro.next())
intTotalRegistros++;
rsRegistro.beforeFirst();
rsRegistro.next();
intRegistro = rsRegistro.getInt("Registro");
Campo[0] = Integer.toString(intRegistro);
Campo[1] = rsRegistro.getString("Nome");
Campo[2] = rsRegistro.getString("Endereco");
Campo[3] = rsRegistro.getString("Bairro");
Campo[4] = rsRegistro.getString("Cidade");
Campo[5] = rsRegistro.getString("Estado");
Campo[6] = rsRegistro.getString("CEP");
Campo[7] = rsRegistro.getString("Telefone");
ModeloAgenda.insertRow(0,Campo);
intNumRegistro = 1;
while (rsRegistro.next()) {
intRegistro = rsRegistro.getInt("Registro");
Campo[0] = Integer.toString(intRegistro);
Campo[1] = rsRegistro.getString("Nome");
Campo[2] = rsRegistro.getString("Endereco");
Campo[3] = rsRegistro.getString("Bairro");
Campo[4] = rsRegistro.getString("Cidade");
Campo[5] = rsRegistro.getString("Estado");
Campo[6] = rsRegistro.getString("CEP");
Campo[7] = rsRegistro.getString("Telefone");
ModeloAgenda.insertRow(intNumRegistro,Campo);
intNumRegistro++;
}
Comando.close();
}
catch (Exception Excecao) {
JOptionPane.showMessageDialog(null,"SQLException: " +
Excecao.getMessage(),"Erro: Leitura dos
registros",JOptionPane.INFORMATION_MESSAGE);
}
getContentPane().add(pnlBotoes,BorderLayout.NORTH);
getContentPane().add(pnlNome);
getContentPane().add(pnlEndereco);
getContentPane().add(pnlBairro);
getContentPane().add(pnlCidade);
getContentPane().add(pnlEstado);
getContentPane().add(pnlCEP);
getContentPane().add(pnlTelefone);
getContentPane().add(ScrollTabela,BorderLayout.SOUTH);
Agenda.addMouseListener(new MouseTableHandler());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
Conexao.close();
System.exit(0);
}
catch (Exception Excecao) {
JOptionPane.showMessageDialog(null,"SQLException: " +
Excecao.getMessage(),"Erro: Saída",JOptionPane.INFORMATION_MESSAGE);
}
}
});
setVisible(true);
if (eventoObjeto.getSource() == btnAdicionar) {
try {
PreparedStatement ComandoInserir = null;
strNome = fldNome.getText();
strEndereco = fldEndereco.getText();
strBairro = fldBairro.getText();
strCidade = fldCidade.getText();
strEstado = fldEstado.getText();
strCEP = fldCEP.getText();
strTelefone = fldTelefone.getText();
strComandoSQL = "INSERT INTO dadosagenda
(Nome,Endereco,Bairro,Cidade,Estado,CEP,Telefone) "+
"VALUES (?,?,?,?,?,?,?)";
ComandoInserir = Conexao.prepareStatement(strComandoSQL);
ComandoInserir.setString(1,strNome);
ComandoInserir.setString(2,strEndereco);
ComandoInserir.setString(3,strBairro);
ComandoInserir.setString(4,strCidade);
ComandoInserir.setString(5,strEstado);
ComandoInserir.setString(6,strCEP);
ComandoInserir.setString(7,strTelefone);
intRegistro = ComandoInserir.executeUpdate();
ComandoInserir.close();
fldNome.setText("");
fldEndereco.setText("");
fldBairro.setText("");
fldCidade.setText("");
fldEstado.setText("");
fldCEP.setText("");
fldTelefone.setText("");
}
catch (Exception Excecao) {
JOptionPane.showMessageDialog(null,"SQLException: " +
Excecao.getMessage(),"Erro: Adição",JOptionPane.INFORMATION_MESSAGE);
}
}
else if (eventoObjeto.getSource() == btnExcluir) {
try {
PreparedStatement ComandoExcluir = null;
int intLinha = Agenda.getSelectedRow();
strRegistro = ModeloAgenda.getValueAt(intLinha,0).toString();
strComandoSQL = "DELETE FROM dadosagenda WHERE Registro = ?";
ComandoExcluir = Conexao.prepareStatement(strComandoSQL);
ComandoExcluir.setString(1,strRegistro);
intRegistro = ComandoExcluir.executeUpdate();
ComandoExcluir.close();
}
catch (Exception Excecao) {
JOptionPane.showMessageDialog(null,"SQLException: " +
Excecao.getMessage(),"Erro: Exclusão",JOptionPane.INFORMATION_MESSAGE);
}
}
13.7. Exercícios
1) Em qual projeto foram aplicados os conceitos de bancos de dados relacionais?
2) Qual a origem da linguagem SQL?
3) O que são comandos DDL? Cite alguns exemplos.
4) O que são comandos DML? Cite alguns exemplos.
Tecnologias de
Banco de Dados
FIGURA 14.1
chefia(Maurício,Roque)
chefia(Maurício,Vicente)
chefia(Maurício,Cristina)
chefia(Isaura,Amanda)
chefia(Isaura,Norma)
chefia(Isaura,Augusto)
chefia(José,Maurício)
chefia(José,Isaura)
Agora podemos especificar regras para o banco de dados. Elas também definem predicados. Uma
regra tem a seguinte sintaxe: cabeça :- corpo. O símbolo :- pode ser entendido como uma expressão
que significa "se e somente se". Numa regra podemos ter um único predicado à esquerda desse
símbolo (o lado denominado cabeça) e um ou mais predicados à direita (o lado corpo). Veja duas
regras que podem ser estabelecidas para este exemplo:
superior(X,Y) :- chefia(X,Y)
subordinado(X,Y) :- superior(Y,X)
superior(X,Y) :- chefia(X,Z),superior(Z,Y)
Note que são utilizados dois predicados à direita do operador :-. O primeiro é o predicado já
conhecido como chefia. O segundo é o próprio predicado que se encontra à esquerda do símbolo,
somente com parâmetros diferentes. Isso é possível devido à característica da recursividade. A
expressão toda poderia ser traduzida como "X é superior a Y se X for chefe de Z e se Z for chefe de
Y". Isso significa que os dois predicados devem resultar em verdadeiro para que a expressão toda seja
verdadeira. Podemos concluir que, quando listamos vários predicados no corpo de uma regra, estamos
implicitamente utilizando o operador lógico "E".
Uma consulta normalmente emprega um predicado com alguns argumentos e seu significado (ou valor
de retorno) é obtido a partir da dedução de todas as possíveis combinações que podem tornar o
predicado verdadeiro. Por exemplo, vamos considerar o seguinte:
superior(José,Y)?
superior(Isaura,Amanda)?
Subordinado(Cristina,Maurício)?
No primeiro exemplo os nomes de todos os funcionários cujo chefe é "José" são solicitados,
independente da posição dentro do nível hierárquico. Já a segunda consulta retorna um valor
verdadeiro, pois "Isaura" é superior à "Amanda" na hierarquia. Da mesma forma, a terceira consulta
retorna verdadeiro, pois "Cristina" é subordinada a "Maurício".
Para conhecer um pouco mais sobre a linguagem de programação Prolog, visite um dos seguintes sites
(setembro/2009):
http://kti.ms.mff.cuni.cz/~bartak/prolog.old/intro.html
http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/contents.html
http://www.visual-prolog.com/
FIGURA 14.2
14.3. Exercícios
1) O que é banco de dados dedutivo?
2) Que são fatos?
3) Dê uma definição para regras.
4) Em qual linguagem se baseiam os bancos de dados dedutivos?
5) Quais são os sistemas atualmente conhecidos?
15.1. Introdução
Apesar do grande sucesso comercial que alcançaram, os sistemas de bancos de dados convencionais,
baseados no modelo de dados relacional, de rede ou hierárquico, apresentam deficiências quando é
preciso desenvolver aplicações para as áreas de engenharia (CAD/CAM/CAE), simulações científicas
ou médicas, informações geográficas (GIS - Geographical Information System), telecomunicações, gerência
de documentos e multimídia. Essas aplicações fazem uso de estruturas de dados mais complexas,
como imagens, vídeos, áudio e textos formatados em parágrafos. Surgiu então uma proposta de um
novo modelo de banco de dados para que pudesse oferecer uma solução a essas deficiências.
Outro fator que impulsionou o surgimento desse modelo de banco de dados foi a crescente
popularidade das linguagens orientadas a objeto, como Smalltalk, C++ e Java. É um consenso geral
que os bancos de dados são peças fundamentais no desenvolvimento de muitos sistemas aplicativos,
mas eles são difíceis de utilizar em conjunto com essas linguagens orientadas para objeto. Sendo assim,
procura-se uma integração do banco de dados orientado a objetos com as aplicações criadas com uma
das linguagens citadas anteriormente, ou seja, aliar a capacidade de armazenamento dos bancos de
dados com os poderosos recursos oferecidos pelas linguagens na manipulação de objetos e métodos.
Vários protótipos experimentais foram desenvolvidos, alguns chegando inclusive a se tornar
disponíveis comercialmente. Como exemplo, podemos citar o GemStone da GemStone Systems, o
Objectivity da Objectivity Inc., o ObjectStore da Object Design (subsidiária da Progress Software), o FastObjects da
POET Software, o Versant Developer Suite da Versant Corporation, o OpenODB da Hewlett-Packard e o
Informix da IBM.
Com a disponibilidade comercial de SGBDs orientados a objetos (SGBDOO), tornou-se necessária a
adoção de novas características em termos de modelagem de dados e uma linguagem padrão para
trabalhar com esses sistemas. Assim foi formado o ODMG - Object Database Management Group (Grupo
de Gerenciamento de Bancos de Dados de Objetos), um consórcio formado por diversas organi-
zações, fornecedores de SGBDs e usuários de bancos de dados de objetos. Esse grupo propôs um
padrão conhecido como ODMG-93, atualmente revisado e denominado ODMG 2.0, e que foi aceito
mundialmente pela indústria de SGBDOO - Sistemas de Gerenciamento de Banco de Dados
Orientados a Objeto.
O ODMG é responsável também pela definição de um padrão de linguagens para o modelo orientado
para objeto, sendo classificadas como ODL - Object Definition Language (Linguagem de Definição de
Objeto) e OQL - Object Query Language (Linguagem de Consulta de Objeto). Nesse padrão foi
estabelecido que o banco de dados deve possuir um vínculo/ligação com alguma linguagem
hospedeira orientada a objeto, como Smalltalk, C++ ou Java. Outra especificação nesse padrão diz
FIGURA 15.1
FIGURA 15.2
class Mensagem {
char *Texto;
public:
Mensagem(char*);
~Mensagem();
void Imprime();
};
Às vezes a herança é também denominada de derivação, uma vez que um objeto novo é derivado de
um já existente.
O polimorfismo está relacionado às diversas maneiras como uma mesma função membro de uma
classe/objeto pode ser referenciada. Essa característica é também chamada de sobrecarga de funções e
convivemos diariamente com ela quando usamos operadores matemáticos. Nesse caso, o operador
(adição, subtração, multiplicação, divisão etc.) trabalha da mesma maneira, independente do tipo de
valores com os quais ele está lidando, ou seja, podem ser valores inteiros, decimais com duas casas,
ponto flutuante de dupla precisão etc. Não há um operador para cada tipo de dado, mas apenas um que
se adapta automaticamente. A ideia do polimorfismo/sobrecarga de funções é a mesma, ou seja, ter a
capacidade de lidar indistintamente com objetos diferentes. Veja o exemplo apresentado em seguida:
overload Calculo;
int Calculo(int,int,int);
double Calculo(double,double,double);
Neste caso são os parâmetros passados à função Calculo() que vão determinar qual versão será
executada. É importante notar que deve haver pelo menos um parâmetro diferente entre as versões
para que seja possível essa distinção.
Outros dois conceitos presentes na programação orientada a objeto são os construtores e destrutores.
Eles nada mais são que funções escritas especificamente para alocar memória no momento da criação
dos objetos, e posteriormente liberá-la, quando o objeto não é mais necessário (é destruído).
FIGURA 15.3
objDado = Clientes.novo_cliente("WILLIAM");
Há uma diferença gritante na forma como um banco de dados relacional e um orientado a objetos
permitem que as informações sejam recuperadas. No primeiro podemos criar consultas complexas
sobre dados simples. Já o segundo permite a criação de consultas simples sobre dados complexos.
Um termo muito utilizado em banco de dados de objetos é persistência, que está relacionado com a
noção de tempo de vida que um objeto pode ter. Para melhor entender esse conceito, vamos
Se um banco de dados possui muitos objetos (dezenas ou centenas), não é nada prático declarar todos
eles. Nesse caso entra o mecanismo de acessibilidade. Se um determinado objeto for acessível a outro
e esse último for tornado persistente, então o primeiro também se torna persistente automaticamente.
Apesar das suas qualidades, um banco de dados orientado a objeto normalmente apresenta problemas
relacionados ao desempenho e à escalabilidade. Não são também adequados na manipulação de dados
convencionais, como os existentes em bases relacionais.
Note que temos campos que são comuns em ambas estruturas (no caso o campo do nome e os de
informação do endereço). Podemos utilizar domínios para agilizar o trabalho, mas ainda assim será
necessário declarar cada campo separadamente dentro da estrutura das tabelas. Agora vejamos como
isso seria feito com um banco de dados orientado a objeto. Primeiramente definimos uma classe
denominada ClasseBase:
class ClasseBase
(extent DadosBase)
{
attribute string Nome;
attribute string Endereco;
attribute string Bairro;
attribute string Cidade;
attribute string Estado;
attribute string CEP;
};
Agora podemos criar os objetos Clientes e Fornecedores do esquema do banco de dados com os
seguintes comandos:
Podemos perceber que os campos que possuem uma especificação comum foram agregados em uma
classe, tornando mais fácil a vida do desenvolvedor, pois ele precisa apenas indicar que o objeto é
descendente dessa classe. A palavra-chave extends indica que a classe/objeto herda os atributos e
métodos da classe/objeto que a segue.
O comando enum cria um conjunto de valores enumerados que são atribuídos ao campo, o qual
somente aceitará os valores constantes na lista. Note como isso é similar ao tipo de dados enumerado,
que pode ser definido pelo programador na linguagem C/C++.
O ponto de entrada para o banco de dados neste caso é Clientes, que é o próprio nome da extensão
de uma classe, definido pelo comando extent. O nome da extensão é considerado nome de um objeto
persistente.
Uma visão em OQL é definida a partir do conceito de consulta identificada, sendo utilizada a palavra-
-chave define para especificar um identificador para a consulta. Esse identificador não deve conflitar
com o nome de outros objetos, classes, métodos ou funções definidos no esquema. No caso de
especificar um nome que já exista para outra consulta identificada, ela é sobrescrita. Veja o seguinte
exemplo:
define lista_fornecedor(tipo_pessoa) as
select fornec from fornec in Fornecedores
where fornec.Pessoa = tipo_pessoa;
A linguagem OQL possui ainda operadores/funções para agregação e quantificação, como count
(contagem de itens), avg (média), min (menor valor), max (maior valor) e sum (soma de itens). O
exemplo seguinte mostra um código que retorna o total de fornecedores pessoa jurídica existentes no
banco de dados, utilizando a consulta identificada do exemplo anterior:
Na área de banco de dados de objeto para aplicações comerciais, um dos pioneiros foi o Jasmine,
fruto do desenvolvimento conjunto entre a Computer Associates (CA) e Fujitsu. Foi um sistema
orientado a objeto puro, não um sistema híbrido, e que hoje não é mais produzido.
#include <stdlib.h>
#include <iostream>
#include <os_pse/ostore.hh> // Lite and Pro header file
#include "binarytree.cpp"
#include "data.h"
int main()
{
// The top of the stack of every thread of every program
// must be wrapped in a fault handler
// This macro begins the handler's scope
OS_PSE_ESTABLISH_FAULT_HANDLER
if (!db_root) {
switch(next_action) {
case 'l':
// Look up a number, given a name
cout << "Name?" << endl << "==> ";
cin.ignore(1);
cin.getline(na, MAX_CHAR);
data_item = new Data(na, 0);
answer_data = the_tree->lookup(*data_item);
delete data_item;
if(answer_data)
cout << endl << *answer_data;
else
cout << "Not found." << "\n\n";
break;
case 'a':
// Add a name and number
cout << "Name?" << endl << "==> ";
cin.ignore(1);
cin.getline(na, MAX_CHAR);
cout << "Number?" << endl << "==> ";
cin.getline(nu, MAX_CHAR);
cout << "Adding new persistent data..." << "\n\n";
data_item = new(db, os_ts<Data>::get())
Data(na, nu);
the_tree->add(*data_item);
break;
case 'd':
case 's':
// Save database
cout << "Saving database..." << "\n\n";
db->save();
break;
case 'r':
// Close db, open it again, and retrieve tree
cout << "Reverting to last save..." << "\n\n";
db->close();
db = os_database::open("phone.db");
the_tree = (BinaryTree<Data>*) (
db->find_root("phone_root")->get_value()
);
break;
default:
break;
}
}
// Close database
db->close();
return 0;
}
Note que uma variável ponteiro para o objeto os_database é criada e sua função é fazer referência a
um arquivo de dados em disco. Observe também que há métodos (funções membros) para abrir,
salvar e fechar o banco de dados.
O compilador C++ utilizado pelo ObjectStore é o Visual C++ da Microsoft, a partir da versão 6.0.
Veja a Figura 15.4.
Outro pacote bastante interessante é o Objectivity/DB, que pode ser baixado gratuitamente do site
www.objectivity.com (setembro/2009). Ele utiliza como linguagens hospedeiras C++, Java e
Smalltalk.
Vejamos mais um pacote voltado para o desenvolvimento de banco de dados orientado a objetos
utilizando a linguagem C++: o Versant Object Database. A partir do site www.versant.com podemos
efetuar o download de uma versão de demonstração.
Há uma série de utilitários entre os quais se destaca o Adminstration Console, que permite a
execução de várias tarefas, como criar bancos de dados ou visualizar os objetos já definidos nele. O
interessante desses utilitários é que todos são escritos na linguagem Java, como mostra o exemplo da
Figura 15.5.
FIGURA 15.5
Apesar da evolução que alcançaram, sistemas orientados a objeto ainda carecem de uma interface mais
amigável para se trabalhar. Na maioria, tudo o que temos são bibliotecas de classes que devem ser
Um tipo de dados Pessoa foi definido pelo primeiro comando CREATE ROW TYPE. Em seguida
temos a definição de mais dois tipos (Funcionarios e Clientes) que herdam todos os atributos de
Pessoa. A palavra-chave UNDER informa na declaração do novo tipo qual o tipo ancestral. O
Informix não tem suporte à herança múltipla, ou seja, um tipo não herda atributos de mais de um tipo
ancestral.
Podemos ainda criar tabelas de dados utilizando esses novos tipos, ou seja, elas conterão instâncias
dos objetos Funcionarios e Clientes. Veja o código a seguir:
Vamos agora definir duas funções para extrair dados dessas tabelas. A primeira estará ligada ao tipo de
dados Funcionarios:
Agora a próxima função será idêntica, porém vinculada ao tipo de dados Clientes:"
O Oracle, um sistema relacional, também possui suporte a alguns conceitos de orientação a objeto.
Veja na listagem a seguir os comandos para definição de novos tipos de dados e de tabelas, que
correspondem ao exemplo em Informix visto anteriormente:
Elemento Descrição
IDL (stub) Representa o mapeamento entre uma linguagem e a implementação do ORB. Responsável por invocar um objeto remoto por meio
da sintaxe normal da linguagem utilizada.
Interface de invocação dinâmica Permite que uma requisição do cliente seja montada sem o auxílio do elemento anterior (stubs). Assim é necessário especificar o
objeto CORBA, seus métodos e parâmetros.
Interface ORB Permite ao cliente acessar as funcionalidades do objeto CORBA que não são oferecidas pelas outras interfaces.
Esqueleto IDL (estático) Recebe uma invocação remota e envia uma resposta ao cliente.
Interface dinâmica de esqueleto Permite o acesso a servidores que não possuem esqueletos estáticos (IDL).
Adaptador de Objetos Responsável pela comunicação entre a implementação do objeto e o Núcleo ORB. Manipula serviços de geração e interpretação de
referências a objetos IOR (Interoperable Object Reference), invocação e ativação/desativação de objetos CORBA.
Servidor 1
Servidor 2
Servidor 3
No segundo tipo, a fragmentação vertical, temos a divisão de uma relação em outros subconjuntos
que contêm colunas específicas. Cada subconjunto possui apenas algumas colunas, sendo necessário
um campo (chave primária ou chave candidata) para que seja possível reconstruir as informações
originais antes do processo de fragmentação.
Suponha que a relação Funcionarios deva ser fragmentada, gerando dois subconjuntos: o primeiro
contendo o código e o nome do funcionário, o segundo contendo o endereço e o código do depar-
tamento. A situação seria a seguinte:
Servidor 2
Repare que foi necessário incluir também o campo de código de funcionário no segundo subconjunto,
para assim ser possível recuperar as informações de endereço e departamento relativas aos funcio-
nários.
O terceiro tipo (fragmentação híbrida) é uma mistura dos dois anteriores, apresentando caracterís-
ticas de ambos.
Além dessas técnicas podemos também definir uma distribuição em que os subconjuntos são
formados por tabelas inteiras. Por exemplo, as tabelas relacionadas com funcionários e folha de
pagamento podem estar armazenadas no servidor do departamento de recursos humanos; as tabelas
relacionadas ao sistema de contas a pagar e receber agrupadas no servidor do departamento de finança
e assim por diante.
Há operadores na linguagem SQL (UNION, OUTER UNION e OUTER JOIN) que possibilitam a
união/junção dos subconjuntos para reconstruir uma relação completa.
Outra característica que pode ser encontrada num ambiente de banco de dados distribuído é a
replicação de dados. Ela consiste na duplicação total ou parcial do banco de dados em mais de uma
localização ou ponto da rede. Isso é útil para melhorar a disponibilidade dos dados, uma vez que
agiliza as consultas globais na recuperação de dados, mas como efeito colateral, pode tornar o sistema
todo mais moroso nas operações de atualização, as quais devem ser replicadas nas cópias. Veja na
Figura 16.1 um diagrama que demonstra a arquitetura de banco fragmentado, na Figura 16.2 a
replicação de dados e na Figura 16.3 um modelo de banco de dados distribuído com acesso remoto
por uma rede WAN.
FIGURA 16.2
Como solução para os problemas de distribuição e localização dos dados, temos três enfoques. Em
todos eles há um componente denominado Gerenciador de Transações, que é responsável por
analisar as requisições das estações clientes e direcioná-las para o servidor apropriado. O servidor
responde à requisição e retorna um conjunto de registros para a consulta. O Gerenciador de
Transações então sintetiza todas essas respostas numa só e devolve o resultado ao usuário.
No primeiro tipo de enfoque, cada Gerenciador de Transações mantém seu próprio catálogo e
contém ainda uma cópia do catálogo global do sistema, na qual se encontram as informações de todas
as localizações na rede, assim cada sistema sabe onde os outros estão. A vantagem desse enfoque é
que se um catálogo for alterado, somente as modificações são transmitidas pela rede. A desvantagem é
a possibilidade de a integridade dos dados ser quebrada, o que leva à necessidade de um mecanismo
que acompanha as mudanças efetuadas nos catálogos locais e atualiza todas as informações quando
houver alterações.
No segundo enfoque, cada Gerenciador de Transações também mantém seu próprio catálogo de
sistema, mas um examina o catálogo do outro antes que uma busca seja efetuada. Um problema
inerente a essa configuração é que se um dos servidores estiver desativado, os dados em seu banco são
ignorados.
O terceiro e último enfoque utiliza um catálogo global com informações sobre todas as localizações na
rede. Antes de executar uma operação, o Gerenciador de Transações analisa esse catálogo. Esse
esquema cria a ilusão de um sistema centralizado, mas tem como efeito colateral a demanda excessiva
de processamento e elevado tráfego de rede.
FIGURA 16.4
Alguns métodos foram desenvolvidos para trabalhar com essa ideia de cópias distintas, sendo
diferentes na forma de sua escolha. Esses métodos se encontram descritos a seguir. Na abordagem
utilizamos o termo "nó" para designar um ponto ou localização dentro da rede, que pode ser um
servidor ou mais comumente uma estação cliente.
Método do nó principal
Um único nó primário é definido como o supervisor das operações de bloqueio. Isso significa que
todos os bloqueios são mantidos por ele e todas as solicitações de bloqueio/desbloqueio são enviadas
16.4. Exercícios
1) O que é banco de dados distribuído?
2) Quais são as funções adicionais de um SGBD distribuído?
3) Quais são as técnicas de fragmentação de um banco de dados?
4) O que é replicação de dados?
5) Quais são os enfoques empregados na distribuição e localização de dados num SGBD distri-
buído?
6) O que é interoperabilidade?
7) Defina controle de concorrência.
Arquitetura Cliente/Servidor
Nesse ambiente pode-se ter a dupla controladora/terminal ligada diretamente ao grande porte, ou os
chamados terminais remotos que por meio de um sistema de telecomunicação recebem e transmitem
os dados. A Figura 17.3 ilustra essas duas arquiteturas.
FIGURA 17.3
FIGURA 17.4
FIGURA 17.5
FIGURA 17.6
Alguns exemplos de bancos de dados para grande porte são: DB2 da IBM, o IMS (Information
Management System) também da IBM, ADABAS da SoftwareAG, SUPRA Server SQL e SUPRA
Server PDM ambos da Cincom, e o próprio Oracle.
Com o DB2 a IBM lidera o mercado de banco de dados relacional padrão SQL para ambiente de
grande porte. Há versões para os mais diversos sistemas operacionais da IBM (MVS, VSE, VM, AIX,
OS/390, AS/400) e não IBM, como HP-UX, Linux, Solaris e Windows, para microcomputadores. As
versões mais recentes desse gerenciador oferecem recursos para acesso ao banco de dados pela
Internet, utilizando apenas um navegador padrão, como Internet Explorer, Mozilla Firefox ou Opera.
Isso torna possível o desenvolvimento de aplicações web de comércio eletrônico.
Outra característica presente nas novas versões é a capacidade de lidar com objetos complexos, como
imagens, sons, vídeos, além da pesquisa linguística de documentos por palavra, por sinônimo, por
parágrafo ou por caracteres genéricos. Com isso se torna possível o desenvolvimento de aplicações
multimídia altamente sofisticadas.
Várias linguagens de desenvolvimento têm suporte para acesso a banco de dados DB2, como o
Delphi/C++Builder (Embarcadero/CodeGear), o PowerBuilder (Sybase) e VisualAge (IBM), além das
linguagens de terceira geração como C/C++, COBOL e FORTRAN, que requerem uma pré-compilação
de scripts escritos em SQL.
FIGURA 17.8
Nos anos de 1990, houve uma verdadeira correria em direção a um novo processo denominado
downsizing, que em bom português seria algo como rebaixar o nível de processamento, migrando
dos computadores de grande porte para equipamentos de menor porte. Isso se tornou possível graças
à tecnologia de rede local que estava em expansão, tanto em termos de hardware (placas de rede, hubs,
padrões etc.) quanto de software (sistemas operacionais, protocolos, softwares gerenciadores de rede
etc.).
A meta principal dos gerentes de informática era a redução de custos. Mas os poucos softwares de
gerenciamentos de banco de dados para microcomputadores existentes na época não tinham
capacidade nem ofereciam recursos para se trabalhar num ambiente descentralizado. Assim, diversos
fornecedores passaram a desenvolver novas soluções, algumas das quais migradas de ambientes de
grande porte ou de minicomputadores. Iniciou-se então a difusão do conceito da arquitetura
cliente/servidor.
Na Figura 17.9 temos o diagrama das tarefas que cada componente executa de uma rede local baseado
num servidor de arquivos.
Já no segundo processo encontramos o servidor, uma máquina com configurações bem mais robustas
e que reage aos serviços solicitados pelas estações clientes. Essas reações podem ser o processamento
de um arquivo, a impressão de um relatório ou uma consulta de registros de um banco de dados.
No caso específico de uma consulta a banco de dados, após ter efetuado as operações necessárias, o
servidor retorna as informações (conjunto de registros resultantes da consulta) ao cliente. Por ser um
sistema reativo, ele somente entra em ação quando há alguma requisição por parte do cliente. As
aplicações que são executadas no servidor para desempenhar essas tarefas são denominadas back-end.
Na Figura 17.10 podemos ver o fluxo de dados entre o cliente e o servidor e na Figura 17.11, um
diagrama que ilustra a divisão das tarefas entre as duas partes.
No servidor encontramos ainda os recursos compartilhados com os clientes, como, por exemplo,
diretório, arquivos e impressora. O acesso a esses recursos é controlado por rígidos esquemas de
segurança, como níveis de acessos definidos pelo administrador da rede e senhas para cada usuário.
Tanto o cliente quanto o servidor devem estar providos de hardware e de software capazes de
oferecer as funcionalidades de todo o ambiente, como sistema operacional, protocolos de rede,
software aplicativo adequado, gerenciadores de banco de dados etc.
FIGURA 17.10
No lado cliente, as aplicações exigem menos recursos da máquina do que os softwares que rodam no
servidor. Esse último deve possuir uma estrutura sofisticada a tal ponto que seja capaz de atender a
várias requisições ao mesmo tempo, como, por exemplo, vários usuários acessando o mesmo banco
de dados. Se ele for o responsável por gerenciar os processos de impressão, deve controlar a fila de
arquivos a serem impressos.
Os sistemas operacionais de rede mais utilizados são o UNIX e suas diversas variantes (AIX, IRIX,
Solaris, HP-UX etc.), os diversos sabores do Linux (Red Hat, Ubuntu, Suse, Mandriva etc.), NetWare
e Windows NT/2000/2003/2008. Ainda é possível encontrar redes que utilizam no servidor o OS/2
da IBM, um sistema muito bom e estável, mas que por forças maiores deixou de ser produzido.
Como já visto anteriormente, também é possível termos mais de um servidor, como, por exemplo:
1) Servidor de banco de dados: no qual reside o gerenciador de banco de dados e os bancos de
dados em si.
2) Servidor de aplicações: no qual se encontram os softwares aplicativos a serem utilizados pelos
clientes.
3) Servidor de impressão: responsável por gerenciar a fila de impressão de documentos.
4) Servidor de Internet: responsável pela conexão à Internet e distribuição desta de forma compar-
tilhada aos demais computadores ligados à rede.
É interessante ressaltar que a arquitetura cliente/servidor possui a característica de permitir a utilização
de mais de um servidor para a mesma tarefa. Por exemplo, podemos ter três servidores de banco de
dados, e os bancos de dados podem se encontrar distribuídos entre eles. O gerenciador de banco de
dados deve coordenar as tarefas de manutenção de forma transparente ao usuário.
Um ambiente cliente/servidor é ainda heterogêneo, o que significa que podemos encontrar diversas
máquinas com sistemas operacionais distintos convivendo lado a lado pacificamente. Este é um dos
grandes trunfos dessa arquitetura, pois não estamos presos a soluções proprietárias, já que temos a
liberdade de escolher tanto o hardware quanto o software que melhor atendam nossas necessidades,
seja em termos de custo ou benefícios oferecidos. Veja na Figura 17.12 o diagrama de uma arquitetura
cliente/servidor em que se misturam diversas plataformas de hardware/software.
FIGURA 17.12
FIGURA 17.13
Os protocolos de rede são os mecanismos responsáveis pela comunicação entre os diversos equipa-
mentos. Podemos dividi-los em dois tipos, os de transporte e os de cliente/servidor. No primeiro
FIGURA 17.14
O segundo tipo (três camadas - three tiers architecture) já possui um pouco mais de complexidade.
Nele temos uma divisão mais ampla entre quem trabalha com os dados e quem os armazena,
representada por três componentes: anfitrião (host), servidor e cliente. O servidor de aplicação age
como uma ponte entre o cliente e o servidor de banco de dados (o anfitrião - host). Agora ele é o
responsável pela manipulação das regras de negócio (procedimentos e restrições) do banco de dados.
Ele também gerencia todas as requisições oriundas dos clientes, antes de encaminhá-las ao servidor de
banco de dados. Em sistemas que possuem mais de um servidor, ele se encarrega de direcionar as
solicitações dos clientes para eles, coletar as respostas retornadas e sintetizá-las de forma que o cliente
receba somente uma resposta.
Na primeira camada ficam as aplicações clientes que são dedicadas apenas à interface com o usuário
(apresentação e entrada dos dados), na maioria das vezes executadas em ambientes gráficos (interface
gráfica) de acordo com o sistema operacional que se está utilizando. Na terceira camada se encontram
FIGURA 17.15
FIGURA 17.16
Os sistemas de bancos de dados relacionais, que em grande parte iniciaram como sistemas
centralizados, tiveram características da arquitetura cliente/servidor incorporada, levando para o lado
cliente toda a interface com usuário e os programas aplicativos.
Um sistema gerenciador de banco de dados para ambiente cliente/servidor trabalha com o conceito
de que se deve responder a solicitações recebidas das aplicações clientes. Esses sistemas geralmente
trabalham com a linguagem SQL, desenvolvida exclusivamente para manipular bancos de dados
relacionais, e costumam ser denominados de servidores SQL.
Uma vez que é possível haver vários servidores SQL trabalhando juntos e possivelmente manipulando
bancos de dados distintos, inclusive sendo de diferentes fornecedores, a aplicação cliente deve ser
capaz de "montar" comandos da linguagem SQL a partir de solicitações do usuário e então enviá-los
aos servidores adequados. Para saber a localização de cada servidor, a aplicação cliente faz uso de um
dicionário de dados que contém informações relativas à distribuição dos dados entre esses servidores
SQL. Como resultado, os conjuntos de registros retornados por cada servidor (após o processamento
da consulta) são agregados para gerar um único conjunto de dados a ser apresentado ao usuário.
Nesse tipo de abordagem, o servidor SQL é denominado também de servidor de transação,
enquanto os clientes são chamados de processadores de aplicação.
17.7. Exercícios
1) Como era o modelo computacional no início da era informatizada?
2) Para que serviam os terminais de vídeo?
3) Qual a função de uma controladora de terminais?
4) Que equipamento permitiu a utilização de microcomputadores PC como terminais de vídeo?
5) Descreva as fases envolvidas no processo de comunicação grande porte/terminal de vídeo.
6) Como é o processo de interação da estação cliente com o servidor?
7) Quais os tipos de rede e a característica que os distingue?
8) O que é ambiente cliente/servidor de duas camadas?
9) O que é ambiente cliente/servidor de três camadas?
10) Como trabalha um sistema de banco de dados cliente/servidor?
11) Cite dois fatores que contribuíram para a passagem do ambiente centralizado para o descen-
tralizado.
12) Quais são as principais dificuldades encontradas na implantação de um ambiente descentra-
lizado?
PRODUTO
Codigo Descricao Preco Estoque Data_Inclusao
Caractere(13) Caractere(40) Decimal(10,2) Inteiro Data
FIGURA 18.1
Esse tipo de conjunto tem o nome CAT_PROD, como indicação do relacionamento entre categorias e
produtos. Temos também o tipo de registro proprietário denominado CATEGORIA e PRODUTO
que é o tipo de registro membro. Nesse relacionamento, um componente de PRODUTO somente
FIGURA 18.2
FIGURA 18.3
Aspectos Avançados
Os sistemas SQL atuais possuem ambientes gráficos que tornam mais fácil e intuitiva a tarefa de
gerenciar contas, usuários e privilégios, uma vez que tudo é executado de forma visual, sem a
necessidade de digitação de comandos.
Vejamos então como utilizar os recursos desse tipo de ferramenta que pode ser encontrado em dois
gerenciadores padrão SQL muito conhecidos, o MySQL 5.1 e o Microsoft SQL Server 2008 Express
Edition.
A ferramenta de administração de banco de dados do MySQL responsável pelo gerenciamento de
contas de usuários e privilégios é a MySQL Administrator. A opção User Administration deve ser
utilizada para executar as tarefas de gerenciamento, Figura 19.1.
Para adicionar um novo usuário, clique no botão Add new user ( ) e a tela da Figura 19.2
deve ser mostrada. Digite um nome de identificação do usuário e sua senha de acesso nas caixas de
entrada MySQL User e Password respectivamente. A senha deve ser ainda repetida na caixa de
entrada Confirm password.
FIGURA 19.2
Acesse a guia Schema Privileges para ver a tela da Figura 19.3. A partir da lista mais à esquerda,
escolha o banco de dados para definir os privilégios para o usuário. Em seguida, selecione um dos
itens apresentados na lista da direita e depois clique no botão para adicionar à lista de privilégios
concedidos, como mostra o exemplo da Figura 19.4.
Para revogar um privilégio já atribuído ao usuário, simplesmente selecione-o a partir da lista central
(Assigned Privileges) e clique no botão .
FIGURA 19.4
O SQL Server 2008 Express Edition oferece o Server Management Studio, mostrado na Figura
19.5.
Para adicionar um novo usuário, expanda o item de banco de dados mostrado pelo Object Explorer
(Explorador de Objetos) e depois clique com o botão direito do mouse na pasta Security (Segurança).
Escolha a opção New → Login, Figura 19.6. Assim a tela da Figura 19.7 deve ser aberta.
FIGURA 19.6
Digite um nome de identificação do usuário na caixa de entrada Login name. Em seguida selecione a
opção SQL Server authentication para habilitar os campos mostrados na Figura 19.8.
Entre com a senha de acesso nas caixas de entrada Password e Confirm password. Após clicar no
botão OK o novo usuário estará cadastrado.
FIGURA 19.8
FIGURA 19.11
Podemos ter dois tipos de roteador, sendo estático e dinâmico. O roteador estático sempre seleciona o
caminho mais curto entre dois pontos. Apesar de ser mais simples, requer cuidados extras, pois as
informações de roteamento são registradas manualmente. Um roteador dinâmico é mais sofisticado,
capaz de tomar decisões que chegam ao nível de cada pacote, baseando-se em informações pro-
venientes de outros roteadores e dispositivos da rede.
Para efetuar o backup de um banco de dados, clique no botão New Project para que seja apresentada
a tela da Figura 19.15. Digite um nome para identificar o projeto de backup e depois selecione o banco
de dados a partir da lista. Veja o exemplo da Figura 19.16.
FIGURA 19.15
Note que é possível marcar as tabelas que devem ser copiadas. Após clicar no botão Save Project
você verá o nome do projeto de backup na lista da esquerda, Figura 19.17. Para executar o backup
selecionado, clique no botão Execute Backup Now.
Na guia Schedule é possível configurar o dia da semana e a hora em que o backup deve ser efetuado
automaticamente pelo sistema, Figura 19.18.
A restauração de um banco de dados, quando necessária, pode ser feita pela opção Restore. A tela da
Figura 19.19 deve ser mostrada. Clique no botão Open Backup File para poder abrir o arquivo
gerado pela operação de backup, Figura 19.20. Clique por fim no botão Start Restore.
FIGURA 19.20
Embora não seja uma regra que deva ser seguida impreterivelmente, é aconselhável que as operações
de backup e restore sejam executadas quando não houver usuários acessando o banco de dados.
Devemos ter em mente ainda que não é possível deixar a critério de uma única pessoa a execução da
cópia de segurança, mas utilizar o método de cópia automática quando for oferecido. Nunca é demais
ter duas ou três cópias, por exemplo, uma que é a imagem atual do banco de dados e duas que são
anteriores. Isso facilita no caso de haver necessidade de recuperação de dados.
Outra forma um pouco mais dispendiosa, porém mais segura e que não depende de terceiros, é a
utilização de discos rígidos espelhados, como na arquitetura RAID, apresentada no capítulo 7. Em
ambientes cliente/servidor que rodam aplicações de missão crítica podemos encontrar máquinas
inteiras espelhadas, cuja arquitetura (hardware e software) permite que, se uma delas falhar, a outra
entre em substituição automaticamente, sem que os usuários percebam qualquer anomalia.
Uma transação pode ser definida como uma unidade lógica de processamento de um banco de dados,
a qual possui diversas operações, como inclusão, alteração, exclusão etc. A maneira de especificar o
limite de uma transação é por meio de comandos explícitos que indicam o início (BEGIN
TRANSACTION) e o fim da transação (END TRANSACTION). Todos os comandos e acesso ao
banco de dados existentes entre essas duas fases formam a transação em si.
Sem esse gerenciamento de transações, muitos problemas podem acabar ocorrendo, como perda de
atualização de dados, leitura suja de dados e agregação incorreta. O primeiro problema pode acontecer
quando duas transações que acessam os mesmos itens têm suas operações executadas de forma
entrelaçada, ocasionando valores incorretos num dos itens.
O segundo problema surge em decorrência de alguma falha na transação, no momento em que estava
sendo efetuada uma atualização nos dados. Quando uma transação falha, os itens com os quais ela lida
voltam ao seu estado anterior, mas antes disso ocorrer, outra transação pode acessar o valor do item
atualizado.
FIGURA 19.23
Internet, Multimídia e
Data Warehouse Hierárquico
FIGURA 20.3
Enquanto em CGI os aplicativos são arquivos executáveis .EXE, em ISAPI/NSAPI eles são biblio-
tecas de ligação dinâmica (DLL - Dynamic Link Libraries). Uma vez que o ISAPI e o NSAPI trabalham
com o conceito de threads, todo aplicativo deve ser desenvolvido para suportar processamento concor-
rente.
Podemos ver na Figura 20.4 o processo que envolve a solicitação, processamento e retorno de uma
página dinâmica. A Figura 20.5 apresenta o processo sob a óptica do JDBC.
É importante destacar que o SGBD e o próprio banco de dados podem residir no mesmo equipa-
mento utilizado como servidor web, ou estarem num equipamento à parte.
Além dessas tecnologias existe outra desenvolvida pela Microsoft e denominada ASP (Active Server
Pages - Servidor de Páginas Ativas). Ela se encontra incorporada ao servidor web da Microsoft IIS
(Internet Information Server) e pode executar scripts escritos em VBScript ou JavaScript. Eles podem estar
inseridos nas próprias páginas (arquivos com extensão .ASP) ou existirem como arquivos externos que
são chamados por elas.
FIGURA 20.4
A rotina em VBScript ou JavaScript envia ao servidor web instruções SQL, solicitando uma conexão
com o banco de dados e posterior extração de informações dele. O SGBD retorna um conjunto de
registros em resposta à consulta, que é o formato para ser inserido num documento padrão HTML e
devolvido pelo servidor ao navegador do usuário. Veja o processo na Figura 20.6.
FIGURA 20.6
Tipo Descrição
ROLAP (Relational OLAP) Utiliza bancos de dados relacionais e tem como principal vantagem o fato de utilizar tecnologia já consagrada, de arquitetura
aberta e padronizada, que abrange uma ampla faixa de plataformas.
MOLAP (Multidimensional OLAP) Utiliza bancos de dados multidimensionais, possibilitando execução de análises sofisticadas. Os dados são organizados em
estruturas de array para oferecer um ótimo desempenho.
HOLAP (Hybrid OLAP) Uma estrutura híbrida, que une características dos modelos ROLAP e MOLAP. Assim, produtos no padrão ROLAP incorporam
bancos de dados multidimensionais.
WOLAP (Web OLAP) Tecnologia OLAP aplicada ao ambiente da Internet, caracterizada pela independência de plataforma e facilidade de uso e
manutenção.
FIGURA 20.7
FIGURA 20.8
Uma característica do Data Warehouse é a possibilidade que ele oferece de chegarmos a detalhes
minuciosos de uma informação analítica. No exemplo do laboratório farmacêutico, uma informação
do volume de vendas de um determinado medicamento é apresentada de forma sintetizada, mas uma
vez que um medicamento pode apresentar-se em diversas formas (comprimido, xarope, solução,
injetável etc.), podemos "abrir" essa informação para que sejam mostrados dados de cada modelo/tipo
de apresentação do produto. Isso é oferecido pelo mecanismo do OLAP.
FIGURA 20.9
Os Data Marts são na verdade um subconjunto de informações existentes num Data Warehouse, cujo
desenho é elaborado de tal forma a atender a um segmento ou unidade de uma organização. Desta forma
ele faz parte da estratégia adotada no Data Warehouse. São considerados como Data Warehouses
departamentais, nos quais os dados são ajustados aos requisitos de cada área ou departamento.
São muito utilizados em pequenas empresas ou com o objetivo de reduzir a complexidade de um
projeto de Data Warehouse. É costume dividir essa arquitetura em três camadas, assim distribuídas:
1) Camada do banco de dados transacional, em que os dados da empresa são propriamente arma-
zenados.
2) Camada do Data Warehouse, um repositório de dados históricos com informações detalhadas.
3) Camada do Data Mart, que são conjuntos de tabelas estruturadas, alimentadas pela segunda
camada.
Veja o diagrama apresentado na Figura 20.10.
Os sistemas de Datamining (Mineração de Dados) trabalham com previsões, ou seja, por meio de
árvores de decisão buscam avaliar o que pode acontecer, permitindo dessa maneira responder a
questões como "e se ocorresse tal situação?". Assim os executivos, gerentes e analistas podem tomar
medidas preventivas e não corretivas. É conceitualmente diferente do Data Warehouse, que fornece
respostas a questões sobre o passado histórico da organização.
FIGURA 20.10
Entre alguns dos principais tipos de aplicações que fazem uso do Datamining podemos encontrar:
Marketing e propaganda: análise do comportamento dos consumidores com relação aos
seus padrões de compra.
Finanças: avaliação de concessões de crédito a clientes, análise de desempenho de investi-
mentos e aplicações financeiras.
Manufatura: otimização de recursos, força de trabalho e matéria-prima.
Saúde: análise da eficácia de determinados tratamentos, relacionamento de dados entre
diagnósticos e pacientes.
20.4. Exercícios
1) O que é endereço URL?
2) Como é efetuada uma requisição de página a um servidor Web?
3) O que é CGI?
4) O que é ISAPI?
FIGURA 21.1
Há opções bastante variadas para a criação de uma tabela no Access, como mostra a Figura 21.3.
Também é possível criar consultas de forma interativa, Figura 21.4. Essas consultas criam automati-
camente comandos SQL para recuperar as informações do banco de dados.
Para apresentar os dados de uma tabela, o Access utiliza uma tela similar a uma planilha de cálculos,
Figura 21.5. Os dados de tabelas que estão ligadas por um relacionamento podem ser apresentados de
forma agrupada, como indica a Figura 21.6.
FIGURA 21.7
FIGURA 21.8
FIGURA 21.10
Um recurso inovador inaugurado pelo Access foram as macros, pequenas rotinas agrupadas num
mesmo módulo que podem executar tarefas simples, como abertura de um formulário, impressão de
um relatório ou execução de uma consulta. A Figura 21.11 mostra a tela de definição de macros.
Ao programador mais avançado (ou exigente) o Access oferece uma poderosa linguagem derivada da
famosa ferramenta Visual Basic. Com ela é possível desenvolver aplicações poderosas. Na Figura
21.12 é possível ver a tela do editor de códigos.
A definição dos relacionamentos entre as diversas tabelas do banco de dados também é efetuada
visualmente, como mostra a Figura 21.13.
FIGURA 21.12
FIGURA 21.21
A Figura 21.22 apresenta o editor de códigos que permite a criação de stored procedures. Os
comandos SQL são executados na tela da Figura 21.23, que pode ser aberta clicando com o botão
direito do mouse no nome do banco de dados e escolhendo a opção New Query do menu mostrado
pela Figura 21.24. Veja um exemplo na Figura 21.25.
FIGURA 21.23
FIGURA 21.24
21.3. MySQL 5
O MySQL é um servidor de banco de dados relacional que faz parte de um novo segmento de
software denominado Software Livre. Ele possui características e recursos que o tornam uma
excelente alternativa aos dispendiosos sistemas oferecidos por grandes empresas.
Totalmente escrito em C/C++, ele foi desenvolvido por dois suecos (David Axmark e Allan Larsson)
e um finlandês (Michael "Monty" Widenius), com base em outro projeto de banco de dados, o mSQL
(também conhecido como miniSQL), idealizado pelo pesquisador australiano David Hughes.
É um servidor multithreaded, ou seja, pode criar vários subprocessos de execução dentro de um
mesmo processo maior para atender simultaneamente às diversas solicitações dos usuários.
Uma característica bastante interessante é que ele consome poucos recursos da máquina, como memória e
espaço em disco, e mesmo assim proporciona alto desempenho.
Sua disponibilidade para diversos sistemas operacionais, como Windows, Linux (nas mais diversas
distribuições), Solaris, FreeBSD, Mac OS, HP-UX, AIX, SGI Irix etc., torna-o ideal para projetos que
precisam rodar em plataformas diferentes (multiplataformas).
O MySQL tem sido empregado frequentemente no gerenciamento de banco de dados de sites de
e-commerce (comércio eletrônico), data warehouse (armazém de dados) e aplicações de gestão
empresarial, como Enterprise Research Planning (ERP) e Customer Relationship Manager (CRM).
Entre os grandes usuários do MySQL podem ser mencionados Yahoo, Cisco, Nasa, Lucent
Technologies, Motorola, Google, Silicon Graphics, HP, Xerox.
Em relação à conectividade, ele oferece suporte a soquetes TCP/IP, Unix e Named Pipes (Windows NT)
e interface para Open DataBase Connectivity (ODBC) e Java DataBase Connectivity (JDBC). Possui
também interface para desenvolvimento de aplicações em C, C++, Java, Perl, PHP, Eiffel, Python e TCL.
O MySQL se enquadra no tipo de licença General Public License (GPL), em que, além do aplicativo
executável, também se encontra disponível gratuitamente o código-fonte do software. Se estiver
desenvolvendo uma aplicação que usa MySQL e pode ser distribuída e utilizada segundo os termos da
GPL, ele pode ser disponibilizado sem precisar pagar licença. Se sua aplicação for comercial (vendida
aos clientes), é preciso adquirir uma versão licenciada do MySQL.
FIGURA 21.26
FIGURA 21.27
Para criar outra conexão, clique no botão New Connection e depois forneça um nome para a
conexão, uma identificação de usuário e a senha de acesso. Na caixa de entrada Hostname, digite
uma cadeia de caracteres que representa o nome do servidor ou seu endereço IP.
Quando a tela inicial retornar, a partir da caixa de combinação superior selecione a conexão que
acabou de ser criada. Coloque a senha e clique no botão OK.
A tela da Figura 21.28 deve então aparecer. Note que o status é mostrado como MySQL Server is
running, o que significa que o servidor MySQL roda perfeitamente. Ao selecionar a opção Catalogs,
O botão Create Table permite que novas tabelas sejam adicionadas através da tela mostrada pela
Figura 21.32. Já o botão Edit Table abre a tela da Figura 21.33, contendo a estrutura da tabela
selecionada para que seja possível fazer alterações, como incluir novos campos.
A guia Stored procedures, Figura 21.34, lista todos os procedimentos criados pelo desenvolvedor.
Para adicionar um novo procedimento, clique no botão Create Stored Proc e o editor mostrado na
Figura 21.35 é apresentado.
FIGURA 21.34
FIGURA 21.35
FIGURA 21.36
FIGURA 21.37
FIGURA 21.38
FIGURA 21.39
Com o botão Administração podemos gerenciar os usuários do sistema selecionando uma das opções
do item Usuários do BD, Figura 21.40. Na Figura 21.41 é possível ver a tela de criação de usuário.
Já a criação de uma tabela é efetuada com a opção Criar → Tabela do menu aberto pelo botão Browser
de Objetos, Figura 21.42. A estrutura da tabela é então definida na tela mostrada na Figura 21.43.
FIGURA 21.42
FIGURA 21.43
FIGURA 21.44
FIGURA 21.45
FIGURA 21.46
FIGURA 21.47
FIGURA 21.48
Bem, meu caro amigo, assim finalizamos nossa pequena viagem por esse maravilhoso mundo dos
bancos de dados. Como sempre é de meu costume dizer, espero que tenha sido proveitosa e que tudo
que foi apresentado tenha contribuído para aumentar seus conhecimentos ou mesmo para sanar algu-
mas pequenas dúvidas. E que DEUS abençoe a todos, tanto na vida pessoal quanto na profissional!
Aplicação cliente/servidor: Programa aplicativo de banco de dados que roda em parte no servidor e
em parte na estação cliente.
Atributo: É o componente principal de uma entidade, sendo representado nos bancos de dados
físicos como campo.
Back-Ends: Programas responsáveis pelo gerenciamento das informações do banco de dados e que
respondem a solicitações das estações clientes.
Banco de dados relacional: Tipo de banco de dados cujas informações são armazenadas em tabelas,
também chamadas relações.
Banco de dados: Conjunto de uma ou mais tabelas (arquivos de dados) em que são armazenadas
informações de forma coerente.
BDE: Sigla de Borland Database Engine, é a arquitetura de acesso à base de dados desenvolvida pela
Borland para suas ferramentas de desenvolvimento (Delphi, C++Builder, JBuilder etc.).
Campo autoincremento: Campo cujo valor é automaticamente atualizado em uma unidade quando
da inserção de novos registros.
Campo calculado: Um campo cujo valor depende do resultado de um cálculo que envolve outros
campos, que é representado por uma expressão matemática.
Campo formatado: Possui uma cadeia de caracteres que força os dados desse campo a serem
armazenados e apresentados num determinado formato.
CGI: Sigla de Common Gateway Interface, é uma interface entre um servidor Web e um navegador
que permite a transferência de dados para páginas HTML.
Chave candidata: Campo ou conjunto de campos de uma tabela de dados que possui valor único,
mas não é definido como chave primária.
Chave primária: Campo ou conjunto de campos utilizado pelo gerenciador de banco de dados para
criar índices e que não permite duplicidade de informação.
Cliente: Computador que pertence a uma rede e tem por função servir de estação de trabalho para o
usuário.
Glossário 277
Data Warehouse: Sistema em que informações originárias de diversos bancos de dados utilizados
dentro da empresa são agrupadas num repositório de dados.
Dead-lock: Situação que ocorre quando, num ambiente multiusuário, mais de um usuário está tentan-
do alterar as informações do mesmo registro.
Dicionário de dados: Local onde se encontram armazenadas informações sobre o banco de dados,
como descrição dos domínios, das estruturas das tabelas, dos relacionamentos etc.
Embedded SQL: Processo pelo qual é possível incluir comandos SQL em outras linguagens de
programação, como COBOL, C, Pascal etc.
Entidade: Conjunto de informações sobre um item específico que se deseja armazenar num banco de
dados.
Firewall: Software ou equipamento responsável pelas tarefas de triagem dos pacotes TCP/IP que
trafegam pela rede interna ou externa (Internet). O objetivo principal é bloquear acessos não
autorizados, como o de invasores de sistemas.
Formulários: Telas criadas para aplicações que servem de interface com o usuário.
Front-Ends: Programas que servem como interface para o usuário para acesso a um banco de dados.
HTTP: Protocolo de rede embasado no TCP/IP e utilizado nas transações que envolvem a
comunicação entre um navegador e o servidor Web.
IDAPI: Sigla de Integrated Database Application Programming Interface, também é uma arquitetura
de conexão a banco de dados desenvolvida pela Borland e rival do ODBC.
Índice: Estrutura utilizada pelos bancos de dados para colocar os registros numa determinada ordem
ou agilizar as pesquisas efetuadas pelo usuário.
Integridade referencial: Restrição aplicada a uma tabela que impede alterações que possam afetar os
dados de outra tabela que possui uma ligação dependente do registro alterado.
LAN: Sigla de Local Area Network, uma rede de microcomputadores que se encontram a curtas
distâncias, como num mesmo prédio.
Macro: Conjunto de pequenas rotinas que executam tarefas bastante simples, como impressão de
relatórios ou apresentação de mensagens.
Network Computer (NC): Arquitetura de computador projetada pela Sun Microsystems, cujo
principal objetivo era baixar os preços dos equipamentos para cerca de US$ 500,00.
ODBC: Sigla de Open DataBase Connectivity, é uma arquitetura desenvolvida pela Microsoft que permite
aos aplicativos conectarem-se com bancos de dados através de drivers desenvolvidos pelos fabricantes.
Pesquisa: Meio oferecido pelos bancos de dados para localizar um determinado registro.
Relacionamento: Ligação lógica criada entre duas tabelas que permite o acesso automático às
informações contidas nelas.
Rule: Regras de validação que devem ser aplicadas aos campos de uma tabela.
Servidor de aplicações: Computador da rede que tem como função gerenciar banco de dados e
outros aplicativos.
Servidor de arquivos: Computador da rede que tem por função centralizar o armazenamento de
arquivos de uma organização.
Servidor: Computador que pertence a uma rede capaz de oferecer diversos recursos compartilhados,
como arquivos, impressoras, conexão com Internet.
Sistema gerenciador de banco de dados: Software responsável pela criação de banco de dados e
manipulação dos seus registros.
Stored Procedure: Pequenas rotinas escritas em linguagem SQL que são armazenadas no próprio
banco de dados e executadas por meio de chamadas explícitas pelas aplicações clientes.
TCP/IP: Protocolo de rede que permite a comunicação entre dois computadores que possuem
arquitetura e sistema operacional diferentes.
Glossário 279
Transação: Conjunto de comandos que devem ser executados numa determinada sequência para que
uma operação completa seja executada no banco de dados.
Trigger: Rotinas incorporadas aos bancos de dados SQL que permitem a execução de operações
quando da manipulação de registros (inserção, atualização, exclusão etc.).
Validação: Uma regra imposta a um campo que não permite o armazenamento de valores que estejam
fora da especificação dada.
Valor padrão: Um valor que é automaticamente atribuído ao campo quando um novo registro é
inserido.
View (Visão): Seleção de uma ou mais tabelas do banco de dados que é tratada como um subcon-
junto deste, similarmente a uma tabela.
WAN: Sigla de Wide Area Network, uma rede de computadores que podem estar localizados a gran-
des distâncias e utilizam na comunicação a infraestrutura da Internet, radiofrequência, satélite etc.
Bibliografia 281
Marcas Registradas
Turbo C++, Turbo Pascal, InterBase, Delphi, C++Builder e JBuilder são marcas registradas da
Embarcadero Technologies, Inc.
Access, Visual Basic, Visual C++, SQL Server 2000/2008, Windows 95/98/Me/XP/2000/2003/
2008/Vista são marcas registradas da Microsoft Corporation.
MySQL é marca registrada da Sun Microsystems, Inc.
Oracle é marca registrada da Oracle Corporation.
Sybase, SQLAnywhere e PowerBuilder são marcas registradas da Sybase, Inc. Trademarks.
SQLBase é marca registrada da Gupta Technologies.
ERwin e Jasmine são marcas registradas da Computer Associates.
PostgreSQL é marca registrada da PostgreSQL Inc.
Informix e DB2 são marcas registradas da IBM Corporation.
Todos os demais nomes registrados, marcas registradas ou direitos de uso citados neste livro perten-
cem aos seus respectivos proprietários.
A Chave
candidata, 43
Abstração de dados, 24 da entidade, 150
Access, 23, 25, 40, 42, 46, 49, 50, 216, 259-262 estrangeira, 44, 48
Acesso primária, 38, 42-46, 48, 51, 145, 146, 150-152
aleatório, 55 Classificação Bolha, 67
sequencial, 55 Cliente/servidor, 197, 219-221, 240, 246, 251
Ada, 160, 168 Clipper, 220
ADABAS, 209, 210 COBOL, 24, 29, 160, 168, 209, 210, 219, 221
ADO, 32 CODASYL, 28
ALTER Comércio eletrônico, 250, 268
DATABASE, 162 COMMIT, 52, 242
TABLE, 163 Computação distribuída, 196
ANSI/ISO, 160, 163, 165, 230 Condicionalidade, 136
Apache, 250 CONSTRAINT, 49
AppleTalk, 215 Controladora de terminais, 206, 207
Arquitetura cliente/servidor, 206, 212, 213, 215 Controle de
Arquivos sequenciais, 20 acesso concorrente, 203
Árvore binária, 64 concorrência, 25, 31
ASP, 248, 250, 258 CORAL, 175, 179
Atributos, 116, 121, 132 CORBA, 194-196
CREATE
B DATABASE, 162
DOMAIN, 164
Back-end, 212 INDEX, 164
Backups, 237 TABLE, 162
Banco de dados, 20, 22-25, 30-32, 37-56, 65, 85, 91, VIEW, 165
129, 131, 132, 147, 148, 157-163, 197, 205, 209, CRM, 268
212-221, 229, 230, 237, 240, 241, 252, 255, 256,
259, 262, 265, 267, 268
de rede, 28, 29 D
dedutivo, 175
Data
distribuído, 197, 198, 200, 202, 205
Blades, 193
hierárquico, 30, 31
Division, 24
objeto-relacional, 26
Mart, 256
orientado a objeto, 182-184, 192
Warehouse, 252-256
relacional, 26, 27, 121, 130, 159, 160, 175,
178,185, 210 Datalog, 175, 178
BLOB, 38 Datamining, 252, 256, 257
Borland, 70 DB2, 159, 210, 218, 250, 252, 256
Bubble Sort, 67, 100 DB2 Universal DB, 192
dBase, 259
III, 31
C IV, 31
DBTG, 28
C/C++, 24, 55, 210, 247, 267
DCL, 161
C++, 160, 168, 180-185, 187, 188, 191, 193, 195
DDL, 161
C++Builder, 221
Deadlock, 203, 244, 245
Campo, 37, 38, 41-49, 51
Define, 187
Cartão perfurado, 20
DELETE, 230
Catálogo do sistema, 33, 53, 121
FROM, 166
CGI, 247, 248, 250, 257
P
M
PalmOS, 55
Macintosh, 271 Paradox, 42, 49, 216
Mainframes, 210, 219 Pascal, 24, 29, 69, 70, 74, 78, 82, 85, 89, 92, 160,
Metadados, 33, 50, 121, 251 168
Metamodelo, 129 Persistência, 185
Microsoft, 217, 259 Pesquisa
Middleware, 195, 247 binária, 87, 91, 101
Minicomputadores, 219 sequencial, 85
Minimundo, 130 PHP, 268
Modelagem de Dados, 129 Pilhas, 58, 59, 67
Modelo Plano de consulta, 42
abstrato, 130 PocketPC, 160
conceitual, 130, 131 Polimorfismo, 182, 183, 194
de dados multidimensional, 253 PostgreSQL, 160, 218
de dados orientados a objeto, 26 PowerBuilder, 221
de dados relacional, 26 Predicado, 175, 176, 177
de dados, 26, 28, 53, 175, 255 Pré-processador, 160, 168
físico, 130, 132 Programação orientada a objeto, 181, 182
hierárquico, 28 Prolog, 175, 177-179
lógico, 130, 132 Protocolos de rede, 212, 214
MySQL, 23, 40, 121, 122, 160, 218, 267, 268 Proxy, 237
MySQL Administrator, 268
Q
N QBE, 255
NAIL!, 175, 177-179 QuickSort, 76, 79-81
NetBIOS, 215
Netscape, 247
NetWare, 210, 213 R
NSAPI, 247, 248 Recursividade, 77, 177, 179
Registro, 39-43, 48, 51
corrente, 56
O de informações, 19, 20
Objectivity/DB, 191 Relacionamento(s), 130, 150
ObjectStore, 180, 188, 191 condicionais, 136
ODBC, 32, 217, 268 incondicionais, 136
ODL, 180, 185 Relações, 26, 30
ODMG, 180 Replicação de dados, 200, 205
ODMG-93, 180 Repositório de dados, 219, 253, 256
ODS, 253 Representação conceitual dos dados, 24
OID, 183, 184 REVOKE, 161, 167, 230
OLAP, 252, 254, 256 ROLLBACK, 52, 242
Banco de Dados
Oracle Database 10g Express Edition - Guia de Instalação, Configuração e Administração
com Implementação PL/SQL Relacional e Objeto-Relacional
Autor: Robson Soares Silva
Código: 1628 • 240 páginas • Formato: 17 x 24 cm • ISBN: 978-85-365-0162-8 • EAN: 9788536501628
O livro detalha os principais recursos desse poderoso banco de dados, como a aquisição e instalação do programa,
criação de tabelas, chaves primária e estrangeira, consultas SQL, utilização de índices, usuários do sistema, criação de
usuários, concessão e restrição de direitos de acesso, programação PL/SQL, procedures, functions, packages, triggers,
implementação objeto-relacional, criação de aplicações, acesso remoto, backup e restore, mashback, níveis de certilcação e
conexão Oracle com o Java.
Possui também diversos exercícios propostos, além de um simulado com questões para certilcação.
Banco de Dados