Académique Documents
Professionnel Documents
Culture Documents
Brasília-DF, 2011.
Elaboração:
Produção:
2
Sumário
Apresentação........................................................................................................................................... 04
Organização do Caderno de Estudos e Pesquisa ................................................................................... 05
Organização da Disciplina ...................................................................................................................... 06
Introdução ............................................................................................................................................... 07
Unidade I – Introdução à Modelagem Conceitual ................................................................................ 09
Capítulo 1 – Bancos de Dados e seus Usuários .......................................................................... 09
Capítulo 2 – Conceitos e Arquiteturas de um SGBD ................................................................... 16
Capítulo 3 – Modelagem de Dados Utilizando o MER ................................................................. 28
Unidade II – Introdução à Modelagem Conceitual ............................................................................... 41
Capítulo 4 – Modelo de Dados Relacional .................................................................................. 41
Capítulo 5 – Projeto de Banco de Dados Relacional Utilizando o MER ......................................... 48
Capítulo 6 – SQL – Structured Query Language ......................................................................... 52
Unidade III – Teoria e Metodologia do Projeto de Banco de Dados .................................................... 81
Capítulo 7 – Dependência Funcional e Normalização .................................................................. 81
Capítulo 8 – Metodologia para Projeto Prático de Banco de Dados ............................................. 92
Unidade IV – Armazenagem de Dados, Indexação, Processamento de Consultas e Projeto Físico .. 95
Capítulo 9 – Algoritmos para Processamento e Otimização de Consultas ................................... 95
Capítulo 10 – Técnicas de Controle de Concorrência ................................................................. 99
Capítulo 11 – Técnicas de Recuperação de Dados ..................................................................... 108
Para (não) Finalizar ................................................................................................................................ 122
Referências .............................................................................................................................................. 123
Apêndice I – Palavras-Chave do SQL .................................................................................................... 124
Apêndice II – Expressões de Valor ........................................................................................................ 137
Apêndice III – Comandos SQL ............................................................................................................... 143
Pós-Graduação a Distância
3
Apresentação
Caro aluno,
Este é o nosso Caderno de Estudos e Pesquisa, material elaborado com o objetivo de contribuir para a realização e o
desenvolvimento de seus estudos, assim como para a ampliação de seus conhecimentos.
Para que você se informe sobre o conteúdo a ser estudado nas próximas semanas, conheça os objetivos da disciplina, a
organização dos temas e o número aproximado de horas de estudo que devem ser dedicadas a cada unidade.
A carga horária desta disciplina é de 80 (oitenta) horas, cabendo a você administrar o tempo conforme a sua disponibilidade.
Mas, lembre-se, há uma data-limite para a conclusão do curso, incluindo a apresentação ao seu tutor das atividades
avaliativas indicadas.
Os conteúdos foram organizados em unidades de estudo, subdivididas em capítulos, de forma didática, objetiva e
coerente. Eles serão abordados por meio de textos básicos, com questões para reflexão, que farão parte das atividades
avaliativas do curso; serão indicadas, também, fontes de consulta para aprofundar os estudos com leituras e pesquisas
complementares.
Desejamos a você um trabalho proveitoso sobre os temas abordados nesta disciplina. Lembre-se de que, apesar de
distantes, podemos estar muito próximos.
A Coordenação
Sistemas de Banco de Dados
4
Organização do Caderno de Estudos e Pesquisa
Introdução: Contextualização do estudo a ser desenvolvido por você na disciplina, indicando a importância desta para
sua formação acadêmica.
Provocação: Pensamentos inseridos no material didático para provocar a reflexão sobre sua prática e
seus sentimentos ao desenvolver os estudos em cada disciplina.
Para refletir: Questões inseridas durante o estudo da disciplina para estimulá-lo a pensar a respeito
do assunto proposto. Registre sua visão sem se preocupar com o conteúdo do texto. O importante é
verificar seus conhecimentos, suas experiências e seus sentimentos. É fundamental que você reflita
sobre as questões propostas. Elas são o ponto de partida de nosso trabalho.
Textos para leitura complementar: Novos textos, trechos de textos referenciais, conceitos de
dicionários, exemplos e sugestões, para lhe apresentar novas visões sobre o tema abordado no texto
básico.
Sintetizando e enriquecendo nossas informações: Espaço para você fazer uma síntese dos textos
e enriquecê-los com sua contribuição pessoal.
Praticando: Atividades sugeridas, no decorrer das leituras, com o objetivo pedagógico de fortalecer o
processo de aprendizagem.
Para (não) finalizar: Texto, ao final do Caderno, com a intenção de instigá-lo a prosseguir com a
Pós-Graduação a Distância
reflexão.
5
Organização da Disciplina
Ementa:
Sistemas de banco de dados. Sistemas de gerenciamento de banco de dados. Modelagem de dados. Modelos conceituais. O
modelo relacional. Normalização. A linguagem SQL. Projeto de banco de dados. Implementação de SGBDs. Armazenamento
de dados. Estruturas de índices. Processamento e otimização de consultas. Processamento de transações. Controle de
concorrência. Recuperação.
Objetivos:
– Contribuir para a capacitação do participante quanto à análise, planejamento, estruturação e implementação
de sistemas de gerenciamento de banco de dados.
6
Introdução
Ao olharmos para os processos modernos que nos prestam serviços ou mesmo nos que somos os próprios prestadores de
serviços, é possível inferir que existem gigantescas bases de dados que dão suporte ou até mesmo gerenciam nossas vidas.
Questões como a nossa conta bancária. As instituições bancárias mantêm bancos de dados que permitem o gerenciamento
de todas as transações financeiras realizados. São esses registros que permitem que seja possível acompanhar saldos,
aplicações, saques e manter todo histórico de cada conta de cada cliente.
Processos como a apuração das eleições ou mesmo o processamento da declaração do imposto de renda também são
suportados por bancos de dados mantidos pelo governo e que permitem que seja possível, como no caso deste último,
acompanhar o histórico de cada cidadão.
Pós-Graduação a Distância
7
8
Sistemas de Banco de Dados
Unidade I
1. Introdução
Segundo Silberschatz (2006), um banco de dados é um conjunto de dados inter-relacionados. Podemos afirmar que
esses bancos possuem informações que representam o dia a dia de uma empresa, de uma loja, de uma locadora de vídeo,
enfim, de qualquer ambiente que possa ter suas informações coletadas e representadas de uma forma organizada. Tais
bancos de dados, além de manter todo esse volume de dados organizado, também devem permitir atualizações, inclusões e
exclusões de dados, sem nunca perder a consistência. E, além disso, é necessário considerar que muitas vezes estaremos
lidando com vários acessos simultâneos e concorrentes em várias partes diferentes de nosso banco de dados.
Heuser (2001) define dado como sendo um fato do mundo real que está registrado e possui um significado implícito no
contexto de um domínio de aplicação. Um banco de dados possui as seguintes propriedades:
• é uma coleção lógica coerente de dados com um significado inerente; uma disposição desordenada dos dados
não pode ser referenciada como um banco de dados;
• é projetado, construído e populado com dados para um propósito específico; um banco de dados possui um
Pós-Graduação a Distância
Um banco de dados pode ser criado e mantido por um conjunto de aplicações desenvolvidas especialmente para a
tarefa, denominada Sistema de Gerenciamento de Banco de Dados (SGBD). Um SGBD permite aos usuários criar e
manipular bancos de dados de propósitos gerais. Silberschatz (2006) define SGBD como sendo uma coleção de dados
inter-relacionados e um conjunto de programas para acessar esses dados.
9
Introdução à Modelagem Conceitual Unidade I
1.1. Metadados
Uma característica importante da abordagem Banco de Dados é que o SGBD mantém não somente os dados, mas
também a forma como esses são armazenados, uma vez que contém uma descrição completa do banco de dados.
Essas informações são armazenadas no catálogo do SGBD, o qual contém informações como a estrutura de cada arquivo,
o tipo e o formato de armazenamento de cada tipo de dado, restrições. Segundo Heuser (2001), o conjunto de informações
armazenadas no catálogo de dados é denominado Metadados.
No processamento tradicional de arquivos, o programa que irá manipular os dados deve conter este tipo de informação,
ficando limitado a manipular as informações que ele conhece. Por outro lado, utilizando a abordagem banco de dados, a
aplicação pode manipular diversas bases de dados diferentes.
O processamento tradicional de arquivos pressupõe que a estrutura de dados está incorporada ao próprio programa de
acesso. Assim sendo, uma alteração na estrutura de arquivos resulta na alteração do código fonte de todos os programas.
Porém, a abordagem de banco de dados permite que as alterações sejam efetuadas apenas no catálogo de dados, sem
necessitar alterações nos programas de acesso.
Uma das funções de um SGBD é fornecer aos usuários uma representação conceitual dos dados sem que, para tanto,
necessite fornecer muitos detalhes de como os dados estão armazenados.
Um Modelo de Dados é uma forma de abstração dos dados que é utilizada para fornecer essa representação conceitual,
utilizando conceitos lógicos como objetos, suas propriedades e seus relacionamentos (ALVES, 2004).
Os níveis de abstração têm como função, inclusive, ocultar a complexidade e simplificar o processo de interação com os
usuários. Sob esse ponto de vista, podemos classificar a abstração em três níveis (SILBERSCHATZ, 2006).
• Físico: é o nível de abstração mais baixo e descreve como os dados são realmente armazenados no banco de
dados. Nesse nível, um registro de dado pode ser descrito como um bloco consecutivo de memória.
• Lógico: é nível de abstração intermediário, que descreve que os dados estão armazenados no banco de dados
e quais são as relações existentes entre eles. Nesse nível, um registro de dado é descrito por um tipo definido
(como um tipo em linguagem de programação) e as inter-relações entre dados são definidas.
• Visualização: é o nível de abstração mais alto, que descreve a parte do banco de dados de maior interesse
para o usuário final. Nesse nível, podemos dizer que se trata de subconjunto de dados que podem existir
apenas durante a execução de uma operação.
Uma vez que um banco de dados deve permitir o acesso de um conjunto diverso de usuários a todo o seu conteúdo, é
possível inferir que cada usuário, ou grupo de usuários, pode ter uma necessidade específica. Desse modo, é necessário
que cada conjunto de usuário tenha a possibilidade de ter visões diferentes da base de dados.
Assim, uma visão é definida como um subconjunto de uma base de dados, formando desse modo, um conjunto virtual
de informações (SILBERSCHATZ, 2006).
10
Introdução à Modelagem Conceitual Unidade I
2. Usuários
Em todo grande banco de dados existe um grande número de pessoas envolvidas que varia desde sua concepção e seu
projeto até sua manutenção.
Um ambiente de banco de dados envolve vários recursos que vão desde o banco de dados em si até o SGBD e outros
softwares. Cabe ao Administrador de Banco de Dados (DBA) o seu gerenciamento, envolvendo tarefas como a
autorização de acesso a ele, a sua coordenação e a monitoração de seu uso.
Cabe ao Projetista de Banco de Dados a identificação dos dados que devem ser armazenados, bem como a definição
da estrutura adequada para representá-los e armazená-los. É função do projetista também avaliar as necessidades de
cada grupo de usuários para definir as visões que serão necessárias, integrando-as, fazendo com que o banco de dados
seja capaz de atender a todas as necessidades dos usuários.
Os usuários finais são as pessoas que utilizam o banco de dados fazendo consultas, atualizações e gerando documentos.
Podemos agrupar esses usuários em três categorias:
• casuais: acessam o banco de dados casualmente, mas podem necessitar de diferentes informações a cada
acesso; utilizam sofisticadas linguagens de consulta para especificar suas necessidades;
• usuários avançados: são usuários que estão familiarizados com o SGBD e realizam consultas complexas.
Os Analistas de Sistemas são responsáveis pela determinação dos requisitos dos usuários finais e pelo desenvolvimento
das especificações para atender aos requisitos mapeados. Por sua vez, os Programadores são responsáveis pela
implementação das especificações definidas na forma de programas, testando, depurando, documentando e dando
manutenção.
3. Esquemas de Dados
Segundo Silberschatz (2006), os esquemas de dados dizem respeito ao projeto geral do banco de dados e é um aspecto
que raramente é modificado.
Um esquema de base de dados é especificado durante o projeto da base de dados e a forma de visualização de um
esquema é chamada Diagrama do Esquema.
Pós-Graduação a Distância
Os SGBDs possuem vários esquemas de banco de dados que variam em função do nível de abstração dos dados:
• esquema físico: tem como objetivo descrever o projeto do banco de dados no nível físico;
• subesquema de visualização: diz respeito à descrição das visualizações possíveis para um banco de dados.
Muitos modelos de dados têm certas convenções para, diagramaticamente, mostrar esquemas especificados neles.
11
Introdução à Modelagem Conceitual Unidade I
Alguns autores defendem que uma das maiores contribuições dos primeiros SGBDs foi introduzir a separação entre os
dados armazenados e a descrição da estrutura dos dados, o esquema de dados.
4.1. Desvantagens
As organizações têm se tornado cada vez mais complexas e os processos de negócio, por sua vez, refletem a necessidade
da disponibilidade de dados de forma rápida, precisa e flexível. Como conseqüência, os bancos de dados acabam por se
tornar cada vez mais complexos, volumosos e onerosos.
Apesar dos custos relativos ao armazenamento de dados estarem sendo reduzidos em ritmo acelerado, juntamente com
a popularização do hardware necessário, aspectos como a concepção, o gerenciamento e a manutenção de bancos de
dados cada vez mais pesam no orçamento de seu projeto. Por vezes, os custos podem se tornar um empecilho para a
adoção de um banco de dados.
A par e passo com a evolução da necessidade de informações, os bancos de dados também necessitam de manutenção
evolutiva e/ou corretiva. Uma vez que um processo na organização, que é suportado por um banco de dados, sofre alguma
mudança, a necessidade de informações para geri-lo adequadamente também muda. Além disso, a evolução tecnológica
dos SGBDs imprime a necessidade de ajustes de versão de software e/ou upgrades para que seja possível usufruir dos
benefícios que estes sistemas oferecem.
Desse modo, a necessidade de uma estrutura para gerenciar o banco de dados, bem como a necessidade de mantê-lo,
gera custos que podem tornar o seu uso proibitivo.
4.2. Vantagens
No processamento tradicional de tratamento de arquivos, é necessário que cada grupo de usuários mantenha seu próprio
conjunto de arquivos e dados, o que pode fazer com que acabe ocorrendo redundâncias que prejudiquem o sistema com
problemas como:
• toda vez que for necessário atualizar um arquivo de um grupo, todos os grupos devem ser atualizados para
manter a integridade dos dados no ambiente como um todo;
Sistemas de Banco de Dados
A utilização de um SGBD permite que múltiplos usuários acessem o banco de dados ao mesmo tempo, permitindo que
múltiplas aplicações integradas possam acessá-lo.
O SGBD multiusuário necessita manter o controle de acessos simultâneos (concorrência) para assegurar a qualidade
do resultado de atualizações, bem como fornecer recursos que permitam a construção de múltiplas visões.
12
Introdução à Modelagem Conceitual Unidade I
Um SGBD permite que seja criado um subsistema de autorização e segurança, o qual é utilizado pelo DBA para criar
contas de acesso e especificar as restrições de cada conta, sendo estendido tanto para acesso aos dados quanto ao
uso de softwares inerentes ao SGBD.
Um banco de dados permite que seja catalogada uma variedade de dados que estão inter-relacionados de várias formas.
Por sua vez, um SGBD fornece uma série de recursos para representar uma grande variedade de relacionamentos entre
os dados, bem como recuperá-los e atualizá-los de maneira prática e eficiente.
4.2.5. Padronização
A abordagem de base de dados permite que o DBA defina e obrigue a padronização entre os usuários da base de dados
em grandes organizações. Isso facilita a comunicação e a cooperação entre vários departamentos, projetos e usuários.
Padrões podem ser definidos para formatos de nomes, elementos de dados, telas, relatórios, terminologias.
É possível utilizar esse recurso, com maior facilidade, em um ambiente de base de dados centralizado, em comparação
com um ambiente onde cada usuário ou grupo tem o controle de seus próprios arquivos e programas de aplicação.
4.2.6. Flexibilidade
Mudanças nos requisitos podem acarretar a necessidade de modificações na estrutura de um banco de dados. Por
exemplo, um novo grupo de usuários pode surgir com necessidade de informações adicionais, ainda não disponíveis na
base de dados. Alguns SGBDs permitem que tais mudanças na estrutura da base de dados sejam realizadas sem afetar
a maioria dos programas de aplicações existentes.
Uma das características mais significativas da abordagem de base de dados é o tempo reduzido para o desenvolvimento
de novas aplicações, como a recuperação de certos dados da base de dados para a impressão de novos relatórios.
Projetar e implementar uma nova base de dados pode tomar mais tempo do que escrever uma simples aplicação
especializada de arquivos. Porém, uma vez que a base de dados esteja em uso, geralmente é bastante reduzidoo tempo
para se criar novas aplicações, usando-se os recursos de um SGBD. O tempo para se desenvolver uma nova aplicação em
um SGBD é estimado em 1/4 a 1/6 do tempo de desenvolvimento, usando-se apenas o sistema de arquivos tradicional,
devido às facilidades de interfaces disponíveis em um SGBD.
A abordagem de banco de dados permite que tão logo um usuário modifique uma base de dados, todos os outros usuários
podem usufruir imediatamente dessa modificação. Essa disponibilidade de informações atualizadas é essencial para muitas
aplicações, tais como sistemas de reservas de passagens aéreas ou bases de dados bancárias.
Pós-Graduação a Distância
A abordagem de banco de dados permite a consolidação de dados e de aplicações, reduzindo-se, desse modo, o desperdício
em atividades redundantes de processamento em diferentes projetos ou departamentos.
Não raro, o uso de um SGBD pode representar um acréscimo desnecessário de custos, se comparado à abordagem de
processamento tradicional de arquivos. Exemplificando, podemos ter:
13
Introdução à Modelagem Conceitual Unidade I
É necessário reconhecer que problemas adicionais podem ocorrer como da resultado especificação inadequada do projeto
e/ou da implementação das aplicações de forma não apropriada. Caso o DBA não administre o banco de dados de forma
adequada, tanto a segurança quanto a integridade dos sistemas podem ser comprometidas. A sobrecarga causada pelo
uso de um SGBD e a má administração justificam a utilização da abordagem de processamento tradicional de arquivos
em casos como:
• o banco de dados e as aplicações sejam simples, bem-definidos e não sejam esperadas mudanças no projeto;
• sejá necessário processamento em tempo real de certas aplicações, que são terrivelmente prejudicadas pela
sobrecarga causada pelo uso de um SGBD;
No final dos anos 1960, a tecnologia de armazenamento em discos rígidos levou a uma mudança radical no cenário do
processamento de dados, pois permitiam o acesso direto aos dados, independentemente de sua posição no disco.
Entre as décadas de 1960 e 1970, várias pesquisas foram desenvolvidas no sentido de desenvolver tecnologias que
permitissem a simplificação dos processos de escritório que conduziram à automação. Tarefas como armazenar e organizar
arquivos, que dependiam única e exclusivamente de mão-de-obra intensiva, poderiam ser simplificadas com o uso de
soluções mecânicas mais eficientes e mais baratas. Desse modo, muitas pesquisas foram desenvolvidas e resultaram na
criação dos modelos hierárquicos, de rede e relacionais.
Nesse cenário, empresas, como a IBM, tomaram a dianteira e, em 1970, um pesquisador daquela empresa, Ted Codd,
publicou o primeiro artigo sobre bancos de dados relacionais, que tratava de um método que permitia que usuários
não técnicos pudessem armazenar e recuperar grande quantidade de dados, a partir da utilização de comandos que
manipulassem dados armazenados em tabelas.
Na década de 1980, com base nesse estudom, a IBM montou um grupo de pesquisa conhecido como Sistema R (System R)
que objetivava a criação de um banco de dados relacional que tivesse viabilidade comercial. O primeiro sistema comercial
baseado no conceito desenvolvido pela IBM, foi lançado em 1976 pela Honeywell Information Systems Inc. No entanto,
Sistemas de Banco de Dados
o primeiro SGBD construído nos padrões SQL só começou a surgir no mercado a partir do início da década de 1980 com
o Oracle 2, da empresa Oracle, e, posteriormente, com o SQL/DS, da IBM.
No início da década de 1990, um dos produtos do Sistema R foi a criação de uma linguagem denominada SQL –
Structured Query Language (Linguagem de Consulta Estruturada). A linguagem SQL tornou-se um padrão na indústria
para bancos de dados relacionais e hoje em dia, é um padrão ISO (International Organization for Standardization1), o
que permitiu o desenvolvimento e refinamento de softwares de banco de dados relacionais. Outros aspectos relevantes
que contribuíram para o refinamento e popularização dos bancos de dados relacionais foram: o retorno que os usuários
desses sistemas davam para o aprimoramento da linguagem, o desenvolvimento de sistemas para novas indústrias e
1 A ISO é a organização internacional de padronização responsável pelos padrões técnicos internacionais
14
Introdução à Modelagem Conceitual Unidade I
aumento do uso de computadores pessoais e sistemas distribuídos. O padrão SQL passou da IBM para a ANSI (American
National Standards Institute) – Instituto Nacional Americano para Padrões que, juntamente com a ISO, formaram um
grupo de trabalho para continuar o desenvolvimento. Este desenvolvimento ainda acontece com outras novas versões
dos padrões definidos até os dias atuais.
O final da década de 1990 foi marcado pela massificação do uso da World Wide Web (WWW), fazendo com que
os sistemas de banco de dados tivessem de trabalhar com taxas de processamento de transação cada vez maiores e
disponibilidade de 24x7, ou seja, disponibilidade 24 horas por dia, 7 dias por semana.
Em meados de 2000, surge a Linguagem Extensível de Formatação ou Extended Markup Language (XML) como
uma nova tecnologia de banco de dados. O XML é uma especificação técnica desenvolvida pela W3C – World Wide
Web Consortium1.
Pós-Graduação a Distância
15
Introdução à Modelagem Conceitual Unidade I
Uma distinção importante para qualquer modelo de dados é a que deve ser feita entre a descrição do banco de dados e o
próprio banco. A descrição de um banco de dados é chamada de esquema de um banco de dados e é especificada durante
o projeto do banco de dados. Geralmente, poucas mudanças ocorrem no esquema do banco de dados.
Uma instância1 do banco de dados diz respeito à coleção de dados armazenados em um banco de dados em um determinado
momento (SILBERSCHATZ, 2006). A instância modifica toda vez que uma alteração no banco de dados é feita. O SGBD é
responsável por garantir que toda instância do banco de dados satisfaça o seu esquema do banco de dados, respeitando
sua estrutura e suas restrições.
O esquema de um banco de dados também pode ser chamado de intensão de um banco de dados e a instância, de extensão
de um banco de dados.
A diferenciação entre esquema e instância de um banco de dados pode ser melhor compreendida fazendo uma analogia
com um programa, conforme ilustrado na Figura 2.1.
Variável Dados
Uma das vantagens mais relevantes de um banco de dados é a possibilidade de fornecer alguns níveis de abstração de
dados para o usuário final, omitindo os detalhes de como estes são armazenados.
16
Introdução à Modelagem Conceitual Unidade I
Segundo Silberschatz, um Modelo de Dados é uma coleção de ferramentas conceituais para descrever dados, relações
de dados, semântica de dados e restrições de consistência. Um modelo de dados permite descrever a estrutura1 de
um banco de dados de forma lógica e física. Além disso, vários Modelos de Dados também definem um conjunto de
operações para especificar como recuperar e modificar a base de dados.
Desse modo, podemos dizer que o Modelo de Dados é a principal ferramenta que fornece a abstração a um BD.
• baixo nível: ou modelo físico de dados, que fornece uma visão mais detalhada do modo como os dados estão
realmente armazenados no computador.
O primeiro modelo de dados a ser reconhecido foi o modelo hierárquico, que só pôde ser desenvolvido devido à consolidação
dos discos de armazenamento endereçáveis. Esses discos possibilitaram a exploração de sua estrutura de endereçamento
físico para viabilizar a representação hierárquica das informações.
No modelo hierárquico, os dados são estruturados em hierarquias ou árvores. Os nós das hierarquias contêm ocorrências
de registros, onde cada registro é uma coleção de campos (atributos), cada um contendo apenas uma informação.
O registro-pai é o registro da hierarquia que precede a outros, sendo esses outros denominados registros-filhos. Uma
ligação é uma associação entre dois registros. Possui cardinalidade 1:N o relacionamento entre um registro-pai e vários
registros-filhos.
Organizando os dados segundo o modelo hierárquico, esses podem ser acessados por meio de uma seqüência hierárquica
com uma navegação do topo para as folhas e da esquerda para a direita. Um registro pode estar associado a vários
registros diferentes, desde que seja replicado.
O Information Management System da IBM Corp (IMS) foi o sistema comercial mais divulgado no modelo hierárquico.
Uma boa parte das restrições e consistências de dados estava contida dentro dos programas escritos para as aplicações
Para acessar o banco de dados, era necessário escrever os programas na ordem.
O esquema de um banco de dados hierárquico é descrito por meio de um diagrama de estrutura de árvore. Tal diagrama
consiste em dois componentes básicos: Caixas, as quais correspondem aos tipos de registros, e Linhas, que correspondem
às ligações entre os tipos de registros. Como exemplo do modelo hierárquico, considere a Figura 2.2.
1 Por estrutura podemos compreender o tipo dos dados, os relacionamentos e as restrições que podem recair sobre os dados.
17
Introdução à Modelagem Conceitual Unidade I
• existência de restrições à cardinalidade dos links (de muitos para muitos (N:M) e de muitos para um (N:1));
Além disso, a replicação possui duas grandes desvantagens: pode causar inconsistência de dados, quando houver
atualização, e o desperdício de espaço é inevitável.
O surgimento do modelo de rede deu-se como uma extensão ao modelo hierárquico; dessa forma, foi eliminando o conceito
de hierarquia e permitindo que um mesmo registro estivesse envolvido em várias associações.
Os registros, no modelo em rede, são organizados em grafos onde aparece um único tipo de associação (set) que define
uma relação 1:N entre 2 tipos de registros: proprietário e membro. Nesse sentido, é possível construir um relacionamento
M:N entre A e D, dados dois relacionamentos 1:N entre os registros A e D e entre os registros C e D.
Com linguagem própria para definição e manipulação de dados, o gerenciador Data Base Task Group (DBTG) da CODASYL
(Committee on Data Systems and Languages) estabeleceu uma norma para esse modelo de banco de dados. Como os
dados tinham uma forma limitada de independência física, a única garantia era que o sistema deveria recuperar os dados
para as aplicações como se eles estivessem armazenados na maneira indicada nos esquemas.
Concorrência e segurança foram definidas, pelos geradores de relatórios da CODASYL, como dois aspectos chaves dos
sistemas gerenciadores de dados. Para cada um desses aspectos foram definidas sintaxes. O mecanismo de segurança
fornecia uma facilidade em que parte do banco de dados (ou área) pudesse ser bloqueada para prevenir acessos simultâneos,
quando necessário. A sintaxe da segurança permitia que uma senha fosse associada a cada objeto descrito no esquema.
Ao contrário do modelo hierárquico, o modelo em rede possibilita acesso a qualquer nó da rede sem passar pela raiz. O
CAIDMS da Computer Associates é o sistema comercial mais divulgado do modelo em rede. O diagrama para representar
os conceitos do modelo em redes consiste em dois componentes básicos: Caixas, que correspondem aos registros, e
Linhas, que correspondem às associações. A Figura 2.3 ilustra um exemplo de diagrama do modelo em rede.
R_Link
Cliente Conta
Pedro R231 Guará 61893 500,00
João R121 Brasília 51935 100,00
R_Link
18
Introdução à Modelagem Conceitual Unidade I
• necessidade de criação de registros artificiais para implementar relacionamentos muitos para muitos;
• alta complexidade das consultas, pois o programador é forçado a pensar em termos de links e como percorrê-
los para obter as informações necessárias (manipulação de dados navegacional).
O modelo relacional surgiu devido às necessidades de aumentar a independência de dados nos sistemas gerenciadores de
banco de dados; de prover um conjunto de funções apoiadas em álgebra relacional para armazenamento e recuperação de
dados, de permitir o processamento ad hoc1. Esse modelo, tendo por base a teoria dos conjuntos e a álgebra relacional,
foi resultado de um estudo teórico realizado por CODD[1]2.
Esse modelo foi o que revelou ser o mais flexível e adequado ao solucionar os vários problemas que se colocam no
nível da concepção e implementação da base de dados. Sua estrutura fundamental é a relação (tabela). Uma relação é
constituída por um ou mais atributos (campos) que traduzem o tipo de dados a armazenar. Tupla (registro) é o nome dado
a cada instância do esquema (linha).
O modelo relacional não tem caminhos pré-definidos para se fazer acesso aos dados como nos modelos que o precederam
e implementa estruturas de dados, organizadas em relações.
Algumas restrições devem ser impostas para que se trabalhe com essas tabelas e evitar aspectos indesejáveis como: repetição
Pós-Graduação a Distância
de informação, incapacidade de representar parte da informação e perda de informação. Essas restrições são: integridade
referencial, chaves e integridade de junções de relações. A Figura 2.4 traz exemplos de tabelas sob o modelo relacional.
Em meados de 1980, começaram a se tornar comercialmente viáveis os bancos de dados orientados a objeto. Seu
surgimento foi motivado em função dos limites de armazenamento e representação semântica impostas no modelo
relacional. Os sistemas de informações geográficas (SIG), os sistemas CAD e CAM, que são mais facilmente construídos
usando tipos complexos de dados, são alguns dos exemplos que podem ser citados.
19
Introdução à Modelagem Conceitual Unidade I
Uma característica das linguagens de programação orientadas a objetos é a habilidade para criar os tipos de dados
necessários. Contudo, esses sistemas necessitam guardar representações das estruturas de dados que utilizam no
armazenamento permanente.
O ODMG (Object Database Management Group) foi quem criou a estrutura padrão para os bancos de dados orientados a
objetos. Esse grupo é formado por representantes dos principais fabricantes desses bancos disponíveis comercialmente.
Os membros do grupo têm o compromisso de incorporar o padrão em seus produtos.
Modelo Orientado a Objetos é um termo usado para documentar o padrão que contém a descrição geral das facilidades
de um conjunto de linguagens de programação orientadas a objetos e a biblioteca de classes que pode formar a base para
o Sistema de Banco de Dados. Algumas das falhas perceptíveis do modelo relacional pareceram ter sido solucionadas
quando os bancos de dados orientados a objetos foram introduzidos e acreditava-se que tais bancos de dados ganhariam
grande parcela do mercado.
Acredita-se que nos dias atuais, enquanto os sistemas relacionais continuarão a sustentar os negócios tradicionais, onde
as estruturas de dados baseadas em relações são suficientes, os Bancos de Dados Orientados a Objetos serão usados
em aplicações especializadas.
O diagrama de classes UML serve geralmente como o esquema para o modelo de dados orientado a objetos. Observe o
exemplo da Figura 2.5. e compare as diferenças com o modelo anterior.
Os sistemas relacionais convencionais têm dificuldade de representar e manipular dados complexos, visando ser mais
representativos em semântica e construções de modelagens; com isso, a área de atuação dos sistemas Objeto-Relacional
tenta suprir essas dificuldades. A solução proposta é a adição de facilidades para manusear tais dados utilizando-se
das facilidades SQL (Structured Query Language) existentes. Para isso, foi necessário adicionar: extensões dos tipos
básicos no contexto SQL; representações para objetos complexos no contexto SQL; herança no contexto SQL e sistema
para produção de regras.
• nível interno: ou esquema interno, que descreve a estrutura de armazenamento físico do banco de dados;
utiliza um modelo de dados e descreve detalhadamente os dados armazenados e os caminhos de acesso ao
banco de dados;
• nível conceitual: ou esquema conceitual, que descreve a estrutura do banco de dados como um todo; é uma
descrição global do banco de dados, que não fornece detalhes do modo como os dados estão fisicamente
armazenados;
20
Introdução à Modelagem Conceitual Unidade I
• nível externo: ou esquema de visão, que descreve as visões do banco de dados para um grupo de usuários;
cada visão descreve as porções do banco de dados às quais um grupo de usuários terá acesso.
Segundo Oppel (2004), é possível definir a independência de dados como a capacidade de se alterar um esquema em
um nível em um banco de dados sem ter que alterar um nível superior. É possível classificar a independência de dados
em dois tipos:
• independência de dados lógica: é a capacidade de alterar o esquema conceitual sem ter que alterar o
esquema externo ou as aplicações do usuário;
• independência de dados física: é a capacidade de alterar o esquema interno sem ter que alterar o esquema
conceitual, o esquema externo ou as aplicações do usuário.
NÍVEL
EXTERNO Usuários Finais
Mapeamento
NÍVEL
Esquema Interno Conceitual
INTERNO
Externo
Cada camada e/ou função de um banco de dados necessita de um tipo de linguagem específica, conforme podemos ver.
A Linguagem de Definição de Dados ou Data Definition Language (DDL) é a linguagem utilizada pelo DBA e pelos
projetistas de banco de dados para definir seus esquemas. O SGBD, por sua vez, possui um compilador para processar
descrições em DDL e construir a descrição do esquema armazenado no catálogo.
21
Introdução à Modelagem Conceitual Unidade I
A Linguagem de Manipulação de Dados ou Data Manipulation Language (DML) é a linguagem pela qual os usuários
manipulam os dados em um SGBD. Manipulações comuns como recuperação, inserção, remoção e modificação de dados
são realizadas pela DML.
Em situações onde a separação entre os níveis conceitual e interno de um SGBD é bem clara, utiliza-se a Linguagem
de Definição de Armazenamento ou Storage Definition Language (SDL) para a especificação do esquema interno,
sendo que a especificação do esquema conceitual fica por conta da DDL.
Sistemas de Banco de Dados que utilizam a arquitetura três esquemas necessitam de uma linguagem para a definição
de visões, a Linguagem de Definição de Visões ou Vision Definition Language (VDL).
• Compilador DML: é o elemento que traduz os comandos DML em instruções de baixo nível, entendidos pelo
componente de execução de consultas. Também é responsável pela otimização de solicitações do usuário.
• Pré-compilador para comandos DML inseridos em programas de aplicação: são os elementos que
convertem comandos DML em chamadas de procedimentos normais da linguagem hospedeira. Também
interagem com o compilador DML de modo a gerar o código apropriado.
• Interpretador DDL: é o elemento que interpreta os comandos DDL e os registra no dicionário de dados.
• Componente de execução de consultas: é o elemento que executa instruções de baixo nível geradas pelo
compilador DML.
Sistemas de Banco de Dados
22
Introdução à Modelagem Conceitual Unidade I
Programas de
Pré-compilador de
Processador de
Componente
Banco de Dados
de Execução de
Consultas
Gerenciador de
Gerenciador de Gerenciador de
Memória
Buffer Transações
Gerenciador de
Arquivos
O componente Gerenciador de Memória é o responsável por traduzir os diversos comandos DML em comandos de baixo
nível de sistemas de arquivos, o que lhe confere especial importância uma vez que um dos principais objetivos de um
SGBD é simplificar e otimizar o acesso aos dados. Visto que esse componente é responsável por fazer a interface entre
o armazenamento de dados em um nível mais baixo e as consultas e programas de aplicações submetidos ao sistema, é
possível afirmar que o Gerenciador de Memória é um dos principais elementos de um SGBD.
• Gerenciamento de Autorizações e Integridade: são os elementos que testam o cumprimento das regras
de integridade e a permissão ao usuário no acesso ao dado.
• Administração de Buffer1: é o elemento responsável pela intermediação de dados do disco para a memória
principal e pela decisão de quais dados alocar em memória auxiliar.
23
Introdução à Modelagem Conceitual Unidade I
O Módulo Banco de Dados não se limita apenas a armazenar dados, uma vez que também contém definições e descrições
sobre a estrutura que forma o Banco de Dados (metadados). Os metadados, por sua vez, contêm definições da estrutura
de cada arquivo, o tipo e formato de armazenamento de cada item de dados e as restrições dos dados. Todas essas
definições ficam armazenadas no Catálogo de Dados (dicionário de dados) do Banco de Dados e são utilizadas pelo SGBD.
• Estatística de Dados: é o elemento que armazena informações estatísticas relativas aos dados contidos
no banco de dados. Essas informações são usadas pelo processador de consultas para seleção de meios
eficientes para execução de consultas.
Os mainframes eram utilizados pelas primeiras arquiteturas para executar o processamento principal e de todas as funções
do sistema, incluindo os programas aplicativos, programas de interface com o usuário, bem como a funcionalidade dos
SGBDs. Essa é a razão pela qual a maioria dos usuários fazia acesso aos sistemas via terminais que não possuíam poder
de processamento, mas, somente a capacidade de visualização. Apenas as informações a serem visualizadas e os controles
eram enviados do mainframe para os terminais de visualização e todos os processamentos eram feitos remotamente,
conectados a ele por redes de comunicação.
Muitos usuários trocaram seus terminais por Computadores Pessoais (PC) e estações de trabalho devido à queda dos
preços do hardware. No começo, os SGBDs usavam esses computadores da mesma maneira que usavam os terminais.
O SGBD era centralizado e toda sua funcionalidade, execução de programas aplicativos e processamento da interface
do usuário eram executados em apenas uma máquina.
Os SGBDs, gradualmente, começaram a explorar a disponibilidade do poder de processamento no lado do usuário, o que
levou à arquitetura cliente-servidor. Essa arquitetura foi desenvolvida para dividir ambientes de computação onde um
grande número de PCs, estações de trabalho, servidores de arquivos, impressoras, servidores de banco de dados e outros
equipamentos são conectados juntos por uma rede.
A idéia era definir servidores especializados, tais como servidor de arquivos, que mantém os arquivos de máquinas clientes,
ou servidores de impressão que podem estar conectados a várias impressoras; assim, quando se desejar imprimir algo,
todas as requisições de impressão são enviadas a esse servidor. As máquinas clientes disponibilizam para o usuário as
interfaces apropriadas para utilizar esses servidores, bem como o poder de processamento para executar aplicações locais.
A arquitetura cliente-servidor se tornou muito popular por causa da facilidade de implementação dada à clara separação
Sistemas de Banco de Dados
das funcionalidades e dos servidores; pelo servidor ser inteligentemente utilizado porque as tarefas mais simples são
delegadas às máquinas-clientes mais baratas e também porque o usuário pode executar uma interface gráfica que lhe é
familiar, ao invés de usar a interface do servidor.
Aos SGBDs comerciais, foi incorporada a arquitetura cliente-servidor e diferentes técnicas foram propostas para se
implementar essa arquitetura, sendo que a mais adotada pelos Sistemas Gerenciadores de Banco de Dados Relacionais
(SGBDRs) comerciais é a inclusão da funcionalidade de um SGBD centralizado no lado do servidor. Permanecem no
servidor de consulta ou servidor de transação as consultas e a funcionalidade transacional. É assim que um servidor
SQL é fornecido aos clientes.
24
Introdução à Modelagem Conceitual Unidade I
Os clientes têm que formular suas consultas SQL, prover a interface do usuário e as funções de interface usando uma
linguagem de programação. Podem também se referir a um dicionário de dados, que inclui informações sobre a distribuição
dos dados em vários servidores SQL, bem como sobre os módulos para a decomposição de uma consulta global em um
número de consultas locais que podem ser executadas em vários sítios.
O servidor SQL também é chamado de back-end machine e o cliente de front-end machine. Como SQL provê uma linguagem
padrão para o SGBDRs, esta criou o ponto de divisão lógica entre o cliente e o servidor.
Atualmente, existem várias tendências para arquitetura de Banco de Dados, nas mais diversas direções.
• Sistemas de Computador Pessoal: fazem seus processamentos sozinhos e, com isso, trabalham em sistema
stand-alone. No começo esse processamento era bastante limitado, porém, com a evolução do hardware,
tem-se hoje PCs com grande capacidade de processamento. Utilizam o padrão Xbase e, em se tratando de
SGBDs, funcionam como hospedeiros e terminais. Desta forma, possuem um único aplicativo a ser executado
na máquina e sua principal vantagem é a simplicidade.
• Banco de Dados Cliente-Servidor: nessa arquitetura, o cliente (front_end) executa as tarefas do aplicativo
fornecendo a interface do usuário (tela e processamento de entrada e saída). O servidor (back_end)
executa as consultas no DBMS e retorna os resultados ao cliente. Embora sendo uma arquitetura bastante
popular, são necessárias soluções sofisticadas de software que possibilitem: o tratamento de transações,
as confirmações de transações (commits), desfazer transações (rollbacks), linguagens de consultas (stored
procedures) e gatilhos (triggers). A principal vantagem dessa arquitetura é a divisão do processamento entre
dois sistemas, o que reduz o tráfego de dados na rede. (Ver Figura 2.8)
• Banco de Dados Distribuídos (N camadas): como se pode observar na Figura 2.9, a informação, nessa
arquitetura, está distribuída em diversos servidores. Cada servidor atua como no sistema cliente-servidor,
porém as consultas oriundas dos aplicativos são feitas para qualquer servidor indistintamente. Caso a
informação solicitada seja mantida por outro servidor ou servidores, o sistema encarrega-se de obter a
informação necessária, de maneira transparente para o aplicativo, que passa a atuar consultando a rede,
independente de conhecer seus servidores. As bases de dados corporativas, em que o volume de informação
é muito grande e, por isso, deve ser distribuído em diversos servidores são exemplos típicos. Porém, não é
dependente de aspectos lógicos de carga de acesso aos dados, ou de base de dados fracamente acopladas, em
que uma informação solicitada vai sendo coletada numa propagação da consulta numa cadeia de servidores.
A existência de diversos programas aplicativos consultando a rede para acessar os dados necessários é a
característica básica, porém, sem o conhecimento explícito de quais servidores dispõem desses dados.
Pós-Graduação a Distância
25
Introdução à Modelagem Conceitual Unidade I
• Quanto aos usuários: um SGBD pode ser monousuário, comumente utilizado em computadores pessoais ou
Sistemas de Banco de Dados
• Quanto à localização: um SGBD pode ser localizado ou distribuído; se ele for localizado, então todos os
dados estarão em uma só máquina (ou em um único disco); se distribuído, os dados estarão distribuídos por
diversas máquinas (ou diversos discos).
• Quanto ao ambiente: ambiente homogêneo é o ambiente composto por um único SGBD e um ambiente
heterogêneo é o ambiente composto por diferentes SGBDs.
26
Introdução à Modelagem Conceitual Unidade I
• dBASE: é um aplicativo lançado pela Ashton-Tate e posteriormente adquirido pela Borland. Teve versões
para DOS e Windows, trabalhava com gerenciamento de arquivos planos baseados em listas invertidas e
possuía uma linguagem de programação própria para desenvolvimento de aplicações. A partir da versão 7, os
direitos foram vendidos pela Borland.
• Paradox: teve versões para DOS e hoje possui apenas versões para Windows. Possui ambiente integrado de
desenvolvimento para criação de aplicativos e seus direitos de produção foram vendidos para a Corel.
• DataFlex: teve versões para DOS e Windows e é popular para ambiente Unix. Hoje é comercializado com o
nome de Visual Data Flex e possui ambiente integrado para o desenvolvimento de aplicações.
• Access: é um aplicativo que, por possuir ambiente integrado, permite a criação e gerenciamento do banco
de dados, desenvolvimento de aplicações e geração de relatórios. Sua linguagem de programação deriva do
Visual Basic. Para microcomputadores do ambiente Windows é padrão em banco de dados.
• Interbase: teve uma versão liberada como Open Source e foi incluído, pela Borland, nas suas ferramentas de
desenvolvimento (Delphi, C++Builder, JBuider).
• MS-SQL Server: as versões atuais são independentes e operam exclusivamente sobre Windows. Foi
produzido pela Microsoft. Inicialmente era uma versão especial do Sybase.
• Sybase SQL Anywhere: as aplicações para esse banco de dados são desenvolvidas com o PowerBuilder. No
mercado, seu concorrente corporativo é o Oracle.
• MySQL: além de gratuito, possui versões para Windows, Solaris, Unix, FreeBSD, Linux. Usado principalmente
para desenvolvimento WEB como servidor de dados para comércio eletrônico.
• PostgreSQL: além de ser gratuito, tem boa aceitação. Foi concebido para rodar em Linux e possui versões
para Windows. É, principalmente, usado para comércio eletrônico, juntamente com a linguagem PHP.
• BD2: aplicativo produzido pela IBM, nasceu nos ambientes de grande porte, sendo posteriormente portado
para plataformas mais simples (microcomputadores).
• Firebird: aplicativo nascido de uma iniciativa da Borland em abrir o código do InterBase 6. Este sistema é
open source e esbanja versatilidade e robustez. Possui recursos de trigger, store procedures e transações
concorrentes.
27
Introdução à Modelagem Conceitual Unidade I
É um modelo de dados conceitual de alto nível, cujos conceitos foram projetados para estar o mais próximo possível da
visão que o usuário tem dos dados, não se preocupando em representar como esses dados estarão realmente armazenados.
Baseia-se na percepção de um mundo real que consiste em uma coleção de objetos básicos, denominados entidades, e
de relações entre esses objetos.
O MER é utilizado principalmente durante o processo de projeto de banco de dados e é, atualmente, a técnica mais
difundida, chegando a confundir-se com a própria modelagem de dados.
A Figura 3.1 faz uma descrição simplificada do processo de projeto de um banco de dados.
• Simplicidade: possui uma riqueza de conceitos e com isso se torna uma poderosa ferramenta para a
descrição da realidade. Não é um modelo muito simples, especialmente no que diz respeito aos conceitos de
cardinalidade, cobertura de generalização e identificação. Uma solução é produzir diagramas ER em diferentes
níveis de detalhe.
Sistemas de Banco de Dados
• Minimalidade: nenhum conceito do modelo pode ser descrito em termos dos demais, com exceção dos
atributos compostos. O fato de a mesma realidade poder ser modelada de diferentes maneiras não invalida a
minimalidade do modelo.
• Formalidade: possui o necessário grau de formalidade, uma vez que cada um de seus conceitos possui uma
interpretação única, precisa e bem-definida.
• Representação gráfica: todos os seus conceitos possuem um símbolo gráfico associado, por isso, é um
modelo graficamente completo. Os diagramas ER são fáceis de serem entendidos pelos usuários.
28
Introdução à Modelagem Conceitual Unidade I
2. Uma aplicação
A Figura 3.1 descreve uma base de dados COMPANHIA, que será utilizada para ilustrar o processo de projeto de base
de dados. São listados os requisitos da base de dados e criado o seu esquema conceitual passo a passo ao mesmo tempo
em que são introduzidos os conceitos de modelagem usando o MER.
A base de dados COMPANHIA armazena os dados dos empregados, departamentos e projetos. Supõe-se que após a
Obtenção e Análise dos Requisitos, os projetistas da base de dados produziram a seguinte descrição do minimundo –
parte da companhia a ser representada na base de dados.
• Um departamento controla inúmeros projetos, sendo que cada um tem um nome, um número e uma localização.
• Do empregado armazena-se o nome, número do seguro social, endereço, salário, sexo e a data de nascimento.
Todo empregado é associado a um departamento, mas pode trabalhar em diversos projetos, que não são
necessariamente controlados pelo mesmo departamento. Armazena-se, também, o número de horas que o
empregado trabalha em cada projeto. Mantém-se, ainda, a indicação do supervisor direto de cada projeto.
• Os dependentes de cada empregado são armazenados com o propósito de garantir os benefícios do seguro.
Para cada dependente será armazenado o nome, sexo, data de nascimento e o relacionamento com o
empregado.
Mini-Mundo
Comum a todos os tipos de SGBD
Projeto Conceitual
Projeto Físico
Pós-Graduação a Distância
Esquema Interno
Banco de Dados
29
Introdução à Modelagem Conceitual Unidade I
3. Entidades e Atributos
O objeto básico tratado pelo modelo ER é a entidade, que pode ser definida como um objeto do mundo real, concreto ou
abstrato e que possui existência independente.
Cada entidade possui um conjunto particular de propriedades que a descreve, denominado atributos. Para cada atributo
existe um conjunto de valores permitidos, que é chamado de domínio desse atributo. Um atributo pode ser dividido em
diversas partes menores com significado independente entre si, recebendo o nome de atributo composto. Um atributo
que não pode ser subdividido é chamado de atributo simples ou atômico.
O atributo que pode assumir apenas um determinado valor em uma determinada instância é denominado atributo
simplesmente valorado, enquanto que um atributo que pode assumir diversos valores em uma mesma instância é denominado
multivalorado. Um atributo que é gerado a partir de outro é chamado de atributo derivado.
4. Tipos Entidade, Conjunto de Valores, Atributo Chave
Um banco de dados costuma conter grupos de entidades que são similares, possuindo os mesmos atributos, porém, cada
entidade conta com seus próprios valores para cada atributo. Esse conjunto de entidades similares forma tipo entidade.
Cada tipo entidade é identificado por seu nome e pelo conjunto de atributos que definem suas propriedades. A descrição
do tipo entidade é chamada de esquema do tipo entidade, onde são especificados o nome do tipo entidade, o nome
de cada um de seus atributos e qualquer restrição que incida sobre as entidades.
5. Relacionamentos
5.1. Tipos de Relacionamento
Um tipo relacionamento R entre n entidades E1, E2, ..., En é um conjunto de associações possíveis entre entidades desse
tipo. Em outras palavras, cada instância de relacionamento r1 em R é uma associação de entidades. Isso significa que
essas entidades estão relacionadas de alguma forma no minimundo.
A Figura 3.2 mostra um exemplo entre dois tipos entidade (empregado e departamento) e o relacionamento entre eles
(trabalha para). Repare que para cada relacionamento participa apenas uma entidade de cada tipo entidade, porém, uma
entidade pode participar de mais de um relacionamento.
E6 R6
30
Introdução à Modelagem Conceitual Unidade I
O grau de um tipo relacionamento é o número de tipos entidade que participam do tipo relacionamento. No exemplo
da Figura 3.2, temos um relacionamento binário. O grau de um relacionamento é ilimitado, porém, a partir do grau 3, a
compreensão e a dificuldade de se desenvolver a relação corretamente se tornam extremamente complexas.
Um exemplo de um tipo de relacionamento ternário é Fornece para, ilustrado na Figura 3.3. Cada instância de
relacionamento R1 associa três entidades – um fornecedor F, uma peça E e um projeto P – onde o fornecedor F fornece
a peça E para o projeto P. Podem existir tipos de relacionamento de qualquer grau, porém é mais freqüente encontrar o
tipo de relacionamento de grau dois.
Algumas vezes é conveniente pensar em um relacionamento como um atributo. Considere o exemplo da Figura 3.2. Podemos
pensar departamento como sendo um atributo da entidade empregado, ou empregado, como um atributo multivalorado
da entidade departamento. Se uma entidade não possuir existência muito bem definida, talvez seja mais interessante
para a coesão do modelo lógico que ela seja representada como um atributo.
Peças
E1
E2
Fornecer para
E3
R1 Projeto
E4
R2
E5
P1
E6 R3
P2
R4
R5 P3
Fornecedor
R6
F1
F2
Cada tipo entidade que participa de um tipo relacionamento desempenha um papel particular no relacionamento. O nome do
papel representa o papel que uma entidade de um tipo entidade participante desempenha no relacionamento. No exemplo
Pós-Graduação a Distância
da Figura 3.2, nós temos o papel empregado ou trabalhador para o tipo entidade EMPREGADO e o papel departamento
ou empregador para a entidade DEPARTAMENTO.
Nomes de papéis não são necessariamente importantes quando todas as entidades participantes desempenham papéis
diferentes. Algumas vezes, o papel torna-se essencial para distinguir o significado de cada participação. Isso é muito
comum em “relacionamentos recursivos”.
Um relacionamento recursivo é um relacionamento entre entidades do mesmo tipo entidade, conforme ilustrado na Figura
3.4.
31
Introdução à Modelagem Conceitual Unidade I
Na Figura 3.4, temos um relacionamento entre o tipo entidade EMPREGADO, onde um empregado pode supervisionar
outro empregado e um empregado pode ser supervisionado por outro empregado.
E4 R4
E5 R5
E6 R6
Supervisiona
Supervisionando
Em alguns casos, alguns tipos entidade podem não ter um atributo chave por si só. Isso implica que não poderemos distinguir
algumas entidades porque as combinações dos valores de seus atributos podem ser idênticas. Esses tipos entidade são
chamados entidades fracas. As entidades desse tipo precisam estar relacionadas com uma entidade pertencente ao
tipo entidade proprietária. Esse relacionamento é chamado de relacionamento identificador.
Na Figura 3.5, o tipo entidade DEPENDENTE é uma entidade fraca uma vez que não possui um método de identificar
uma entidade única. O EMPREGADO não é uma entidade fraca uma vez que possui um atributo para identificação
(atributo chave).
O número do CPF de um empregado pode identificar um único empregado, porém um dependente de 5 anos de idade não
possui necessariamente um documento como esse. Dessa forma, essa entidade é um tipo entidade fraca.
Um tipo entidade fraca possui uma chave parcial que, juntamente com a chave primária da entidade proprietária,
forma uma chave primária composta.
No exemplo da Figura 3.5 a chave primária do EMPREGADO pode ser o CPF. A chave parcial do DEPENDENTE
pode ser o seu nome, pois dois irmãos não podem ter o mesmo nome. Desse modo, a chave primária desta entidade
fica sendo o CPF do pai ou da mãe mais o nome do dependente.
32
Introdução à Modelagem Conceitual Unidade I
Os tipos de relacionamento também podem ter atributos da mesma maneira que os tipos de entidades. Exemplificando,
tomemos a situação representada pela Figura 3.6 e acrescentemos a necessidade de representar a data em que um
EMPREGADO começou a gerenciar um DEPARTAMENTO por meio de um atributo Data_Início para o tipo de
relacionamento GERÊNCIA.
Empregado
E1
Gerência Departamento
E2
R1 D1
E3
R2 D2
E4
E5 R3 D3
E6
Nesse caso, é possível perceber que atributos de tipos de relacionamento 1:1 ou 1:N podem ser incluídos como atributos
de um dos tipos de entidades participantes. Assim, o atributo Data_Início para o tipo de relacionamento GERÊNCIA
pode ser um atributo tanto de EMPREGADO quanto de DEPARTAMENTO embora, conceitualmente, ele pertença
ao relacionamento GERÊNCIA. Isso ocorre porque GERÊNCIA é um relacionamento 1:1, uma vez que toda entidade
DEPARTAMENTO ou EMPREGADO participam em apenas uma instância de relacionamento e, dessa forma, o valor do
atributo Data_Início pode ser representado em qualquer uma das entidades participantes.
No caso de um tipo de relacionamento 1:N, um atributo de relacionamento pode somente ser colocado no tipo de
entidade que está do lado N do relacionamento. Isso pode ser visto na Figura 3.2, pois se o relacionamento TRABALHA-
PARA tiver um atributo Data_Início, indicando quando um empregado começou a trabalhar para um DEPARTAMENTO,
esse atributo pode ser colocado como atributo de EMPREGADO. Isso ocorre porque o relacionamento é 1:N de modo
que cada entidade EMPREGADO participa apenas uma única vez em uma instância de TRABALHA-PARA.
Uma vez que o valor de um atributo é determinado pela combinação das entidades participantes em uma instância de
relacionamento, e não apenas por uma das entidades, então o atributo deve ser especificado como um atributo de
relacionamento. Esse é o caso de atributos de tipos de relacionamentos M:N, porque as entidades dos tipos de entidades
participantes podem participar em inúmeras instâncias de relacionamento.
Exemplificando, tomemos a situação descrita na Figura 3.2 e acrescentemos a necessidade de incluir o atributo Horas_
Trabalhadas do relacionamento M:N TRABALHA-PARA. O número de horas que um empregado trabalha em um projeto
é determinado pela combinação empregado-projeto e não separadamente.
Pós-Graduação a Distância
Os conceitos do modelo Entidade-Relacionamento, discutidos anteriormente, são suficientes para representar logicamente
a maioria das aplicações de banco de dados. Porém, com o surgimento de novas aplicações, surgiu também a necessidade
de novas semânticas para a modelagem de informações mais complexas.
O modelo Entidade-Relacionamento Estendido (ERE) visa fornecer esta semântica para permitir a representação
de informações complexas. É importante frisar que, embora o modelo ERE trate classes e subclasses, ele não possui a
mesma semântica de um modelo orientado a objetos.
33
Introdução à Modelagem Conceitual Unidade I
O modelo ERE engloba todos os conceitos do modelo E-R mais os conceitos de subclasse, superclasse, generalização,
especialização e o de herança de atributos.
O primeiro conceito do modelo ERE, que será abordado, é o de subclasse de um tipo entidade.
Como visto anteriormente, um tipo entidade é utilizado para representar um conjunto de entidades do mesmo tipo. Em
muitos casos, um tipo entidade possui diversos subgrupos adicionais de entidades que são significativas e precisam ser
representadas explicitamente, devido ao seu significado, à aplicação de banco de dados. Considere o seguinte exemplo:
Para um banco de dados de uma empresa temos o tipo entidade empregado, o qual possui as seguintes características:
nome, RG, CPF, número funcional, endereço completo (rua, número, complemento, CEP, bairro, cidade), sexo, data de
nascimento e telefone (ddd e número); caso o(a) funcionário(a) seja um(a) engenheiro(a), então deseja-se armazenar
as seguintes informações: número do CREA e especialidade (Civil, Mecânico, Eletrônico); caso o(a) funcionário(a) seja
um(a) secretário(a), então se deseja armazenar as seguinte informações: qualificação (bi ou trilíngue) e os idiomas em
que possui fluência verbal e escrita.
Se as informações número do CREA, especialidade, tipo e idiomas forem representados diretamente no tipo entidade
empregado estaremos representando informações de um conjunto limitado de entidades empregado para os todos os
funcionários da empresa. Nesse caso, podemos criar duas subclasses do tipo entidade empregado: engenheiro e secretária,
as quais irão conter as informações acima citadas. Além disto, engenheiro e secretária podem ter relacionamentos
específicos.
Uma entidade não pode existir meramente como componente de uma subclasse. Antes de ser componente de uma
subclasse, uma entidade deve ser componente de uma superclasse. Isto leva ao conceito de herança de atributos; ou
seja, a subclasse herda todos os atributos da superclasse. Isso porque a entidade de subclasse representa as mesmas
características de uma mesma entidade da superclasse. Uma subclasse pode herdar atributos de superclasses diferentes.
Uma representação diagramática do exemplo mencionado é ilustrada na Figura 3.7.
Nome
RG Endereço
Função
d
No Registro Qualificação
Especialização
Engenheiro Engenheiro Idiomas
Sistemas de Banco de Dados
6.3.2. Especialização
Especialização é o processo de definição de um conjunto de classes de um tipo entidade; esse tipo entidade é chamado
de superclasse da especialização. O conjunto de subclasses é formado com base em alguma característica que distinga
as entidades entre si.
No exemplo da Figura 3.7, temos uma especialização, que podemos chamar de função. Veja agora no exemplo da Figura
3.8, temos a entidade empregado e duas especializações.
34
Introdução à Modelagem Conceitual Unidade I
Como visto anteriormente, uma subclasse pode ter relacionamentos específicos com outras entidades ou com a própria
entidade, que é a sua superclasse. Veja o exemplo da Figura 3.9.
N Empregado
Projeto
É liderado
É desenvolvido por Função
N S d
Lidera
N
Engenheiro Secretária
Participa
6.3.3. Generalização
A generalização pode ser pensada como um processo de abstração reverso ao da especialização, no qual são suprimidas
as diferenças entre diversos tipos entidades, identificando suas características comuns e generalizando essas entidades
em uma superclasse.
Pós-Graduação a Distância
35
Introdução à Modelagem Conceitual Unidade I
É importante destacar que existe diferença semântica entre a especialização e a generalização. Na especialização, podemos
notar que a ligação entre a superclasse e as subclasses é feita por meio de um traço simples, indicando participação
parcial por parte da superclasse. Analisando o exemplo da Figura 3.9, é observado que um empregado não é obrigado a
ser um engenheiro ou uma secretária. Na generalização, podemos notar que a ligação entre a superclasse e as subclasses
é feita por intermédio de um traço duplo, indicando participação total por parte da superclasse. Analisando o exemplo
da Figura 3.10, é observado que um empregado é obrigado a ser um engenheiro ou uma secretária.
A letra d dentro do círculo que especifica uma especialização ou uma generalização significa disjunção. Uma disjunção
em uma especialização ou generalização indica que uma entidade do tipo entidade que representa a superclasse pode
assumir apenas um papel dentro dela. Analisando o exemplo da Figura 3.11 temos duas especializações para a superclasse
Empregado, as quais são restringidas por meio de uma disjunção. Nesse caso, um empregado pode ser um engenheiro ou
uma secretária e ele pode ser horista ou mensalista.
Além da disjunção, podemos ter um overlap, representado pela letra o. No caso do “overlap”, uma entidade de uma
Sistemas de Banco de Dados
superclasse pode ser membro de mais que uma subclasse em uma especialização ou generalização. Analise a generalização
no exemplo da Figura 3.12. Suponha que uma peça fabricada em uma tornearia pode ser manufaturada ou torneada, ou
ainda, pode ter sido manufaturada e torneada.
36
Introdução à Modelagem Conceitual Unidade I
Uma subclasse pode ser definida por meio de um “lattice”, ou múltipla herança, ou seja, ela pode ter diversas superclasses,
herdando características de todas. Tomemos como base a situação de que uma construtora possui diversos funcionários,
que podem ser engenheiros ou secretárias. Um funcionário pode também ser assalariado ou horista. Todo gerente de
departamento da construtora deve ser um engenheiro e assalariado.
Nesse caso, então, um gerente será um funcionário que, além de possuir as características próprias de Gerente, herdará
as características de Engenheiro e de Mensalista.
7. Diagrama Entidade-Relacionamento
Pós-Graduação a Distância
O Diagrama Entidade-Relacionamento (DER) é composto por um conjunto de objetos gráficos que visa representar
todos os objetos do modelo Entidade Relacionamento, tais como entidades, atributos, atributos chaves, relacionamentos,
restrições estruturais etc.
O diagrama ER oferece uma visão lógica do banco de dados, fornecendo um conceito mais generalizado de como estão
estruturados os dados de um sistema.
37
Introdução à Modelagem Conceitual Unidade I
Várias formas de notação de um MER foram desenvolvidas. Entre elas podemos destacar:
• ER – Peter Chen
Apesar de todas se destinarem, em suma, à mesma finalidade, a notação mais utilizada ainda é a ER, proposta por Peter
Chen.
Os elementos gráficos que compõem o Diagrama Entidade-Relacionamento (DER), proposto por Chen (1976), são:
• Retângulos: conjuntos de entidades.
• Linhas: unem atributos aos conjuntos de entidades e esses aos conjuntos de relacionamentos.
• Elipses duplas: atributos multivalorados. Linhas duplas indicam participação total de uma entidade em um
conjunto de relacionamentos.
• Os atributos multivalorados são denotados em elipses com linhas duplas (atributo Localização de
DEPARTAMENTO).
• Os atributos derivados são representados em elipses com linhas tracejadas (atributo Número De Empregados
de DEPARTAMENTO).
38
Introdução à Modelagem Conceitual Unidade I
• Os tipos de entidades-fracas são distinguidos por retângulos com linhas duplas e os relacionamentos de
identificação, por losangos com linhas duplas (tipo de entidade-fraca DEPENDENTE e tipo de relacionamento
de identificação DEPENDENTE-DE).
Figura 3.14. Objetos que Compõem o Diagrama ER
Na Figura 3.15 é apresentado o mesmo esquema da Figura 3.16, porém com a utilização da notação alternativa para
ilustrar as restrições estruturais de tipos de relacionamentos.
39
Introdução à Modelagem Conceitual Unidade I
40
Unidade II
Sistemas de Banco de Dados:
conceitos e arquiteturas
1. Introdução
Segundo Silberschatz (2006), Modelo de Dados é uma coleção de ferramentas conceituais para descrever dados, relações
de dados, semântica de dados e restrições de consistência, constituindo-se em uma maneira de descrever o projeto de
um banco de dados nos seus vários níveis de abstração.
As bases do modelo relacional foram lançadas por Edgar Codd, nos anos 1970, e começou a ser realmente utilizado
nas empresas a partir de 1987, por meio do SGBDs, tendo como finalidade representar os dados como uma coleção de
relações, onde cada relação é representada por uma tabela. O conceito principal vem da teoria dos conjuntos (álgebra
relacional) atrelado à idéia de que não é relevante ao usuário saber onde os dados estão nem como os dados estão.
Quando uma relação é pensada como uma tabela de valores, cada linha nessa tabela representa uma coleção de dados
relacionados. Esses valores podem ser interpretados como fatos descrevendo uma instância de uma entidade ou de um
relacionamento. O nome da tabela e das colunas são utilizados para facilitar a interpretação dos valores armazenados
em cada uma de suas linhas. Todos os valores em uma coluna são necessariamente do mesmo tipo.
41
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Segundo Takai (2005), quando uma relação é vista como uma tabela de valores, cada linha representa uma coleção de
valores relacionados. Esses valores podem ser interpretados como um fato que descreve uma entidade ou uma instância
de relacionamento. O nome da tabela e os nomes das colunas são usados para ajudar a interpretar o significado dos
valores em cada linha da tabela.
Exemplificando, na Figura 4.1, a primeira tabela é chamada ESTUDANTE porque cada linha representa o fato sobre uma
particular entidade estudante. Os nomes das colunas – Nome, Número, Classe, Departamento – especificam como
interpretar os valores em cada linha, baseando-se nas colunas em que cada um se encontra. Todos os valores de uma
coluna são, normalmente, do mesmo tipo.
Tomemos como exemplo de uma relação esquema R de grau 4, que descreve estudantes universitários:
Nessa relação-esquema, ESTUDANTE é o nome da relação esquema, que tem 4 atributos. Podemos especificar alguns
domínios para cada atributo da relação ESTUDANTE:
dom(Nome)=Nomes
dom(Matrícula)=Número da matrícula dos alunos
dom(Classe)=Número de identificação das turmas
dom(Departamento)=Código relativo ao departamento a que os cursos estão vinculados
Sistemas de Banco de Dados
Uma relação r1 da relação esquema R(A1, A2, ..., An), também denotada por r(R), é um conjunto de tuplas r={ t1, t2, ...,
tm}. Cada tupla t é uma lista ordenada de n valores t=<v1, v2, ..., vn>, onde cada valor vi, 1 ≤ i ≤ n, é um elemento
do dom(Ai) ou um valor especial null. São utilizados, com freqüência, os termos intenção da relação para o esquema R e
extensão da relação para a instância r(R).
Uma relação é definida como um conjunto de tuplas. Pela definição, todos os elementos de um conjunto são distintos.
Assim, todas as tuplas de uma relação também são distintas. Isso significa que nenhuma tupla pode ter a mesma
1 Também chamada de instância de relação
42
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
combinação de valores para todos os seus atributos. Normalmente, existem subconjuntos de atributos de uma relação
esquema R com a propriedade de que nenhuma tupla de uma relação r de R tenha a mesma combinação de valores para
esses atributos. Suponha que esse subconjunto seja denotado por SC; então, para quaisquer tuplas t1 e t2 em r de R,
deve valer a regra:
t1 [SC] ≠ t2 [SC]
Assim, SC é chamada Super-Chave da relação esquema R. Toda relação tem ao menos uma Super-Chave, que é o
conjunto de todos os seus atributos. Uma chave C, de uma relação esquema R, é uma Super-Chave de R com a propriedade
adicional de não se poder remover qualquer atributo A de C e continuar a ser Super-Chave de R. Assim, uma chave é
uma Super-Chave mínima; uma super-chave da qual não se pode remover qualquer atributo.
Por exemplo, considere a relação ESTUDANTE da Figura 4.1. O conjunto de atributos {Número} é uma Super-Chave
de ESTUDANTE, porque se sabe que nenhum estudante irá ter o mesmo número de matrícula, e também é uma chave,
pois não se pode remover nenhum atributo. Qualquer conjunto de atributos que inclua Número - por exemplo, {Número,
Nome, Anos} - será uma Super-Chave.
No entanto, o conjunto {Número, Nome, Departamento} não é uma chave de ESTUDANTE porque, removendo Nome
ou Anos, ou ambos, o conjunto resultante será ainda uma Super-Chave.
A chave deve ser determinada pelo significado dos atributos na relação esquema e deve ser invariante ao tempo. Por
exemplo, o atributo Nome da relação ESTUDANTE não pode ser indicado como chave, uma vez que nada garante a não
ocorrência de homônimos. Em geral, uma relação esquema pode ter mais que uma chave. Nestes casos, cada chave é
chamada chave-candidata. Por exemplo, o esquema da relação ESTUDANTE poderia ter um atributo adicional Código,
para indicar o código interno de estudantes na escola. Assim, o esquema teria duas chaves candidatas: Número e
Código. É comum designar uma das chaves-candidatas como a Chave-Primária da relação. A indicação no modelo de
qual Chave-Candidata é a Chave-Primária é efetuada sublinhando-se os atributos que formam a Chave-Candidata
escolhida. Quando uma relação esquema tem muitas Chaves-Candidatas, a escolha da Chave-Primária é arbitrária.
No entanto, é sempre melhor escolher a Chave-Primária com o menor número de atributos.
Dicas
• O sinônimo é um nome alternativo para a entidade. São muito utilizados quando dois grupos de usuários
têm diferentes nomes para o mesmo objeto significante.
Em geral, os tipos relacionamentos sofrem certas restrições que limitam as possíveis combinações das entidades
participantes. Essas restrições são derivadas de restrições impostas pelo estado dessas entidades no minimundo.
Pós-Graduação a Distância
A Figura 3.6 representa a situação de que um empregado pode gerenciar apenas um departamento, enquanto que um
departamento pode ser gerenciado por apenas um empregado.
Esse tipo de restrição é chamado de cardinalidade. A cardinalidade indica o número de relacionamentos dos quais uma
entidade pode participar.
43
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
• um para um (1:1);
No exemplo da Figura 3.6, a cardinalidade é 1:1, pois cada entidade EMPREGADO pode gerenciar apenas um
DEPARTAMENTO e um DEPARTAMENTO pode ser gerenciado por apenas um EMPREGADO.
No exemplo da figura 3.3, no relacionamento FORNECEDOR - Fornece Para - PROJETO, o relacionamento é M:N, pois
um fornecedor pode fornecer várias peças para vários projetos.
Uma restrição muito importante é a participação. A participação define a existência de uma entidade por intermédio do
relacionamento, podendo ser parcial ou total.
No exemplo da Figura 3.6, a participação do empregado é parcial, pois nem todo EMPREGADO gerencia um
DEPARTAMENTO, porém a participação do departamento nesse relacionamento é total, pois todo DEPARTAMENTO
necessita ser gerenciado por um EMPREGADO. Dessa forma, todas as entidades do tipo entidade DEPARTAMENTO
precisam participar do relacionamento, mas nem todas as entidade do tipo entidade EMPREGADO precisam
participar do relacionamento.
Na Figura 3.2, ambas as participações são totais, pois todo EMPREGADO precisa trabalhar em um DEPARTAMENTO
e todo DEPARTAMENTO tem que ter EMPREGADOS trabalhando nele. Essas restrições são chamadas de restrições
estruturais.
As chaves-candidatas de cada relação esquema são especificadas pelas restrições de chave. Essas chaves-candidatas
possuem valores que devem ser únicos para todas as tuplas de quaisquer instâncias da relação esquema.
Além da restrição de chave, existem dois outros tipos de restrições no modelo relacional: a integridade de entidade e a
integridade referencial.
Na restrição de integridade de entidade nenhum valor da chave-primária pode ser nulo, pois o valor de uma chave-
primária é utilizado para identificar tuplas em uma relação. Por exemplo, se duas ou mais tuplas tiverem o valor null para
a chave primária, não haverá como diferenciar uma tupla da outra.
A restrição de integridade referencial é usada para manter a consistência entre tuplas de duas relações. Informalmente,
a restrição de integridade referencial estabelece que uma tupla de uma relação que se refere à outra relação deve se
referir a uma tupla existente naquela relação.
Sistemas de Banco de Dados
Por exemplo, na Figura 4.2, o atributo NDEP de EMPREGADO indica o número do departamento que cada empregado
trabalha. Assim, todos os valores de NDEP nas tuplas da relação EMPREGADO devem pertencer ao conjunto de valores
do atributo DNÚMERO da relação DEPARTAMENTO. Para definir formalmente a restrição de integridade referencial,
há a necessidade de, antes, definir o conceito de chave-estrangeira (CE). As condições para uma chave-estrangeira,
descritas abaixo, especificam uma restrição de integridade referencial entre duas relações esquemas R1 e R2.
44
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Um conjunto de atributos CE na relação esquema R1 será uma chave-estrangeira de R1 se ele satisfizer as seguintes regras:
• os atributos em CE têm o mesmo domínio dos atributos da chave-primária CP da outra relação esquema R2.
Diz-se que os atributos CE referenciam ou referem-se à relação R2;
• uma CE na tupla t1 ou tem um valor que ocorre como CP de alguma tupla t2 de R2 ou tem o valor null.
No primeiro caso, tem-se t1 [CE] = t2 [CP], e diz-se que t1 referencia ou refere-se à tupla t2. Uma base de dados tem
muitas relações e possui muitas restrições de integridade referencial. O projetista deve ter um claro entendimento do
significado ou papel que os atributos desempenham nas diversas relações esquemas da base de dados para que essas
restrições sejam especificadas. Normalmente, as restrições de integridade referencial são derivadas dos relacionamentos
entre entidades representadas pelas relações esquemas. Por exemplo, considere a base de dados mostrada na 4.2.
Na relação EMPREGADO, o atributo NDEP refere-se ao departamento em que cada empregado trabalha; desse modo,
designa-se NDEP como a chave-estrangeira de EMPREGADO, referenciando a relação DEPARTAMENTO. Isso significa que
um valor de NDEP em alguma tupla t1 da relação EMPREGADO deve ter um valor correspondente para a chave-primária
da relação DEPARTAMENTO – o atributo DNÚMERO – em alguma tupla t2 da relação DEPARTAMENTO ou o valor de
NDEP pode ser null se o empregado não pertencer a nenhum departamento. Na Figura 4.2, a tupla do empregado “John
Smith” referencia a tupla departamento de “Pesquisa”, indicando que “John Smith” trabalha para esse departamento.
Note que uma chave-estrangeira pode referenciar sua própria relação.
Por exemplo, o atributo NSSSUPER em EMPREGADO refere-se ao supervisor de um empregado, isto é, outro empregado.
Pode-se, diagramaticamente, mostrar as restrições de integridade desenhando-se arcos direcionados, partindo da chave-
estrangeira para a relação referenciada.
A Figura 4.4 ilustra o esquema apresentado na Figura 4.3, com as restrições de integridade referencial anotadas dessa
maneira.
Caso o projetista tenha interesse em manter as restrições válidas para toda a base de dados, essas restrições de
integridade deveriam ser especificadas no esquema da base de dados relacional.
No sistema relacional, a linguagem de definição de dados (DDL) deveria fornecer recursos para especificar os vários tipos
de restrições tal que o SGDB possa verificá-las automaticamente. Muitos sistemas de gerenciamento de base de dados
relacionais permitem restrições de chave e de integridade de entidade, mas alguns não permitem a integridade referencial.
45
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
DEPARTAMENTO
DNOME DNÚMERO NSSGER DATINICGER
Pesquisa 5 333445555 22-MAI-78
Administrativo 4 9876543231 01-JAN-85
Gerencial 1 888655555 19-JUN-71
LOCAIS_DEPTO
DNÚMERO DLOCALIZAÇÃO
1 Housson
4 Stafford
5 Bellaire
5 Sugariand
5 Housson
PROJETO
PNOME PNÚMERO PLOCALIZAÇÃO DNUM
ProdutoX 1 Bellaire 5
ProdutoY 2 Sugarland 5
ProdutoZ 3 Houston 5
Automação 10 Stafford 4
Reorganização 20 Houston 1
Beneficiamento 30 Stafford 4
TRABALHA EM
NSSEMP PNRO HORAS
123456789 1 32,5
123456789 2 7,5
666884444 3 40,0
453453453 1 20,0
453453453 2 20,0
333445555 2 10,0
333445555 3 10,0
333445555 10 10,0
999887777 20 10,0
999887777 30 30,0
987987987 10 10,0
987987987 10 35,0
987654321 30 5,0
987654321 30 20,0
321654987 20 Null
DEPENDENTE
Sistemas de Banco de Dados
46
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
DEPARTAMENTO
DNOME ONÚMERO NSSGER DATINICGER
LOCAIS_DEPTO
DNÚMERO DLOCALIZAÇÃO
PROJETO
PNOME PNÚMERO PLOCALIZAÇÃO DNUM
TRABALHA EM
NSSEMP PNRO HORAS
DEPENDENTE
NSSEMP NOMEDEPENDENTE SEXO DATANIV RELAÇÃO
EMPREGADO
PNOME MNOME SNOME NSS DATANASC ENDEREÇO SEXO SALÁRIO NSSSUPER NDEP
DEPARTAMENTO
DNOME ONÚMERO NSSGER DATINICGER
LOCAIS_DEPTO
DNÚMERO DLOCALIZAÇÃO
PROJETO
PNOME PNÚMERO PLOCALIZAÇÃO DNUM
TRABALHA EM
NSSEMP PNRO HORAS
DEPENDENTE
NSSEMP NOMEDEPENDENTE SEXO DATANIV RELAÇÃO
47
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
O Modelo Entidade-Relacionamento (MER) é o modelo de dados de alto-nível normalmente adotado, e o esquema das
visões e de toda a base de dados é especificado em diagramas entidade-relacionamento (DER). O próximo passo a ser
dado para que os dados sejam modelados é o mapeamento do diagrama da base de dados global, obtido na fase anterior,
para um modelo de dados de implementação.
Uma estratégia de tradução, ou de mapeamento, bastante utilizada é a do modelo de dados relacional. Para isso, considere
o esquema relacional mostrado na Figura 5.1, que foi derivado do DER da Figura 3.14, seguindo um procedimento de
mapeamento. Esse procedimento é apresentado passo-a-passo, a partir do exemplo do DER COMPANHIA.
Passo 1:
Para cada entidade regular E no DER, criar uma relação R que inclua todos os atributos simples de E. Para um atributo
composto, inclua apenas os atributos simples que compõem o atributo composto. Escolha um dos atributos-chave de E
como sendo a chave-primária de R. Se a chave escolhida de E for composta, então o conjunto de atributos simples que o
48
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
compõem irão formar a chave-primária de R. No exemplo, foram criadas as relações EMPREGADO, DEPARTAMENTO e
PROJETO, correspondentes às entidades regulares EMPREGADO, DEPARTAMENTO e PROJETO presentes no DER. Os
atributos indicados com CE (chave-estrangeira) ou * (atributos de relacionamento) não foram incluídos ainda; eles serão
adicionados durante os passos subseqüentes. Foram escolhidas as chaves primárias NSS, DNÚMERO e PNÚMERO para
as relações EMPREGADO, DEPARTAMENTO e PROJETO, respectivamente.
Passo 2:
Para cada tipo de entidade fraca W do DER, com o tipo de entidade de identificação E, criar uma relação R e incluir todos
os atributos simples (ou os componentes simples de atributos compostos) de W como atributos de R. Além disso, incluir
como a chave-estrangeira de R a chave-primária da relação que corresponde ao tipo de entidade de identificação; isso
resolve o problema do tipo do relacionamento de identificação de W. A chave-primária de R é a combinação da chave-
primária do tipo de entidade de identificação e a chave-parcial do tipo de entidade fraca W. No exemplo, foi criada a
relação DEPENDENTE, correspondente ao tipo de entidade fraca DEPENDENTE do DER. Foi incluída a chave-primária da
relação EMPREGADO – que corresponde ao tipo de entidade de identificação – como um atributo de DEPENDENTE; foi
renomeado o atributo NSS para NSSEMP, embora não seja necessário. A chave-primária da relação DEPENDENTE é a
combinação {NSSEMP, NOMEDEPENDENTE} porque NOMEDEPENDENTE é chave-parcial de DEPENDENTE.
Passo 3:
Para cada tipo de relacionamento binário 1:1 R do DER, criar as relações S e T, que correspondem aos tipos de entidade
participantes em R. Escolher uma das relações, por exemplo, S, que inclua como chave-estrangeira de S a chave-primária
de T. É melhor escolher o tipo de entidade com participação total em R como a relação S. Inclua todos os atributos simples
(ou os componentes simples de atributos compostos) do tipo de relacionamento 1:1 R como atributos de S. No exemplo,
foi mapeado o tipo de relacionamento 1:1 GERÊNCIA, escolhendo o tipo de entidade participante DEPARTAMENTO para
fazer o papel de S porque sua participação no tipo de relacionamento GERÊNCIA é total (todo departamento tem um
gerente). Foi incluída a chave-primária da relação EMPREGADO como a chave-estrangeira na relação DEPARTAMENTO,
que foi chamado de NSSGER. Também foi incluído o atributo simples Data-Início do tipo de relacionamento GERÊNCIA
na relação DEPARTAMENTO e foi renomeado como DATINICGER. Note-se que uma alternativa para o mapeamento de
um tipo de relacionamento 1:1 seria unir os dois tipos de entidade e o tipo de relacionamento numa única relação. Isso
é particularmente apropriado quando ambas as participações são total e quando os tipos de entidade não participam em
quaisquer outros tipos de relacionamentos.
Passo 4:
Para cada tipo de relacionamento binário regular 1:N (não fraca) R, identificar a relação S, que representa o tipo de
entidade que participa do lado N do tipo de relacionamento. Incluir como chave-estrangeira de S a chave-primária da
relação T, que representa o outro tipo de entidade que participa em R; isso porque cada instância da entidade do lado
1 está relacionada a mais de uma instância de entidade no lado N do tipo de relacionamento. Por exemplo, no tipo de
relacionamento 1:N TRABALHA-PARA cada empregado está relacionado a um único departamento. Incluir também
quaisquer atributos simples (ou componentes simples de atributos compostos) do tipo de relacionamento 1:N como
atributos de S. No exemplo, foram mapeados os tipos de relacionamentos 1:N TRABALHA-PARA e SUPERVISIONA.
Para TRABALHA-PARA incluiu-se a chave-primária da relação DEPARTAMENTO como a chave-estrangeira na relação
Pós-Graduação a Distância
EMPREGADO e foi chamado DNUM. Para SUPERVISIONA incluiu-se a chave-primária da relação EMPREGADO como a
chave-estrangeira na relação EMPREGADO e foi denominado NSSSUPER. O relacionamento CONTROLA é mapeado da
mesma maneira.
Passo 5:
Para cada tipo de relacionamento binário M:N R, criar uma nova relação S para representar R. Incluir como chave-estrangeira
em S as chaves-primárias das relações que representam os tipos de entidades participantes; sua combinação irá formar
a chave-primária de S. Incluir também qualquer atributo simples do tipo de relacionamento M:N (ou componentes simples
49
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
dos atributos compostos) como atributos de S. Note-se que não se pode representar um tipo de relacionamento M:N como
uma simples chave-estrangeira em uma das relações participantes – como foi feito para os tipos de relacionamentos
1:1 e 1:N – por causa da razão de cardinalidade M:N. Relacionamentos M:N sempre derivam uma nova relação, para o
tipo de relacionamento.
Passo 6:
Para cada atributo A multivalorado, criar uma nova relação R que inclua um atributo correspondendo a A e a chave-primária
K da relação que representa o tipo de entidade ou o tipo de relacionamento que tem A como atributo. A chave-primária
de R é a combinação de A e K. Se o atributo multivalorado é composto, incluir os atributos simples que o compõem.
Passo 7:
Para cada tipo de relacionamento n-ário R, n>2, criar uma nova relação S para representar R. Incluir como chave-
estrangeira em S as chaves-primárias das relações que representam os tipos de entidades participantes. Incluir também
qualquer atributo simples do tipo de relacionamento n-ário (ou componentes simples dos atributos compostos) como
atributo de S. A chave-primária de S é normalmente uma combinação de todas as chaves-estrangeiras e referencia as
relações que representam os tipos de entidades participantes. Porém, se a restrição de participação (min, max) de um
dos tipos de entidades E que participa em R tiver max=1, então a chave-primária de S pode ser a chave-estrangeira que
referencia a relação E’ correspondente a E; isso porque cada entidade em E irá participar em apenas uma instância de R
e, portanto, pode identificar univocamente essa instância de relacionamento.
O principal ponto que deve ser considerado em um esquema relacional, quando comparado ao esquema do MER, é que
os tipos de relacionamento não são representados explicitamente; eles são representados por dois atributos A e B, um
para a chave-primária e outra para a chave-estrangeira – sobre o mesmo domínio – incluídos em duas relações S e T.
Duas tuplas em S e T estão relacionadas quando elas tiverem o mesmo valor para A e B, ou seja, os relacionamentos
são definidos pelos valores dos atributos A e B.
PROJETO
PNOME ...
PEÇA
NÚMERO ...
FORNECE
FNOME PNOME NÚMERO QUANTIDADE
Fonte: Adaptado de Takai et al.(2005).
Sistemas de Banco de Dados
50
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
A Figura 5.3 mostra uma representação esquemática dos passos que devem ser seguidos para a tradução de um MER.
Pós-Graduação a Distância
51
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
1. Introdução
No início dos anos 1970, no laboratório de San José, surgiu a Linguagem SQL, como fruto de um projeto da IBM.
Empenhavam-se num projeto de uma linguagem que se adequasse ao modelo relacional. Esse projeto trabalhava em
paralelo com outro que visava desenvolver um sistema de gerência de Banco de Dados relacional, chamado “System R”.
O primeiro sistema de Banco de Dados baseado em SQL tornou-se disponível comercialmente no final dos anos 1970.
A primeira versão padronizada da linguagem SQL foi publicada em meados de 1980 e dois institutos trabalharam na
sua padronização, o ANSI e o ISO. Desde então, a linguagem vem evoluindo e culminando na criação de novas versões
padronizadas, tais como a versão SQL-92 e a SQL-99, assim chamadas em referência aos anos em que foram publicadas.
A linguagem SQL é utilizada na grande maioria dos sistemas de Bancos de Dados relacionais, tais como MySQL, DB2,
SQLServer, e se tornou a mais poderosa ferramenta de definição e manipulação de Bancos de Dados relacionais.
2. Aplicabilidade e Uso
A linguagem SQL é bem diferente das linguagens comuns de programação por ser, basicamente, uma linguagem de
Sistemas de Banco de Dados
consulta a banco de dados. Ao contrário da maioria das linguagens de programação, a linguagem SQL não é uma linguagem
procedural1. Na linguagem SQL não se especifica como ou em que ordem serão executados os processos que irão fornecer
os resultados requeridos; eles são apenas informados com base nos resultados desejados. Desse modo, o sistema de
banco de dados é o responsável por escolher adequadamente os procedimentos a serem executados, de forma que os
resultados sejam obtidos com a maior eficiência possível.
Com a Linguagem SQL podemos tanto definir e construir relações, como manipular diversas relações, de forma a obter
resultados desejados. Por isso, ela é considerada uma linguagem de definição e de manipulação de dados.
1 Linguagem de programação na qual o elemento básico de programação é a procedure (uma sequência de instruções – rotina, sub-rotina ou função – associadas a um nome próprio).
52
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
A linguagem SQL pode estar presente numa imensa quantidade de sistemas de banco de dados, estando visível ou mascarada
(embutida). Na forma visível o usuário digita os comandos na linguagem SQL diretamente em um prompt de comando, de
onde também é possível visualizar os resultados. Já na forma embutida, a linguagem SQL não está visível diretamente
ao usuário; os programadores podem embutir os comandos em SQL, dentro de um programa, e criar uma interface mais
amigável com o usuário comum – esse pode interagir mais facilmente com a interface do que com a própria linguagem SQL.
Dessa forma, usuários comuns podem manipular um banco de dados sem mesmo ter algum conhecimento sobre de SQL.
A linguagem SQL é composta por um conjunto de declarações que é usado para acessar os dados utilizando gerenciadores
de banco de dados. Nem todos os gerenciadores utilizam SQL.
Uma entrada SQL é constituída por uma sequência de comandos onde um comando é composto por uma sequência de
termos (tokens1), terminada por um ponto-e-vírgula (“;”). O fim do fluxo de entrada também termina o comando, sendo
válido os termos dependendo da sintaxe particular de cada comando.
Um termo pode ser uma palavra-chave, um identificador, um identificador entre aspas, um literal (ou constante), ou um
caractere especial. Geralmente, os termos são separados por espaço em branco (espaço, tabulação ou nova-linha), mas
não há necessidade se não houver ambiguidade (normalmente só acontece quando um caractere especial está adjacente
a um termo de outro tipo). Além disso, podem existir comentários na entrada SQL e esses comentários não são termos,
constituindo-se, na realidade, em equivalentes a espaço em branco.
A seguir é apresentada uma entrada SQL, sintaticamente válida para servir de exemplo.
Figura 6.2. Exemplo de uma entrada SQL sintaticamente válida
A sequência apresentada na Figura 6.2 consiste de uma sequência de três comandos, um por linha. Mesmos não existindo
um limitador que obrigue que a sintaxe seja escrita dessa forma, pode haver mais de um comando na mesma linha, e um
único comando pode ocupar várias linhas.
A sintaxe da linguagem SQL não diferencia claramente quais termos identificam comandos e quais são operandos ou
parâmetros. Em geral, os primeiros termos são o nome do comando e, portanto, no exemplo da Figura 6.2 pode-se dizer
que estão presentes os comandos “SELECT”, “UPDATE” e “INSERT”. Entretanto, para exemplificar, o comando UPDATE
sempre requer que o termo SET apareça em uma determinada posição, e essa forma particular do comando INSERT
também requer a presença do termo VALUES para estar completa. As regras precisas da sintaxe de cada comando
estão descritas na Parte VI.
Os termos SELECT, UPDATE e VALUES mostrados no exemplo da Figura 6.2 são exemplos de palavras-chave, ou
seja, palavras que possuem um significado definido na linguagem SQL. Os termos MINHA_TABELA e A são exemplos
de identificadores, os quais identificam nomes de tabelas, colunas e outros objetos do banco de dados, dependendo do
Pós-Graduação a Distância
comando onde são utilizados. Portanto, algumas vezes são simplesmente chamados de “nomes”. As palavras-chave e os
identificadores possuem a mesma estrutura léxica, significando que não é possível saber se o termo é um identificador
ou uma palavra chave sem conhecer a linguagem.
Os identificadores e as palavras-chave do SQL devem iniciar por uma letra (a-z e, também, letras com diacrítico2 – áéç...
– e letras não latinas), ou o caractere sublinhado (_). Os demais caracteres de um identificador, ou da palavra-chave,
1 Token em computação é um segmento de texto ou símbolo que pode ser manipulado por um parser, que fornece um significado ao texto; em outras palavras, é um conjunto de
caracteres (de um alfabeto, por exemplo) com um significado coletivo.
2 diacrítico — do Gr. diakritikós, que se pode distinguir — diz-se dos sinais gráficos com que se notam os caracteres alfabéticos para lhe dar um valor especial
53
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
podem ser letras, sublinhados, dígitos (0-9) ou o cifrão ($). Deve ser observado que, de acordo com o padrão SQL, o
cifrão não é permitido em identificadores e, portanto, pode tornar a aplicação menos portável. O padrão SQL não irá
definir palavra-chave contendo dígitos, ou começando ou terminando por sublinhado e, portanto, os identificadores com
essa forma estão a salvo contra possíveis conflitos com extensões futuras do padrão.
O sistema não utiliza mais que NAMEDATALEN-1 caracteres de um identificador; podem ser escritos nomes mais
longos nos comandos, mas são truncados. Por padrão, NAMEDATALEN é 64 e, portanto, o comprimento máximo de
um identificador é 63. Se esse limite causar problema, pode ser aumentado, modificando a constante NAMEDATALEN.
Os identificadores e as palavras-chave não fazem distinção entre letras maiúsculas e minúsculas. Portanto, a expressão
“UPDATE MINHA_TABELA SET A = 5;” também pode ser escrita como “uPdAtE Minha_TaBeLa SeT a = 5;”.
De forma geral, utiliza-se a convenção de escrever as palavras-chave em letras maiúsculas e os nomes em letras minúsculas,
tornando a expressão da seguinte forma: “UPDATE minha_tabela SET a = 5;”.
Um segundo tipo de identificador é o identificador delimitado ou identificador entre aspas, formado pela colocação de
uma sequência arbitrária de caracteres entre aspas (“). Um identificador delimitado é sempre um identificador, e
nunca uma palavra-chave. Portanto, a expressão “select” pode ser usada para fazer referência a uma tabela ou coluna
chamada “select”, enquanto select sem aspas sempre é uma palavra-chave ocasionando, por isso, um erro do analisador
quando usado onde um nome de tabela ou de coluna for esperado.
Identificadores entre aspas podem conter qualquer caractere que não sejam as próprias aspas. Essa funcionalidade
permite criar nomes de tabelas e de colunas que não seriam possíveis de outra forma, como os contendo espaços ou
e-comercial (&). O limite do comprimento ainda se aplica.
A linguagem SQL diferencia as letras maiúsculas de minúsculas ao colocarmos um identificador entre aspas, enquanto
as letras dos nomes não delimitados por aspas são sempre convertidas em minúsculas. Por exemplo, os identificadores
“FOO” e foo são considerados o mesmo identificador.
2.2. Constantes
A linguagem SQL1 define, basicamente, três tipos de constante com tipo implícito. São eles: cadeias de caracteres,
cadeias de bits e numéricas. As constantes também podem ser especificadas com tipo explícito, o que permite uma
representação mais precisa, e um tratamento mais eficiente por parte do sistema.
Uma constante cadeia de caracteres no SQL é uma sequência arbitrária de caracteres envolta por apóstrofos (‘).
Exemplificando, suponhamos a seguinte expressão: ‘Esta é uma cadeia de caracteres’.
A forma de escrever um apóstrofo dentro de uma constante cadeia de caracteres, em conformidade com o padrão
SQL, é colocar dois apóstrofos adjacentes como, por exemplo, ‘Maria D’’Almeida’. Alguns SGBDs permitem, também, a
utilização da contrabarra (“\”) como caractere de escape para colocar apóstrofos dentro de cadeia de caracteres como,
por exemplo, ‘Maria D\’Almeida’.
Sistemas de Banco de Dados
O SGBD PostgreSQL permite a utilização dos escapes de contrabarra no estilo da linguagem C. Comando como o “\b”
para voltar apagando (backspace), “\f” para avanço de formulário (form feed), “\n” para nova-linha, “\r” para retorno do
carro, “\t” para tabulação e “\xxx”, onde “xxx” é um número octal, é o byte com o código. Nesse caso, para incluir uma
contrabarra em uma constante do tipo cadeia de caracteres devem ser escritas duas contrabarras adjacentes.
1 A quantidade de tipos de constantes pode variar conforme o Sistema Gerenciado de Banco de Dados que usa a linguagem SQL.
54
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Na linguagem SQL, duas constantes cadeias de caracteres separadas apenas por espaço em branco com pelo menos um
caractere de nova-linha, são concatenadas e tratadas efetivamente como se a cadeia de caracteres tivesse sido escrita
em uma constante. Desse modo, vejamos a expressão descrita na Figura 6.3. Porém, a expressão “SELECT ‘foo’ ‘bar’;”
é interpretada como uma expressão de sintaxe inválida.
Uma constante do tipo cadeia de bits se parece com uma constante do tipo cadeia de caracteres contendo a letra B
(maiúscula ou minúscula) imediatamente antes do apóstrofo de abertura (sem espaços separadores) como, por exemplo,
B’1001’. Os únicos caracteres permitidos dentro de uma constante do tipo cadeia de bits são 0 e 1.
SELECT ‘foo’
‘bar’;
Equivale a:
SELECT ‘foobar’;
Como forma alternativa, constantes do tipo cadeia de bits podem ser especificadas usando a notação hexadecimal,
colocando a letra X (maiúscula ou minúscula) no início como, por exemplo, X’1FF’. Essa notação equivale a uma constante
do tipo cadeia de bits contendo quatro dígitos binários para cada dígito hexadecimal.
As duas formas de constantes do tipo cadeia de bits podem ocupar mais de uma linha, da mesma forma que uma constante
do tipo cadeia de caracteres.
De forma geral, são aceitas constantes numéricas nas seguintes formas gerais:
dígitos
dígitos.[dígitos][e[+-]dígitos]
[dígitos].dígitos[e[+-]dígitos]
dígitos[e[+-]dígitos
Nas formas gerais descrita, dígitos são um ou mais dígitos decimais (0 a 9), devendo haver pelo menos um dígito antes
ou depois do ponto decimal, caso esse seja usado.
Deve haver, também, pelo menos um dígito após a marca de expoente (e), caso esteja presente. Não podem existir
espaços ou outros caracteres incorporados à constante. Deve ser observado que os sinais menos e mais que antecedem
a constante não são, na verdade, considerados parte da constante, e sim um operador aplicado à constante.
42
3.5
4.
.001
5e2
1.925e-3
55
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Uma constante numérica não contendo o ponto decimal nem o expoente é presumida, inicialmente, como sendo do tipo
integer se o seu valor for apropriado para o tipo integer (32 bits); senão, é presumida como sendo do tipo bigint, se o seu
valor for apropriado para o tipo bigint (64 bits); caso contrário, é assumida como sendo do tipo numeric. As constantes
que contêm pontos decimais e/ou expoentes são sempre presumidas, inicialmente como sendo do tipo numeric.
O tipo de dado atribuído inicialmente para a constante numérica é apenas o ponto de partida para os algoritmos de resolução
de tipo. Na maioria dos casos, a constante é automaticamente convertida no tipo mais apropriado conforme o contexto.
Pode ser declarada uma constante de um tipo arbitrário utilizando uma das seguintes notações:
O texto da constante cadeia de caracteres é passado para a rotina de conversão da entrada para o tipo chamado tipo. O
resultado é uma constante do tipo indicado. A conversão explícita de tipo pode ser omitida caso não haja ambiguidade
com relação ao tipo que a constante deva ter (por exemplo, quando é atribuída diretamente para uma coluna de uma
tabela), e nesse caso é convertida automaticamente.
Também é possível especificar a conversão de tipo utilizando a sintaxe semelhante à chamada de função: “nome_do_tipo
( ‘cadeia de caracteres’ )”. Porém, nem todos os nomes de tipo podem ser usados dessa forma.
2.3. Operadores
A linguagem SQL define que um nome de operador é uma sequência com até NAMEDATALEN-1 (por padrão 63) caracteres
da seguinte lista:
+-*/<>=~!@#%^&|`?
• Não podem ocorrer as sequências -- e /* em nenhuma posição no nome do operador, porque são consideradas
início de comentário.
• Um nome de operador com vários caracteres não pode terminar por + ou por -, a não ser que o nome também
contenha ao menos um dos seguintes caracteres: ~ ! @ # % ^ & | ` ?. Por exemplo, @- é um nome de
operador permitido, mas *- não é.
Alguns caracteres não alfanuméricos possuem significado especial diferente de ser um operador.
• O caractere cifrão ($) seguido por dígitos é utilizado para representar parâmetros posicionais no corpo da
definição de uma função. Em outros contextos, o caractere cifrão pode ser parte de um identificador.
Sistemas de Banco de Dados
• Os parênteses (()) possuem seu significado usual de agrupar expressões e impor a precedência. Em alguns
casos, os parênteses são requeridos como parte da sintaxe fixada para um determinado comando SQL.
• As vírgulas (,) são utilizadas em algumas construções sintáticas para separar elementos da lista.
• O ponto-e-vírgula (;) termina um comando SQL, não podendo aparecer em nenhum lugar dentro do comando,
exceto dentro de constantes do tipo cadeia de caracteres ou identificadores entre aspas.
56
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
• Os dois-pontos (:) são utilizados para selecionar “fatias” de matrizes. Em certos dialetos do SQL, como a
linguagem SQL incorporada, os dois-pontos são utilizados como prefixo dos nomes das variáveis.
• O asterisco (*) é utilizado em alguns contextos para denotar todos os campos da linha de uma tabela ou de
um valor composto. Também possui um significado especial quando utilizado como argumento da função de
agregação COUNT.
• O ponto (.) é utilizado nas constantes numéricas, e para separar os nomes de esquemas, tabelas e colunas.
2.5. Comentários
A linguagem SQL define que um comentário é uma sequência arbitrária de caracteres começando por dois hífens e
prosseguindo até o fim da linha como, por exemplo, a expressão “Este é um comentário em conformidade com o padrão
SQL-99”. Alternativamente, é possível utilizarem-se blocos de comentários no estilo da linguagem C, conforme apresentado
na Figura 6.4, onde o comentário começa por /* e se estende até encontrar a ocorrência correspondente de */. Esses
blocos de comentários podem estar aninhados, conforme especificado no padrão SQL, mas diferentemente da linguagem
C, permitindo transformar em comentário grandes blocos de código contendo blocos de comentários.
Os comentários são removidos do fluxo de entrada antes de prosseguir com a análise sintática, sendo substituídos por
espaço em branco.
Um item léxico, também chamado de token, é uma unidade básica do texto correspondente ao programa fonte sendo,
normalmente, representado internamente pelo analisador léxico por três funções:
• Classe: diz respeito à classificação léxica do token. Sob essa ótica, um item pode ser classificado, por
exemplo, com sendo um identificador, uma constante, um operador ou mesmo uma sequência de caracteres.
• Valor ou Lexema: diz respeito ao valor léxico do token, que depende da classe e pode ser categorizado como:
– Token Simples: são aqueles que não possuem argumentos uma vez que sua classe os define completamente.
Ex. operadores matemáticos, relacionais, lógicos.
– Token com Argumento: são aqueles que possuem um valor associado e correspondem aos elementos da
linguagem definidos pelo programador. Ex. o valor de uma constante numérica.
• Posição: diz respeito ao que identifica a localização do token no programa fonte, auxiliando no processo de
Pós-Graduação a Distância
correção de erros.
A precedência léxica diz respeito à ordem de processamento dos comandos por parte do analisador léxico, sendo que a
maioria dos operadores possui a mesma precedência e associatividade esquerda. A precedência e a associatividade dos
operadores estão codificadas no analisador léxico, podendo ocasionar um comportamento contra-intuitivo. Exemplificando,
os operadores booleanos “<” e “>” possuem uma precedência diferente dos operadores booleanos “<=” e “>=”.
Também, em alguns casos é necessário adicionar parênteses ao utilizar uma combinação de operadores unários e
binários. Tomemos a expressão “SELECT 5! – 6;” para análise. Caso a expressão seja apresentada conforme descrita, o
57
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
interpretador a analisará como “SELECT 5! (-6);”, o que decorre do fato de que o interpretador não tem como identificar
que o símbolo “!” é definido como operador unário-direito e não um operador binário que foi colocado entre os operandos.
Para que a expressão seja interpretada corretamente, é necessário apresentá-la com o uso adequado do parêntese e deve
ser escrita como “SELECT (5!) – 6;”. A título de exemplo, a tabela 6.1 apresenta a precedência e a associatividade
dos operadores no PostgreSQL.
Uma tabela em um banco de dados relacional é muito semelhante a uma tabela no papel: é formada por linhas e colunas.
O número e a ordem das colunas são fixos, e cada coluna possui um nome. O número de linhas é variável, refletindo a
quantidade de dados armazenados em um determinado instante. O padrão SQL não dá nenhuma garantia sobre a ordem
das linhas na tabela.
Quando a tabela é lida, as linhas aparecem em uma ordem aleatória, a não ser que a classificação seja requisitada
explicitamente. Além disso, o SQL não atribui identificadores únicos para as linhas e, portanto, é possível existirem
várias linhas totalmente idênticas na tabela. Isto é uma consequência do modelo matemático subjacente ao SQL, mas
geralmente não é desejável. Mais adiante, neste capítulo, será mostrado como lidar com essa questão.
Cada coluna de uma tabela possui um tipo de dado que é o fator que restringe o conjunto de valores que podem ser
atribuídos à coluna e atribui semântica1 aos dados armazenados na coluna. Cada SGBD possui um conjunto de tipos
1 semântica — do Gr. semantiké, da significação — estudo da linguagem humana do ponto de vista do significado das palavras e dos enunciados. PRIBERAM - Língua Portuguesa
On-Line . (N. do T.)
58
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
de dado nativos, adequados para muitas aplicações e, de forma geral, os usuários também podem definir seus próprios
tipos de dado.
Alguns dos tipos de dado mais utilizados são o integer para números inteiros, numeric para números possivelmente
fracionários, text para cadeias de caracteres, date para datas, time para valores da hora do dia, e timestamp para valores
contendo tanto data quanto hora.
Para criar uma tabela utiliza-se o comando CREATE TABLE. Esse comando necessita que sejam especificados, ao menos,
o nome da nova tabela, os nomes das colunas, e o tipo de dado de cada coluna (Figura 6.4).
A sintaxe do comando é:
CREATE TABLE tabela (campo1 tipo [(tamanho)] [NOT NULL] [índice1] [, campo2 tipo [(tamanho)] [NOT NULL] [índice2]
[, ...]] [, CONSTRAINT índicedemulticampos [, ...]])
A sintaxe da Figura 6.5 cria a tabela chamada “minha_primeira_tabela” contendo duas colunas, onde a primeira coluna
é denominada “primeira_coluna” e possui o tipo de dado text, e a segunda coluna chama-se “segunda_coluna” e possui
o tipo de dado integer. É necessário observar que a lista de colunas deve ser envolta por parênteses e os elementos da
lista separados por vírgula.
De forma geral, são dados nomes para as tabelas e para as colunas condizentes com as informações armazenadas
(Figura 6.6.)
59
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Existe um limite quanto à quantidade de colunas que uma tabela pode conter – pode variar entre 250 e 1600, dependendo
dos tipos de dados das colunas.
Dica 1: Quando são criadas tabelas inter-relacionadas, é aconselhável escolher um padrão coerente para
atribuir nomes às tabelas e colunas.
Dica 2: A restrição not null indica que o atributo deve ser obrigatoriamente preenchido; se não for especificado,
então o “default” é que o atributo possa assumir o valor nulo.
Caso uma tabela não seja mais necessária, é possível removê-la utilizando-se o comando DROP TABLE sintaxe do
comando é:
DROP {TABLE tabela | INDEX índice ON tabela}
Dica 1: Observe que, no caso em que a chave primária da tabela removida é composta de elementos de
diversas outras tabelas, essas devem ser devidamente corrigidas. Isso pode resultar na alteração do projeto
Sistemas de Banco de Dados
físico de diversas tabelas e acabar implicando a construção de uma nova base de dados.
O comando ALTER TABLE permite que o usuário faça a inclusão de novos atributos em uma tabela (Figura 6.8.). A
sintaxe do comando é:
ALTER TABLE tabela {ADD {COLUMN campo tipo[(tamanho)] [NOT NULL] [CONSTRAINT índice] | CONSTRAINT
índicedemulticampos} | DROP {COLUMN campo I CONSTRAINT nomedoíndice} }
60
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Além de permitir adicionar colunas em uma tabela, no comando ALTER TABLE, você pode alterar uma tabela existente
utilizando:
• ADD CONSTRAINT para adicionar um índice de campos múltiplos. (Para maiores informações sobre índices
de campos múltiplos, consulte o tópico da cláusula CONSTRAINT).
• DROP COLUMN para excluir um campo. Você especifica somente o nome do campo.
• DROP CONSTRAINT para excluir um índice de campos múltiplos. Você especifica somente o nome do índice
após a palavra reservada CONSTRAINT.
• NOT NULL em um campo único ou dentro de uma cláusula CONSTRAINT nomeada, que se aplica a uma
CONSTRAINT de campo único ou campos múltiplos. Contudo, você pode aplicar a restrição NOT NULL
somente uma vez a um campo pois, senão, ocorrerá um erro em tempo de execução.
Você não pode adicionar ou excluir mais de um campo ou índice de cada vez.
Dica 1: No caso do comando ALTER TABLE, a restrição NOT NULL não é permitida, pois assim que se insere
um novo atributo na tabela, o valor para o mesmo em todas as tuplas da tabela receberão o valor NULL.
Implicitamente definidas pelo SGBD, toda tabela possui diversas colunas do sistema. Desse modo, esses nomes não
podem ser utilizados como nomes de colunas definidas pelo usuário. A Tabela 6.5 apresenta os nomes usuais das colunas
Pós-Graduação a Distância
do sistema.
61
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Nome Descrição
É o identificador de objeto (object ID) de uma linha e consiste de um número serial adicionado
pelo SGBD, automaticamente, a todas as linhas da tabela (a não ser que a tabela seja criada
oid
com WITHOUT OIDS e, nesse caso, esta coluna não estará presente). O tipo desta coluna é
oid (o mesmo nome da coluna).
É o OID da tabela que contém esta linha. Esse atributo é particularmente útil nas consultas
fazendo seleção em hierarquias de herança, porque sem ele é difícil saber de que tabela se
tableoid
origina cada linha. Pode ser feita uma junção entre tableoid e a coluna oid de pq_class para
obter o nome da tabela.
É o identificador da transação de inserção (transaction ID) para esta versão da linha. Uma
xmin versão da linha é um estado individual da linha; cada atualização da linha cria uma nova versão
de linha para a mesma linha lógica.
cmin É o identificador do comando, começando por zero, dentro da transação de inserção.
É o identificador da transação de exclusão (transaction ID), ou zero para uma versão de linha
xmax
não excluída.
cmax É o identificador do comando dentro da transação de exclusão, ou zero.
ctid É a localização física da versão da linha dentro da tabela.
Os OIDs, os identificadores de transações e os identificadores de comandos são quantidades de 32 bits atribuídas a partir
de um contador único para todo o agrupamento de bancos de dados. Na prática, essas quantidades criam um limite de
232 (4 bilhões) de comandos SQL dentro de uma única transação.
Dica 1: Deve-se observar que essa restrição de uso do nome de uma coluna definida pelo sistema é diferente
do nome ser uma palavra-chave ou não, pois colocar o nome entre aspas não faz esta restrição deixar de
ser aplicada.
A linguagem SQL permite que sejam definidas restrições quanto a colunas e tabelas, de forma a controlar os dados
que são armazenados nela. Desse modo, é possível impedir que o usuário armazene dados em uma coluna da tabela
Sistemas de Banco de Dados
que acabe por violar a integridade do conteúdo. Tais restrições permitem que se tenha controle sobre os dados que são
armazenados na tabela.
Entre os tipos de restrições existentes, a restrição de verificação é a mais genérica, pois permite que sejam especificados
os valores que podem ser armazenados em uma determinada coluna para estar de acordo com uma expressão booleana
62
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
(valor-verdade1). Na Figura 6.9, é apresentada uma expressão onde é verificado se os valores relativos aos preços são
positivos.
Na linguagem SQL, a definição da restrição vem após o tipo de dado, assim como a definição do valor padrão. Já o
valor padrão e a restrição podem estar em qualquer ordem, sendo que a restrição de verificação é formada pela palavra
chave CHECK, seguida por uma expressão entre parênteses. Cabe salientar que a expressão da restrição de verificação
necessita envolver a coluna sendo restringida.
Por outro lado, também é possível atribuir um nome individual para a restrição, tornando a mensagem de erro mais clara
e permitindo fazer referência à restrição quando se desejar alterá-la (Figura 6.10).
Figura 6.10. Exemplo de Restrição de Verificação em uma Coluna Atribuindo um Nome para a Restrição
A palavra-chave CONSTRAINT permite que seja atribuído um nome para a restrição e deve ser seguida por um identificador
(nome que será dado à restrição) e um valor que definirá a restrição.
Além disso, é possível definir uma restrição de verificação que referencie mais de uma coluna. Na Figura 6.11, temos
uma expressão onde é verificado o valor armazenado tanto do preço quanto do preço com desconto. Nesse caso, o que
se espera é que o valor relativo ao preço seja maior do que o valor relativo ao preço com desconto.
Figura 6.11. Exemplo de Restrição de Verificação em uma Coluna Referenciando mais de uma Coluna
1 Na lógica, o valor-verdade (truth-value) é um valor indicando até que ponto uma declaração é verdadeira.
63
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Diferentemente da restrição de coluna, a restrição de tabela utiliza uma nova sintaxe, e não está anexada a uma coluna
em particular, aparecendo como um item à parte na lista de colunas separadas por vírgula. As definições das colunas e
as definições dessas restrições podem estar em qualquer ordem.
As Figuras 6.12 e 6.13 apresentam o exemplo da Figura 6.9, reescrito na forma de restrição de tabela.
Uma Restrição de Não Nulo define que o valor de uma coluna não pode ser nulo, ou seja, que necessita conter algum valor
(Figura 6.14). Cabe lembrar que uma Restrição de Não Nulo é sempre escrita como restrição de coluna e não uma restrição
de tabela, sendo que essa é funcionalmente equivalente a criar uma restrição de verificação CHECK (nome_da_coluna
IS NOT NULL.
Como uma coluna pode possuir mais de uma restrição, para considerar todas as restrições necessárias, basta escrever
uma restrição em seguida da outra (Figura 6.15), sendo que a ordem em que as restrições são escritas não determina
Sistemas de Banco de Dados
64
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Dica 1: Em grande parte dos projetos de banco de dados, a maioria das colunas deve ser especificada como
não-nula.
A restrição de unicidade procura garantir que os dados contidos em uma coluna, ou mesmo em um grupo de colunas,
seja único com relação a todas as outras linhas da tabela. A Figura 6.16 apresenta um exemplo desse tipo de restrição
aplicada a uma coluna e a Figura 6.17, um exemplo desta mesma restrição aplicada a uma tabela.
Caso uma restrição de unicidade faça referência a um grupo de colunas, essas devem ser listadas separadas por vírgula,
conforme a Figura 6.18. Esse tipo de restrição especifica que a combinação dos valores das colunas indicadas deve ser
única para toda a tabela, embora não seja necessário que cada uma das colunas seja única.
65
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Figura 6.19. Exemplo de Restrição de Unicidade em uma Coluna Atribuindo um Nome para a Restrição
De modo geral, a restrição de chave primária diz respeito à combinação da restrição de unicidade com a restrição de não-
nulo. Desse modo, é possível definir esse tipo de restrição de mais de um modo, conforme apresentado na Figura 6.20.
Figura 6.20. Exemplo de Restrição de Chave Primária versus Restrição de Não-Nulo e Unicidade
Por outro lado, as chaves primárias também podem restringir valores em mais de uma coluna (Figura 6.21).
);
Uma restrição de chave estrangeira procura especificar que o valor de uma coluna, ou mesmo grupo de colunas, corresponda
a algum valor existente em uma linha de outra tabela, de forma a manter a integridade referencial 1 entre duas ou mais
tabelas relacionadas.
1 Integridade Referencial é um conceito de banco de dados que garante que todos os relacionamentos propostos entre tabelas no modelo de entidade-relacionamento (ER) serão
respeitados, dando a certeza que os dados de um banco de dados estarão íntegros.
66
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
A título de exemplo, tomemos a tabela criada pela sintaxe do segundo item apresentado na Figura 6.20. Adicionalmente,
criemos outra tabela destinada a conter os dados dos pedidos relativos aos produtos. Como existe uma relação entre as
duas tabelas (pedidos e produtos) em que cada pedido precisa conter um ou mais produtos, podemos impor a restrição
de chave-estrangeira para garantir que não sejam incluídos produtos em um pedido que não estejam cadastrados na
tabela produtos (Figura 6.22).
No exemplo utilizado, podemos dizer que a tabela de pedidos é a que faz referência, e a tabela de produtos é a referenciada.
Esse tipo de restrição necessita que exista correspondência entre o número e tipo das colunas referenciadas.
Por outro lado, uma tabela também pode conter mais de uma restrição de chave estrangeira, o que é utilizado para
implementar relacionamentos muitos-para-muitos entre tabelas (Figura 6.22). Na Figura 6.23 é exemplificada uma relação
em que a tabela “itens_pedidos” faz referência às tabelas “pedidos” e “produtos” para poder armazenar os dados relativos
a que pedido os itens se referem e que produto deverá constar de cada item.
A partir da restrição imposta, sabemos que a chave estrangeira não permite a criação de pedidos não relacionados com
algum produto. No entanto, é necessário considerar a situação onde um produto seja removido após a criação de um
pedido fazendo referência a esse produto. A linguagem SQL permite tratar essa situação no sentido de que quando se
desejar remover um produto referenciado por um pedido (por meio da tabela itens_pedidos), isso não será permitido, pois
caso um pedido seja removido, os itens do pedido também serão removidos.
67
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
De forma geral, as opções mais comuns são restringir ou mesmo excluir em cascata (Figura 6.24). O comando RESTRICT,
utilizado para garantir a integridade, também pode ser escrito como NO ACTION, e também é o padrão se nada for
especificado.
Além das opções apresentadas, ainda é possível outras duas opções sobre o que deve acontecer com as colunas da chave
estrangeira quando a chave primária é excluída, SET NULL e SET DEFAULT. Deve ser observado que isso não livra da
obediência às restrições. Por exemplo, se uma ação especificar SET DEFAULT, mas o valor padrão não satisfizer a chave
estrangeira, a exclusão da chave primária não vai ser bem-sucedida.
Semelhante ao comando ON DELETE existe também o comando ON UPDATE, utilizada quando uma coluna referenciada
é atualizada, sendo que as ações possíveis são as mesmas.
Dica 1: A chave estrangeira deve referenciar colunas de uma chave primária ou de uma restrição de unicidade.
de criar vários bancos de dados, criamos um e criamos esquemas dentro desse. Isso permite uma maior flexibilidade,
pois uma única conexão ao banco permite acessar todos os esquemas e suas tabelas. Portanto, devemos planejar com
eficiência para saber quantos bancos precisaremos, quantos esquemas em cada banco e quantas tabelas em cada esquema.
Cada banco ao ser criado traz um esquema public, que é onde ficam todas as tabelas, caso não seja criado outro esquema.
Esse esquema public não é padrão ANSI. Caso se pretenda ao portável, devemos excluir esse esquema public e criar
outros. Por default todos os usuários criados têm privilégio CREATE e USAGE para o esquema public.
68
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Um esquema é essencialmente um espaço de nomes: contém objetos com nome (tabelas, tipos de dado, funções e
operadores), cujos nomes podem ser iguais aos de outros objetos existentes em outros esquemas. Os objetos com nome
são acessados “qualificando” seus nomes, usando o nome do esquema como prefixo, ou definindo um caminho de procura
que inclua os esquemas desejados.
• Para organizar objetos do banco de dados em grupos lógicos tornando-os mais gerenciáveis.
• Para poder colocar, em esquemas separados, aplicações desenvolvidas por terceiros, de modo a não haver
colisão com nomes de outros objetos.
Os esquemas são análogos aos diretórios no nível do sistema operacional, exceto os esquemas que não podem ser
aninhados.
A instrução CREATE SCHEMA pode criar um esquema, as tabelas e as exibições contidas e as permissões GRANT,
REVOKE ou DENY em qualquer item protegido em uma única instrução. Deve ser executada como um lote separado
sendo que os objetos gerados por ela são criados diretamente no esquema ativo. As transações CREATE SCHEMA são
atômicas e, caso algum erro ocorra durante a execução da instrução, nenhum item protegido especificado será criado e
nenhuma permissão será concedida.
Os itens protegíveis criados por CREATE SCHEMA podem ser listados em qualquer ordem, com exceção das exibições que
fazem referência a outras exibições. Nesse caso, a exibição mencionada deve ser criada antes da exibição que a menciona.
Portanto, uma instrução GRANT pode conceder permissões em um objeto antes que o objeto propriamente dito seja criado,
ou uma instrução CREATE VIEW pode aparecer antes das instruções CREATE TABLE, que criam as tabelas mencionadas
pela exibição. Além disso, as instruções CREATE TABLE podem declarar chaves estrangeiras definidas posteriormente
na instrução CREATE SCHEMA
A sintaxe do comando é:
CREATE SCHEMA nome_do_esquema [AUTHORIZATION nome_do_usuário ] [elemento_do_esquema [ ... ] ] CREATE
SCHEMA AUTHORIZATION nome_do_usuário [ elemento_do_esquema [ ... ] ]
Nome_do_usuário O nome do usuário que será o dono do esquema. Se for omitido, tem como padrão
o usuário que está executando o comando. Somente os superusuários podem criar
esquemas pertencentes a outros usuários.
Elemento_do_esquema Um comando SQL definindo um objeto a ser criado no esquema. Atualmente,
somente CREATE TABLE, CREATE VIEW, CREATE INDEX, CREATE SEQUENCE,
CREATE TRIGGER e GRANT são aceitos como cláusula no comando CREATE
SCHEMA. Os objetos de outros tipos podem ser criados por comando em separado,
após o esquema ter sido criado.
69
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Na Figura 6.25 é apresentada uma expressão em que é um esquema e uma visão estão mostrando os filmes premiados.
Deve ser observado que os subcomandos individuais não terminam por ponto-e-vírgula.
Dica 1: As instruções que contêm CREATE SCHEMA AUTHORIZATION, mas não especificam um nome, são
permitidas somente para compatibilidade com versões anteriores.
Dica 2: As instruções CREATE SCHEMA oferecem suporte para DENY e REVOKE. As cláusulas DENY e
REVOKE serão executadas na ordem em que aparecem na instrução CREATE SCHEMA.
O comando ALTER SCHEMA altera a definição de um esquema. Para utilizar o comando ALTER SCHEMA é necessário
ser o dono do esquema ou ter privilégio para tal. Para mudar o nome do esquema também é necessário possuir o privilégio
CREATE no banco de dados.
Para alterar o dono, também é necessário ser um membro direto ou indireto do novo papel dono, além de possuir o
privilégio CREATE no banco de dados.
A sintaxe do comando é:
ALTER SCHEMA nome_do_esquema RENAME TO novo_nome_do_esquema
ALTER SCHEMA nome_do_esquema OWNER TO nome_do_novo_usuário
Dica 1: Apesar do padrão SQL não possuir esse tipo de recurso, boa parte dos SGBDs já o disponibilizam
como aprimoramento da linguagem.
O comando DROP SCHEMA objetiva remover esquemas do banco de dados. O esquema somente pode ser removido pelo
seu dono ou por um dba. Deve ser observado que o dono pode remover o esquema (e, portanto, todos os objetos que
esse contém), mesmo que não seja o dono de alguns objetos contidos no esquema.
Sistemas de Banco de Dados
A sintaxe do comando é:
DROP SCHEMA nome_do_esquema [, ...] [ CASCADE | RESTRICT ]
A opção CASCADE permite que sejam removidos os objetos (tabelas, funções) contidos no esquema, e a opção RESTRICT
permite que seja verificada a existência de algum objeto vinculado ao esquema e impede que o esquema seja removido
quando tem algum conteúdo. Essa é uma opção padrão para a instrução DROP SCHEMA.
70
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Na Figura 6.24 o esquema criado recebeu o nome de cinema e os demais componentes (tabela e visão) também foram
nominados. No entanto, caso não fosse indicado um nome para o esquema e para os elementos criados, por padrão, as
tabelas (e outros objetos) seriam colocadas automaticamente em um esquema chamado “public”. Todo banco de dados
novo possui esse esquema. Portanto, poderíamos reescrever o exemplo da Figura 6.25 da seguinte forma (Figura 6.26),
sem qualquer prejuízo quanto à criação do esquema desejado.
CREATE SCHEMA
CREATE TABLE filmes (titulo text, lancamento date, premios text[])
CREATE VIEW premiados AS
SELECT titulo, lancamento FROM filmes WHERE premios IS NOT NULL;
Com base no exemplo da Figura 6.26, a tabela “filmes” não seria criada por uma instrução como CREATE TABLE cinema.
filmes e sim como CREATE TABLE public.filmes.
Os nomes qualificados são desagradáveis de escrever, sendo geralmente melhor não ligar o aplicativo a um esquema
específico. Por isso, geralmente as tabelas são referenciadas por meio de nomes não qualificados, formados apenas pelo
nome da tabela. O sistema determina que tabela está sendo referenciada seguindo o caminho de procura, que é uma lista
de esquemas para procura. A primeira tabela correspondente encontrada no caminho de procura é assumida como sendo
a desejada. Não havendo nenhuma correspondência no caminho de procura é relatado um erro, mesmo que uma tabela
correspondendo ao nome exista em outro esquema no banco de dados.
O primeiro nome de esquema no caminho de procura é chamado de esquema corrente. Além de ser o primeiro esquema a
ser procurado, também é o esquema onde as novas tabelas são criadas quando o comando CREATE TABLE não especifica
o nome do esquema.
O primeiro elemento especifica que deve ser procurado o esquema com o mesmo nome do usuário corrente. Se esse
esquema não existir, essa entrada será ignorada. O segundo elemento se refere ao esquema público visto anteriormente.
O primeiro esquema existente do caminho de procura é o local padrão para a criação dos novos objetos. Essa é a razão
Pós-Graduação a Distância
pela qual, por padrão, os objetos são criados no esquema público. Quando os objetos são referenciados em qualquer outro
contexto sem qualificação pelo esquema (comandos de modificação de tabelas, modificação de dados ou consultas) o
caminho de procura é percorrido até que o objeto correspondente seja encontrado. Portanto, na configuração padrão,
qualquer acesso não qualificado somente pode fazer referência ao esquema público.
71
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Por padrão, os usuários não podem acessar objetos em esquemas que não são seus. Para poderem acessá-los, o dono
do esquema precisa conceder o privilégio USAGE para o esquema. Para permitir os usuários utilizarem os objetos do
esquema é necessário conceder privilégios adicionais, conforme seja apropriado para cada objeto.
Pode ser permitido, também, que um usuário crie objetos no esquema de outro usuário. Para permitir que isso seja feito,
deve ser concedido o privilégio CREATE para o esquema. Deve ser observado que, por padrão, todos os usuários possuem
o privilégio CREATE e USAGE para o esquema public. Isso permite a todos os usuários que podem se conectar ao banco
de dados criarem objetos no esquema public.
Se isso não for desejado, esse privilégio poderá ser revogado, utilizando a seguinte sintaxe:
O primeiro “public” no comando acima é o nome do esquema, enquanto o segundo “public” significa “todos os usuários”.
Na primeira ocorrência é um identificador, enquanto que na segunda ocorrência é uma palavra-chave; por isso, na primeira
vez está escrito em minúsculas, enquanto que, na segunda vez, em maiúsculas.
Além do esquema public e dos esquemas criados pelos usuários, cada banco de dados inclui o esquema contendo as
tabelas do sistema e todos os tipos de dados, funções e operadores nativos (nome do esquema pode variar de acordo com
o SGBD). Esse catálogo é sempre parte efetiva do caminho de procura. Se não for colocado explicitamente no caminho
de procura, então será procurado implicitamente antes dos esquemas do caminho de procura. Isso garante que os nomes
nativos sempre possam ser encontrados. Entretanto, é possível colocar explicitamente o nome do catálogo no final do
caminho de procura, se for desejado que os nomes definidos pelo usuário substituam os nomes nativos.
Os esquemas podem ser utilizados para organizar os dados de várias maneiras. Existem uns poucos modelos de utilização
recomendados, facilmente suportados pela configuração padrão:
• Se não for criado nenhum esquema, então todos os usuários acessarão o esquema público implicitamente,
simulando a situação onde os esquemas não estão disponíveis. Essa configuração é recomendada,
principalmente, quando existe no banco de dados apenas um usuário, ou alguns poucos usuários colaborativos.
Essa configuração também permite uma transição suave de uma situação sem esquemas.
• Pode ser criado um esquema para cada usuário com o mesmo nome do usuário. Lembre-se que o caminho de
procura padrão começa por $user, que é resolvido como o nome do usuário. Portanto, se cada usuário possuir
um esquema separado, vão acessar seus próprios esquemas por padrão.
• Se essa configuração for utilizada, também poderá ser revogado o acesso ao esquema público (ou mesmo
removê-lo), deixando os usuários totalmente restritos aos seus próprios esquemas.
Sistemas de Banco de Dados
• Para instalar aplicações compartilhadas (tabelas utilizadas por todos, funções adicionais fornecidas por
terceiros), essas devem ser colocadas em esquemas separados. Devem ser concedidos, também, os privilégios
necessários para permitir o acesso pelos outros usuários. Os usuários poderão, então, fazer referência a
esses objetos adicionais qualificando seus nomes com o nome do esquema, ou poderão adicionar esquemas
ao caminho de procura, conforme julgarem melhor.
72
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
4.7. Portabilidade
No padrão SQL, não existe a noção de objetos no mesmo esquema pertencendo a usuários diferentes. Além disso, algumas
implementações não permitem criar esquemas com nome diferente do nome de seu dono. Na verdade, os conceitos de
esquema e de usuário são praticamente equivalentes em sistemas de banco de dados que implementam somente o suporte
básico a esquemas especificado no padrão. Portanto, muitos usuários consideram os nomes qualificados na verdade
formados por nome_do_usuário.nome_da_tabela.
Obviamente, alguns sistemas de banco de dados SQL podem não implementar esquemas de nenhuma maneira, ou oferecer
suporte a espaços de nomes, permitindo apenas acesso entre bancos de dados. Se for necessário trabalhar com esses
sistemas, será obtido o máximo de portabilidade, não utilizando nada relacionado a esquemas.
5. Consultas em SQL
Uma consulta expressa em uma linguagem de consulta de alto nível, como a SQL, deve primeiramente ser examinada,
analisada e validada. O examinador identifica os símbolos da linguagem – como por exemplo palavras chaves da SQL,
nomes de atributos e nomes de relações – no texto de consulta, enquanto o analisador verifica a sintaxe de consulta para
determinar se ela está formulada de acordo com as regras de sintaxe (regras de gramática) da linguagem de consulta.
Além disso, a consulta também deve ser validada, verificando se todos os nomes de atributos e relações são válidos e
semanticamente significativos no esquema do banco de dados específico que está sendo consultado. Uma representação
interna da consulta é, então, criada, geralmente em forma de uma estrutura de dados de árvore1, denominada árvore de
consulta. Também é possível representar a consulta utilizando-se de uma estrutura gráfica de dados denominada gráfico
de consulta. O SGBD deve então planejar uma estratégia de execução para recuperar o resultado da consulta, a partir dos
arquivos de banco de dados. Uma consulta geralmente tem muitas estratégias de execução e o processamento utilizado
para escolher uma estratégia que seja adequada para processar uma consulta é conhecido como otimização de consulta
O comando select permite a seleção de tuplas e atributos em uma ou mais tabelas. A sintaxe básica para o uso do
comando select é:
SELECT [atributo] { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]}
FROM expressãodetabela [, ...] [IN bancodedadosexterno]
[WHERE... ]
[GROUP BY... ]
[HAVING... ]
[ORDER BY... ]
[WITH OWNERACCESS OPTION]
1 Árvore é uma estrutura de dados que herda as características das topologias em árvore. Conceitualmente difere das listas encadeadas, em que os dados se encontram numa
sequência, pelo fato dos dados estarem dispostos de forma hierárquica.
73
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Por exemplo, suponhamos que estamos trabalhando com um banco de dados onde existe o cadastro de pessoal de uma
empresa. Nesse caso, para selecionar o nome e o RG dos funcionários que trabalham no departamento número 2, na
tabela EMPREGADOS utilizamos o seguinte comando:
SELECT nome, rg
FROM EMPREGADOS
WHERE depto = 2;
Na linguagem em SQL também é permitido o uso de condições múltiplas, conforme o seguinte exemplo:
SELECT nome, rg, salario
FROM EMPREGADOS
WHERE depto = 2 AND salario > 2500.00;
A instrução que envolver as cláusulas SELECT-FROM-WHERE em SQL permite envolver quantas tabelas forem necessárias.
Tomemos como exemplo a situação em que desejamos selecionar o número do departamento que controla projetos
localizados em Brasília. Para tanto, podemos utilizar o seguinte comando:
SELECT t1.numero_depto
FROM departamento_projeto t1, projeto t2
WHERE t1.numero_projeto = t2.numero;
74
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Na expressão anterior, t1 e t2 são chamados “alias” (apelidos) e representam a mesma tabela a qual estão referenciando.
Um “alias” é muito importante quando há redundância nos nomes das colunas de duas ou mais tabelas que estão envolvidas
em uma expressão. Ao invés de utilizar o “alias”, também é possível utilizar o nome da tabela, mas isso pode se tornar
muito trabalhoso em consultas muito complexas, além do que impossibilitaria a utilização da mesma tabela mais que
uma vez em uma expressão SQL.
Suponhamos que desejamos selecionar o nome e o RG de todos os funcionários que são supervisores. Para tanto, podemos
utilizar o seguinte comando:
SELECT e1.nome, e1.rg
FROM empregado e1, empregado e2
WHERE e1.rg = e2.rg_supervisor;
Nome RG
João Luiz 10101010
Fernando 20202020
A utilização do operador * dentro do especificador SELECT permite selecionar todos os atributos de uma tabela, enquanto
que a exclusão do especificador WHERE faz com que todas as tuplas de uma tabela sejam selecionadas. Vejamos o
comando apresentado a seguir:
SELECT *
FROM empregados;
Um ponto importante a considerar é que a operação SELECT em SQL permite a geração de tuplas duplicadas como resultado
de uma expressão. Para evitar isto, é necessário utilizar o especificador DISTINCT. Suponhamos o seguinte exemplo:
SELECT depto FROM empregado;
Depto.
Pós-Graduação a Distância
1
2
2
2
3
75
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Depto.
1
2
3
Outra possibilidade da linguagem SQL é a geração de consultas aninhadas utilizando o especificador IN, que permite
que seja feita uma comparação do especificador WHERE da consulta mais externa com o resultado da consulta mais
interna. Suponhamos que desejamos selecionar o nome de todos os funcionários que trabalham em projetos localizados
em Brasília. O comando a ser utilizado será:
SELECT e1.nome, e1.rg, e1.depto FROM empregado e1, empregado_projeto e2 WHERE e1.rg = e2.rg_empregado
AND e2.numero_projeto IN (select numero FROM projeto WHERE localizacao = ‘Brasília‘);
Caso seja necessário selecionar um conjunto de tuplas de forma ordenada devemos utilizar o comando ORDER BY.
Suponhamos que desejamos selecionar todos os empregados por ordem alfabética. O comando a ser utilizado será:
SELECT nome, rg, depto
FROM empregado
ORDER BY nome;
O comando INSERT objetiva inserir novas linhas na tabela. Podem ser inseridas uma ou mais linhas especificadas por
expressões de valor, ou zero ou mais linhas resultantes de uma consulta.
Os nomes das colunas de destino podem ser listados em qualquer ordem sendo que quando não é fornecida nenhuma lista
de nomes de colunas, o padrão é usar todas as colunas da tabela na ordem em que foram declaradas; ou os primeiros N
nomes de colunas, se existirem apenas N colunas fornecidas na cláusula VALUES ou na consulta. Os valores fornecidos
pela cláusula VALUES ou pela consulta são associados à lista de colunas explícita ou implícita da esquerda para a direita.
As colunas que não estão presentes na lista de colunas explícita ou implícita são preenchidas com o valor padrão, seja
o valor padrão declarado ou nulo se não houver nenhum.
Se a expressão para alguma coluna não for do tipo de dado correto, será tentada uma conversão de tipo automática.
A cláusula opcional RETURNING faz com que o comando INSERT compute e retorne valores baseados em cada linha
realmente inserida. Sua utilidade principal é obter valores fornecidos por padrão, como o número sequencial de uma
coluna serial. Entretanto, é permitida qualquer expressão que utilize as colunas da tabela. A sintaxe da lista RETURNING
Sistemas de Banco de Dados
é idêntica à da lista de saída do comando SELECT. Além disso, é necessário possuir o privilégio INSERT na tabela para
poder inserir linhas, e o privilégio SELECT para utilizar RETURNING. Se for utilizada a cláusula consulta para inserir linhas
a partir de uma consulta, também será necessário possuir o privilégio SELECT em todas as tabelas usadas pela consulta.
76
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Como nesse exemplo, todos os campos foram inseridos, não é necessário especificar o nome das colunas na sintaxe.
Suponhamos que desejamos agora inserir os seguintes dados:
nome: Joao de Campos
rg: 70707070
cic: 77777777
departamento: 3
salário: R$2.500,00
INSERT INTO empregados (nome, rg, cic, depto, salario)
VALUES (‘Joao de Campos, ‘70707070’, ‘77777777’, 3, 2500,00);
77
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
Nesse exemplo, como o campo rg_supervisor não foi inserido, foi necessário especificar as colunas que deveriam receber
dados. Outra forma de se elaborar essa inserção seria:
INSERT INTO empregados
VALUES (‘Joao de Campos, ‘70707070’, ‘77777777’, 3, ‘’, 2500,00);
Nessa situação utilizaram-se os caracteres ‘’ para se declarar que um valor nulo seria inserido nesta coluna, o que dispensa
a necessidade e se especificar as colunas.”
Parte Descrição
tabela O nome da tabela contendo os dados que você quer modificar.
Uma expressão que determina o valor a ser inserido em um campo específico dos
Novovalor
registros atualizados.
Uma expressão que determina quais registros serão atualizados. Apenas os
critérios
registros que satisfazem à expressão são atualizados.
Suponhamos que desejamos agora atualizar os dados relativos ao salário de todos os empregados que trabalham no
departamento 2 para R$ 3.000,00. O comando a ser utilizado será:
UPDATE empregado SET salario = 3.000,00 WHERE depto = 2;
Caso a cláusula WHERE seja omitida, todas as linhas da tabela serão atualizadas. Quando está presente, apenas as
linhas atendendo a condição escrita após o WHERE serão atualizadas. Observe que o sinal de igual na cláusula SET é
uma atribuição, enquanto o sinal de igual na cláusula WHERE é uma comparação, mas isto não causa ambiguidade
Dica 1: O comando UPDATE não gera um conjunto de resultados. Além disso, depois de atualizar os registros
usando uma consulta de atualização, você não poderá desfazer a operação. Se quiser saber quais os registros
que foram atualizados, examine antes os resultados de uma consulta seleção que usem os mesmos critérios e,
depois, execute a consulta de atualização. Mantenha sempre cópias de backup dos dados. Se você atualizar
Sistemas de Banco de Dados
O comando DELETE permite que seja excluída uma ou mais linhas de uma tabela. Assim como só é possível adicionar
dados para toda uma linha, também uma linha só pode ser removida por completo de uma tabela. Se for necessário excluir
valores de um campo específico, basta criar uma consulta atualização que altere os valores para Null.
78
Sistemas de Banco de Dados: conceitos e arquiteturas Unidade II
A linguagem SQL não oferece funcionalidade para endereçar diretamente linhas específicas. Portanto, a remoção de linhas
só pode ser feita por meio da especificação das condições que as linhas a serem removidas devem atender. Referenciando
uma chave primária na tabela, então, é possível especificar exatamente a linha. Porém, também pode ser removido um
grupo de linhas, atendendo a uma determinada condição, ou podem ser removidas todas as linhas da tabela de uma só vez.
Parte Descrição
tabela.* O nome opcional da tabela da qual são excluídos registros.
tabela O nome da tabela da qual são excluídos registros.
Critérios Uma expressão que determina os registros a ser excluídos
Suponhamos que desejamos agora excluir os dados relativos aos registros nos quais o empregado trabalhe no departamento
2 e possua salário maior que R$ 3.500,00. O comando a ser utilizado será:
DELETE FROM empregado WHERE salario > 3.500,00 AND depto = 2;
A função DELETE é especialmente útil quando se deseja excluir muitos registros pois, para excluir uma tabela inteira do
banco de dados, é possível usar o método Execute com uma instrução DROP, o que resulta na exclusão dos dados e da
estrutura da tabela. Em contrapartida, ao utilizar o comando DELETE, somente os dados são excluídos e a estrutura da
tabela e todas as suas propriedades, como atributos de campo e índices, permanecem intactos.
É possível utilizar o comando DELETE para remover registros de tabelas que estão em um relacionamento um-paramuitos
com outras tabelas. As operações de exclusão em cascata fazem com que os registros em tabelas que estão no lado
muitos do relacionamento sejam excluídos quando o registro correspondente no lado um do relacionamento é excluído
na consulta.
Dica 1: Depois de remover os registros utilizando uma consulta exclusão, você não poderá desfazer a operação.
Se quiser saber quais registros foram excluídos, examine antes os resultados de uma consulta seleção que
use os mesmos critérios e, depois, execute a consulta exclusão.
Pós-Graduação a Distância
79
Unidade III
Teoria e Metodologia do Projeto de
Banco de Dados
1. Dependência Funcional
Dependência Funcional diz respeito a uma restrição entre dois conjuntos de atributos de uma base de dados. Também
pode ser vista como um conjunto de restrições ao conjunto de relações válidas. Suponha que o esquema de uma base
de dados R possua n atributos A1, A2,..., An e considere que em R = { A1, A2, ... , An } como a representação universal
da base de dados.
Uma dependência funcional, representada por X Y entre dois conjuntos de atributos X e Y que são subconjuntos de R
especificam uma restrição nas tuplas que podem compor uma instância relação r de R. A restrição estabelece que para
qualquer par de tuplas t1 e t2 em r de forma que t1.[X] = t2.[X], é obrigado a existir t1.[Y] = t2.[Y]. Isto significa que os
valores do componente Y em uma tupla em r dependem de, ou são determinados pelos valores do componente X.
Para X Y lê-se: Y é funcionalmente dependente de X, ou X infere sobre Y.
A dependência (a) implica que o número de um RG define de forma única o nome do empregado e o seu CPF do empregado.
A dependência (b) implica que o número do projeto define de forma única o nome do projeto e sua localização e a
dependência (c) implica que o RG do empregado mais o número do projeto define de forma única o número de horas
que o empregado trabalhou no projeto.
Em outras palavras, uma dependência funcional pode ser vista como uma propriedade do significado ou semântica dos
atributos em um esquema de relação R. Utiliza-se o entendimento da semântica de atributos de R – isto é, como eles
Pós-Graduação a Distância
se relacionam – para especificar as dependências funcionais envolvidas em todas as instâncias da relação r (extensão)
de R. As instâncias r que satisfazem as restrições de dependência funcional especificadas sobre atributos de R são
chamadas extensões legais, pois obedecem as restrições de dependência funcional. Assim, a principal utilização das
dependências funcionais é a de descrever um esquema de relação R, especificando restrições sobre seus atributos, que
devem ser válidas todas as vezes.
A especificação das inferências deve ser elaborada pelo projetista de banco de dados em conjunto com o analista de
sistemas, pois eles deverão ter conhecimento da semântica da base de dados.
81
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
b) Dependência funcional parcial: Uma dependência funcional parcial é uma dependência funcional X Y
se existir um atributo A qualquer do componente X que pode ser removido e a dependência funcional X
Y não deixa de existir.
d) Dependência funcional multivalor: Uma dependência multivalor só se verifica nos casos em que a relação
tem pelo menos 3 atributos _ Numa relação R, o atributo y tem uma dependência funcional multivalor
relativamente a x (x, y Î R), se para cada par de tuplas de R contendo os mesmos valores de x, também
existe um par de tuplas de R correspondentes à troca dos valores de y no par original.
1.1. Normalização
O processo de normalização pode ser visto como o processo no qual são eliminados esquemas de relações (tabelas) não
satisfatórios, decompondo-os, por meio da separação de seus atributos em esquemas de relações menos complexas, mas
que satisfaçam as propriedades desejadas.
O processo de normalização, proposto inicialmente por Codd (1972), conduz um esquema de relação por meio de conjunto
de testes para certificar se o ele está na 1a, 2a e 3a Formas Normais. Essas três Formas Normais são baseadas em
dependências funcionais dos atributos do esquema de relação.
A 1a Forma Normal pressupõe que todos os atributos de uma tabela devem ser atômicos, ou seja, não são permitidos
atributos multivalorados, atributos compostos ou atributos multivalorados compostos. Consideremos o seguinte exemplo:
• CLIENTE
1. Código
2. {Telefone}
Telefone 1 Endereço
Cliente Código
Telefone n Rua No Cidade
Considerando os pressupostos da 1a Forma Normal, é necessário reestruturar a Tabela 7.1, pois seus atributos não são
atômicos. Para que a Tabela 7.1 atenda aos pressupostos da 1a Forma Normal temos que eliminar os atributos não
atômicos. O resultado é a geração das Tabelas 7.1a e 7.1b.
82
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
A 2ª Forma Normal baseia-se no conceito da dependência funcional total. Conforme mencionamos anteriormente,
uma dependência funcional X Y é total se removemos um atributo A qualquer do componente X e, desta forma, a
dependência funcional deixa de existir.
Podemos dizer que se trata de uma dependência funcional total, pois se removermos o atributo RG_Empregado ou o
atributo Número_Projeto, a dependência funcional deixa de existir.
Desse modo, podemos dizer que uma tabela T atende à 2ª Forma Normal se estiver na 1ª Forma Normal e todo atributo que
não compõem a chave primária C for em sua totalidade funcionalmente dependente da chave primária C. Se uma tabela
não está na 2ª Forma Normal, ela pode ser normalizada gerando outras tabelas cujos atributos que não façam parte da
chave primária sejam funcionalmente dependentes dela em sua totalidade, passando, assim, a assumir a 2ª Forma Normal.
A 3ª Forma Normal, por sua vez, baseia-se no conceito de dependência transitória. Como apresentado anteriormente,
uma dependência funcional transitória e uma dependência funcional X Y em uma tabela T se existir um conjunto de
atributos Z que não é um subconjunto de chaves de T e as dependências X Z, Z Y, são válidas.
a. RG {Nome_Depto, RG_Ger_Depto}
b. RG No_Departamento
c. No_Departamento {Nome_Depto, RG_Ger_Depto}
d. RG {Nome, No_Funcional}
e. RG CPF
f. CIC {Nome, No_Funcional}
83
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
Conforme pode ser visto na Tabela 7.2b, o CPF, por ser naturalmente um identificador do empregado, pode ser encarado
como uma chave-candidata.
Uma tabela está na 3a Forma Normal se estiver na 2a Forma Normal e não houver dependência transitiva entre atributos
não chave.
2. A Álgebra Relacional
A Álgebra Relacional é uma coleção de operações canônicas que são utilizadas para manipular as relações. Segundo
Silberschatz (2006), a Álgebra Relacional é um conjunto de operadores que tomam relações como seus operandos e
retorna uma relação como seu resultado.
Essas operações são utilizadas para selecionar tuplas de relações individuais e para combinar tuplas relacionadas de
relações diferentes para especificar uma consulta em um determinado banco de dados. O resultado de cada operação é
uma nova operação, a qual também pode ser manipulada pela álgebra relacional.
• Definir requisitos de segurança (definir os dados sobre os quais será concedida alguma espécie de autorização).
A operação SELECT é utilizada para selecionar um subconjunto de tuplas de uma relação, sendo que essas tuplas devem
satisfazer uma condição de seleção. A forma geral de uma operação SELECT é:
A letra grega é utilizada para representar a operação de seleção; <condição de seleção> é uma expressão booleana
aplicada sobre os atributos da relação e <nome da relação> é o nome da relação sobre a qual será aplicada a
operação SELECT.
84
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
Os operadores relacionais que podem ser aplicadas na operação SELECT são: , , , , =, além dos operadores
booleanos: and, or, not.
A operação select é unária, ou seja, só pode ser aplicada a uma única relação. Não é possível aplicar a operação sobre
tuplas de relações distintas.
A operação PROJECT seleciona um conjunto determinado de colunas de uma relação. A forma geral de uma operação
PROJECT é:
<lista de atributos> (<nome da relação>)
A letra grega representa a operação PROJECT, <lista de atributos> representa a lista de atributos que o usuário
deseja selecionar e <nome da relação> representa a relação sobre a qual a operação PROJECT será aplicada.
As operações PROJECT e SELECT podem ser utilizadas de forma combinada, permitindo que apenas determinadas
colunas de determinadas tuplas possam ser selecionadas.
85
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
Por outro lado, a Consulta4 pode ser reescrita em duas outras expressões.
(EMPREGADO)
a) Consulta5 = salario < 2.500,00
b) Consulta6 = (CONSULTA5)
nome, depto., salario
A partir da expressão da Consulta6, teremos os seguintes resultados:
Como pode ser visto nas Tabelas 7.7a e 7.7b, o resultado das consultas acaba sendo o mesmo, porém é mais simples
utilizar a forma descrita na Consulta4.
Levando em consideração que as relações podem ser tratadas como conjuntos, podemos então aplicar um conjunto de
operações matemáticas sobre elas. Essas operações são: união () , intersecção () e diferença ().
Esse conjunto de operações não é unário, ou seja, pode ser aplicado sobre mais de uma tabela, porém, existe a necessidade
de as tabelas possuírem tuplas exatamente do mesmo tipo.
Suponhamos que uma consulta deseja selecionar todos os empregados que trabalham no departamento número 2 ou que
supervisionam empregados que trabalham no departamento número 2.
Em primeiro lugar, vamos primeiro selecionar todos os funcionários que trabalham no departamento número 2. Para
tanto, utilizaremos a seguinte expressão:
86
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
Em seguida, selecionaremos os supervisores dos empregados que trabalham no departamento número 2, utilizando a
seguinte expressão:
Consulta8 = rg_supervisor (CONSULTA7)
Com base na Consulta7, vamos buscar apenas o rg dos empregados selecionados, com base na seguinte expressão:
RG
20202020
30303030
40404040
Por fim, necessitamos unir as Tabelas 7.8b e 7.8c, obtendo o resultado final.
RG
20202020
30303030
40404040
10101010
87
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
O produto cartesiano é uma operação binária que combina todas as tuplas de duas tabelas. Diferente da operação união,
o produto cartesiano não exige que as tuplas das tabelas possuam exatamente o mesmo tipo. O produto cartesiano
permite então a consulta entre tabelas relacionadas utilizando uma condição de seleção apropriada. O resultado de um
produto cartesiano é uma nova tabela formada pela combinação das tuplas das tabelas sobre as quais se aplicou a
operação.
Suponhamos que uma consulta deseja encontrar todos os funcionários que desenvolvem projetos em Brasília. Para tanto,
utilizaremos a seguinte expressão:
Em seguida, necessitamos selecionar as tuplas resultantes que estão devidamente relacionadas, que são as que possuem o
mesmo valor em número do projeto e número e cuja localização seja ‘Brasília. Para tanto, utilizaremos a seguinte expressão:
Consulta12 = rg_empregado, número ((número_projeto = número) .and. (localização = ‘Brasília’)(CONSULTA11))
88
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
A operação junção atua de forma similar á operação produto cartesiano, porém, a tabela resultante conterá apenas
as combinações das tuplas que se relacionam de acordo com uma determinada condição de junção. A forma geral da
operação junção entre duas tabelas R e S é a seguinte:
R<condição de junção>S
Suponhamos que uma consulta deseja encontrar todos os funcionários que desenvolvem projetos em Brasília. Para tanto,
utilizaremos a seguinte expressão:
Consulta13 = EMPREGADOS/PROJETOSnúmero_projeto = número PROJETOS
A partir da expressão da consulta13 teremos os seguintes resultados:
Para finalizar o processo, necessitamos selecionar as tuplas onde a localização seja igual a Brasília.
Consulta14 = (CONSULTA13)
localização = ‘Brasília’
A partir da expressão da consulta14 teremos os seguintes resultados:
Conforme pode ser visto a partir da comparação dos resultados das Tabelas 7.9b e 7.10b, a operação de junção e o
produto cartesiano fornecem o mesmo resultado, porém a operação junção permite que o processamento seja mais simples.
89
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
b. RG CodDepartamento
Analisando a Tabela 7.11, sob a ótica das regras da FNBC, é possível perceber que a tabela em análise não atende a
todos os requisitos que a regra define, pois a chave RG não é uma superchave da tabela Empregado.
Para transformarmos a Tabela 7.11 na FNBC é necessário decompor a tabela em esquemas menores.
a. RG {Nome}
Sistemas de Banco de Dados
b. RG {CodDepartamento, Nome_Depto}
c. RG {Nome, CodDepartamento}
Como pode ser visto nas apresentadas, como RG passou a ser uma superchave, podemos dizer que as relações agora
atendem aos pressupostos da FNBC.
Diz-se que uma decomposição de R em R1 e R2 é sem perda (Lossless join) quando, ao juntarmos as tuplas de R1 com as
tuplas de R2 (igualando os atributos com o mesmo nome), obtivermos exatamente as tuplas de R.
90
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
4. 4ª e 5ª Formas Normais
Além das formas funcionais descritas, existem outras que representam um refinamento das formas anteriores.
Uma relação R está na quarta forma normal (4ªFN) se está na FNBC e para qualquer dependência multivalor não trivial
X Y, X é uma superchave.
Uma relação R está na quinta forma normal (5ªFN) se está na 4ªFN e não tem nenhuma dependência de junção. Uma
dependência de junção é a situação onde uma relação R e certas projeções R1, . . . ,Rn, diz-se que há uma dependência
de junção (de R em relação a R1, . . . ,Rn) se R pode ser reconstituída como a junção de R1, . . . ,Rn.
Apesar do refinamento que apresentam, as formas funcionais mais especializadas que a FNBC costumam ser raramente
utilizadas pois, além da dificuldade de aplicação, podem redundar em redução de performance. A Figura 7.3 mostra uma
representação esquemática das formas de normalização.
91
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
a. Os projetos Lógico e Funcional do Banco de Dados devem ser capazes de prever o volume de informações
armazenadas a curto, médio e longo prazo. Os projetos devem ter uma grande capacidade de adaptação
para os três casos mencionados.
b. Deve-se ter generalidade e alto grau de abstração de dados, possibilitando confiabilidade e eficiência no
seu armazenamento e permitindo a utilização de diferentes tipos de gerenciadores de dados por meio
de linguagens de consultas padronizadas.
c. Deve-se ter projeto com uma interface ágil e com uma “rampa ascendente” para propiciar aprendizado
suave ao usuário, no intuito de minimizar o esforço cognitivo;
d. Implementação de um projeto de interface compatível com múltiplas plataformas (UNIX, Windows NT,
Windows Workgroup).
e. Independência de Implementação da Interface em relação aos SGBDs que darão condições às operações
de armazenamento de informações (ORACLE, SYSBASE, INFORMIX, PADRÃO XBASE).
acesso ao SGBD é requerido, o programa estabelece uma conexão com o SGBD que está instalado no servidor.
92
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
Uma vez que a conexão é criada, o programa cliente pode se comunicar com o SGBD. Um padrão chamado de Conectividade
Base de Dados Aberta (Open DataBase Connectivity – ODBC) provê uma Interface para Programação de Aplicações
(API), que permite que os programas no lado cliente possam chamar o SGBD, desde que as máquinas clientes, como
o servidor, tenham o necessário software instalado. Muitos vendedores de SGBDs disponibilizam drivers específicos
para seus sistemas. Dessa maneira, um programa cliente pode se conectar a diversos SGBDRs e enviar requisições de
consultas e transações usando API, que são processados nos servidores. Após o processamento de uma chamada de
função (levando uma cadeia de caracteres ou programas armazenados), o resultado é fornecido pelo servidor de dados
por meio de tabelas em memória. Os resultados das consultas são enviados para o programa cliente, que pode processá-lo
ou visualizá-lo conforme a necessidade. O conjunto resposta para uma consulta pode ser uma tabela com zero, uma ou
múltiplas tuplas, dependendo de quantas linhas foram encontradas com o critério de busca.
Quando uma consulta retorna múltiplas linhas, é necessário declarar um “CURSOR” para processá-las. Um cursor é similar
a uma variável de arquivo ou um ponteiro de arquivo, que aponta para uma única linha (tupla) do resultado da consulta. Em
SQL os cursores são controlados por três comandos: OPEN, FETCH, CLOSE. O cursor é iniciado com o comando OPEN,
que executa a consulta, devolve o conjunto resultante de linhas e coloca o cursor para a posição anterior à primeira linha
do resultado da consulta. O comando FETCH, quando executado pela primeira vez, devolve a primeira linha nas variáveis
do programa e coloca o cursor para apontar para aquela linha. Subsequentes execuções do comando FETCH avançam o
cursor para a próxima linha no conjunto resultante e retornam a linha nas variáveis do programa. Quando a última linha é
processada, o cursor é desbloqueado com o comando CLOSE. Os cursores existem principalmente para que linguagens de
programação que não permitem abstração para conjunto de registros, como C, possam receber as linhas da resposta de
uma consulta SQL uma de cada vez. Com a utilização de “CURSORES”, apresentam-se esses dados como resultados das
consulta, por meio de itens que representam os elementos de interface com o usuário, atendendo os preceitos impostos
Pós-Graduação a Distância
pelos diferentes paradigmas possivelmente envolvidos. Com isso os resultados são mostrados utilizando o objeto padrão
da interface, disponíveis nas ferramentas de construção de interfaces. Dessa forma, o ciclo de busca de informação nos
mais variados servidores tem início e fim na interface com o usuário.
93
Teoria e Metodologia do Projeto de Banco de Dados Unidade III
É de fundamental importância que se construam aplicativos cujos projetos de interface sejam “ortogonais” aos projetos
de implementação de acesso aos servidores de dados. Na implementação de sistemas de informação, deve-se utilizar uma
arquitetura de base de dados relacional que seja independente de um determinado repositório de dados (gerenciadores
Access, Oracle, Sybase, Informix).
A Figura 8.2 ilustra a utilização de conversores genéricos tanto para interfaces quanto para os servidores de dados. Esses
conversores são construídos para padronizar o controle de compartilhamento de dados, independente da ferramenta de
interface ou do servidor de dados.
94
Unidade IV
Armazenamento de Dados, Indexação,
Processamento de Consultas e
Projeto Físico
Capítulo 9 – Algoritmos para Processamento e Otimização de Consultas
1. Processamento de Consultas
Um dos principais componentes de todo sistema de gerência de bancos de dados é o processador de consultas que, ao
receber uma consulta Q, prepara um plano de execução para Q, consistindo de operações de mais baixo nível, implementadas
pelo subsistema de armazenamento.
Diferentes técnicas podem ser usadas para processar, otimizar e executar consultas de alto nível, como as consultas feitas
usando SQL. Uma consulta deve ser examinada (por meio de um scanner), analisada (por meio de um parser) e validada.
O scanner identifica os componentes da linguagem (tokens) no texto da consulta, enquanto o parser checa a sintaxe
da consulta para determinar se essa foi formulada seguindo as regras de sintaxe (regras de gramática) da linguagem. A
consulta também é validada por meio da checagem de que todos os nomes de atributos e tabelas são válidos e corretos
semanticamente. Uma representação interna da consulta é então criada, geralmente usando-se uma estrutura de árvores
ou grafos, chamada de árvore de consulta ou grafo de consulta.
O SGBD deve, então, determinar uma estratégia de execução para recuperação dos resultados da consulta, dos arquivos
internos do banco de dados. Uma consulta geralmente possui várias possíveis estratégias de execução, e o processo
para escolher entre elas, umas das melhores, é conhecido como otimização de consultas.
Duas abordagens são usadas no processamento de consultas: utilização de regras heurísticas e estimativa de custo.
Usualmente, estas duas abordagens são combinadas na otimização de uma consulta. Portanto, a otimização envolve:
3. Otimização da Consulta.
95
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
A Figura 9.1 apresenta um esquema reduzido contendo as etapas para o processamento de consultas de alto nível.
OTIMIZADOR DE CONSULTAS
GERADOR DE CÓDIGO
Resultado da consulta
2. Otimização de Consultas
A otimização de consultas consiste na escolha de estratégias eficientes para o processamento de consultas, visando minimizar:
• o número de acessos à memória secundária (disco);
• Quando expressamos uma consulta, apenas informamos o resultado que desejamos obter, mas não o melhor
Sistemas de Banco de Dados
• As consultas expressas em uma linguagem de alto nível (SQL, por exemplo) são transformadas pelos sistemas
(SGBD) para poderem ser processadas.
• O processamento da consulta é a busca de uma expressão equivalente, que torne mais rápida a execução
dessa consulta (redução no tamanho das tabelas intermediárias e menor custo de acesso).
• O tempo gasto no processo de otimização deve ser menor do que o tempo de acesso sem a otimização.
96
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Suponhamos agora que se deseja executar uma consulta que busque o nome de todos os fornecedores que fornecem a peça
cujo código é “P2”. A expressão para executar a consulta pode ser:
SELECT nomef FROM fornecedores, embarques WHERE codf = codf and codp = “P2”;
a. Processamento Normal:
• Seleção das tuplas desse produto que satisfazem a condição (50 tuplas, por exemplo, com 6 atributos)
Existem duas técnicas básicas para otimização: as baseadas em heurísticas para a ordenação das operações de acesso
ao banco de dados que participarão da estratégia de acesso; e as que estimam sistematicamente o custo de estratégias
de execução diferentes e escolhem o plano de execução com o menor custo estimado.
A representação de consultas por meio de uma estrutura bem definida permite a transformação da consulta em uma série
de expressões equivalentes. Nessa etapa, são feitas transformações de uma expressão que representa uma consulta em
outras equivalentes mediante o uso de regras. Uma série de transformações baseadas em heurísticas podem ser aplicadas
em uma consulta para melhorá-la com relação ao seu desempenho de execução.
2. Combinar seleções com um produto cartesiano de forma a produzir uma junção natural.
3. Aplicar operações de projeção de forma antecipada (transferir ou inserir projeções, sempre que
necessário). Os únicos atributos que devem permanecer num esquema são aqueles que aparecem no
resultado ou aqueles necessários para o processamento de consultas subseqüentes.
4. Aplicar operações em grupo à medida que se percorre as tuplas (evita a geração de muitas tabelas
intermediárias).
97
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
5. Procurar subexpressões comuns em uma árvore (computá-las uma única vez e guardá-las em uma tabela
temporária).
• Operações unárias (seleção e projeção) são mais econômicas que operações binárias, pois trabalham sobre uma
única relação. Sempre que possível, devem ser antecipadas.
As expressões na álgebra relacional possuem várias formas de se apresentarem, assim como as expressões matemáticas.
Deve-se valer das propriedades de associatividade e comutatividade a fim de simplificar ao máximo tais consultas.
Cada SGBD implementa um certo número de rotinas de acesso a bancos de dados, as quais são escritas para implementar
as operações relacionais, tais como Seleção ou Junção ou combinações destas operações. Uma estratégia de execução é
usualmente implementada por meio da chamada de uma ou mais dessas rotinas de acesso.
O processo de otimização de planos de acesso gera planos de operadores para as versões das consultas resultantes do
processo de transformações lógicas, estabelece os custos de cada plano gerado e escolhe o de menor custo para processar
a consulta. Esse processo é geralmente dividido em três etapas: geração de planos, avaliação de custos e escolha de planos.
Essa etapa mapeia a consulta resultante das transformações lógicas em seqüências de operações denominadas planos de
acesso. Na geração de planos, o otimizador deve planejar suas estratégias de acesso, utilizando da melhor forma possível
os caminhos de acesso já existentes e estimar custos de processamento em termos de tamanho das tabelas e acessos
ao disco. Um Plano de acesso para uma consulta inclui não somente as relações operacionais a serem executadas, mas
também os índices a serem utilizados e a ordem em que as tuplas devem ser acessadas, bem como a ordem de execução
das operações.
As funções do custos são baseadas em estatísticas geradas pelo próprio SGBD. São apenas estimativas e, por não serem
exatas, correm o risco de gerar resultados dos quais a estratégia escolhida para otimização possa não ser a melhor. As
estatísticas são baseadas em informações armazenadas para utilização nessas funções, tais como o número de tuplas
da tabela, os índices secundários e suas chaves e a cardinalidade entre as tabelas.
98
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Em nível lógico, o banco de dados é descrito por um esquema conceitual global consistindo em um conjunto de objetos
lógicos; em nível físico, é descrito por uma série de esquemas internos, um para cada nó onde está armazenado; cada
esquema interno consiste em um conjunto de objetos físicos.
Os mapeamentos do esquema conceitual global para os esquemas internos definem a forma de distribuição do banco e
a correspondência entre objetos físicos e objetos lógicos. Esses mapeamentos poderão determinar que certos conjuntos
de objetos físicos armazenem cópias dos mesmos dados. Os objetos lógicos são manipulados por meio de comandos da
LMD e os objetos físicos mediante ações elementares.
Uma transação de banco de dados é uma unidade de interação com um SGBD ou com um sistema similar de processamento
de transações, que deve ser integralmente completada ou abortada. Um sistema de banco de dados deve assegurar as
propriedades de Atomicidade, Consistência, Isolamento e Durabilidade (ACID) para cada transação. Na prática, essas
propriedades são frequentemente relaxadas de certa forma para aperfeiçoar a execução e melhorar o desempenho do
sistema. Em alguns sistemas, transações são também vistas como Unidades Lógicas de Trabalho (LUW - Logical Unit
of Work). Em SGBDs, a capacidade de manipular transações enseja ao usuário garantir a integridade do banco de dados
mantida.
Essa garantia só pode ser alcançada devido a um conjunto de operações que têm origem em um estudo ligado em quatro
regras fundamentais para gerenciamento de dados em ambientes multiusuário. Essas regras, as propriedades ACD, estão
relacionadas ao seguinte.
• Atomicidade: É a propriedade que garante que todas as transações sejam indursívas em sua execução ou
nenhuma delas será.
• Consistência: O banco de dados deve estar em um estado legal, quando a transação se inicia e quando for
executada. Uma operação não deve violar as regras ou restrições de integridade do banco, que deve continuar
consistente.
• Isolamento: Mesmo que várias transações ocorram paralelamente, elas devem parecer isoladas uma das
outras. Isso significa que nenhuma operação fora da transação pode ver o dado em um estado intermediário
e nenhuma operação deve influenciar as outras. Resultados parciais de uma transação não podem ser vistos
por outras transações concorrentes.
• Durabilidade: Segurança em que se uma transação é finalizada com sucesso, seus resultados serão
persistentes e não serão desfeitos, a não ser por outra transação, mesmo se houver falhas no sistema após
a sua finalização.
A execução de uma transação é controlada pelo gerente de transações (GT) do nó onde foi submetida. Em nível lógico,
a execução de uma transação consiste em todas as operações ali executadas entre o começo e o fim da transação. É
Pós-Graduação a Distância
delimitada pelo.
• COMEÇO-DE-TRANSAÇÃO: o GT, ao interceptar este comando, cria uma área de trabalho para a transação;
comandos da LMD: consultas puras acessam objetos lógicos do banco de dados trazendo-os para a área
de trabalho, se já lá não estiverem. Atualizações sobre os objetos lógicos são mantidas na própria área de
trabalho, não se tornando visíveis de imediato a outras transações;
99
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
• FIM-DE-TRANSAÇÃO: invoca o protocolo bifásico para modificar todas as cópias de todos os objetos lógicos
afetados por atualizações executadas pela transação. Os valores dos objetos lógicos são obtidos da área de
trabalho.
Suponhamos que em cada nó participando do processamento da transação há uma área de trabalho da transação.
Todas as operações a nível lógico são sempre traduzidas em sequências de operações a nível físico. Mais precisamente,
uma execução de um grupo de transações gera, em cada nó, onde o banco está armazenado, uma sequência de ações
elementares, que presumimos de dois tipos:
• R(X) ação de leitura que recupera os valores dos objetos físicos, cujo nome está no conjunto X para a área de
trabalho local da transação que gerou a ação;
• W(X) ação de atualização que escreve os novos valores dos objetos físicos em X no banco de dados local.
Assim, a execução de um comando da LMD (que é uma operação em nível lógico) poderá gerar várias ações do tipo R(X)
para recuperar objetos físicos que ainda não estão na área de trabalho da transação. Porém, um comando da LMD nunca
gerará ações elementares do tipo W(X) pois o banco de dados não é alterado de imediato. Apenas quando o protocolo
bifásico atingir a segunda fase, ações elementares do tipo W(X) serão geradas para efetivar alterações nos bancos de
dados locais.
1. Controle de concorrência será feito em nível dos objetos físicos. Portanto, um mecanismo de controle de
concorrência deverá disciplinar a intercalação das ações elementares de diferentes transações em cada nó.
2. A semântica das transações não será levada em conta pelos mecanismos de controle de concorrência.
Como consequência, o controle de concorrência deverá depender apenas das sequências de operações de leitura/atualização
sobre os objetos físicos armazenados nos vários bancos de dados locais, ou seja, das sequências de operações R(X)
e W(X) executadas contra os bancos de dados locais. Uma execução concorrente E de um conjunto T de transações
pode, então, ser abstraída por um conjunto L= { L1 ,..., Ln }, onde Li é a sequência de ações elementares R(X) ou W(X)
executadas contra o banco de dados do nó i que foram geradas em E. O conjunto L é chamado de um escalonamento
global para T e a sequência Li é chamada do escalonamento local ao nó i para T. Usaremos Ri(X) ou Wi(X) para indicar
ações elementares R(X) ou W(X) executadas a favor da transação Ti em um escalonamento local.
Como exemplos desses conceitos, considere um banco de dados distribuído armazenado em dois nós. Os esquemas
internos são modelados por dois conjuntos de objetos físicos, D1 = { x1 ,y1 } e D2 = { x2 }, onde x1 e x2 armazenam
cópias dos mesmos dados.
Um escalonamento global para duas transações T1 e T2 nesse contexto poderia ser L = { L1 , L2 }, onde L1 = R1(y1)
R2(x1) W2(x1) W1(x1) e L2 = R1(x2) W1(x2) W2(x2)
Sistemas de Banco de Dados
• T2 lê o objeto físico x1
100
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Tanto a teoria de correção quanto o estudo do comportamento dos métodos de controle de concorrência serão baseados
em propriedades de escalonamentos globais.
2. Isolamento da Transação
O padrão SQL define quatro níveis de isolamento de transação em termos de três fenômenos que devem ser evitados
entre transações simultâneas.
• Dirty read 1 (leitura suja): situação onde uma transação lê dados escritos por uma transação simultânea não
efetivada (uncommitted).
• Nonrepeatable read 2 (leitura que não pode ser repetida): situação onde uma transação lê novamente dados
lidos anteriormente, e descobre que os dados foram alterados por outra transação (que os efetivou após ter
sido feita a leitura anterior).
• Phantom read 3 (leitura fantasma): situação onde uma transação executa uma segunda vez uma consulta
que retorna um conjunto de linhas que satisfazem uma determinada condição de procura, e descobre que
o conjunto de linhas que satisfazem a condição é diferente por causa de uma outra transação efetivada
recentemente.
Os quatro níveis de isolamento de transação, e seus comportamentos correspondentes, estão descritos na Tabela 10.1.
Quando uma transação processada sob o nível de isolamento Read Committed (lê efetivado), o comando SELECT enxerga
apenas os dados efetivados antes da consulta começar; nunca enxerga dados não efetivados, ou as alterações efetivadas
pelas transações simultâneas durante a execução da consulta. Entretanto, o SELECT enxerga os efeitos das atualizações
Pós-Graduação a Distância
anteriores executadas dentro da sua própria transação, mesmo que ainda não tenham sido efetivadas. Na verdade, o
1 Dirty read — A transação SQL T1 altera uma linha. Em seguida, a transação SQL T2 lê essa linha antes de T1 executar o comando COMMIT. Se depois T1 executar o comando
ROLLBACK, T2 terá lido uma linha que nunca foi efetivada e que, portanto, pode ser considerada como nunca tendo existido. (ISO-ANSI Working Draft) Foundation (SQL/
Foundation), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
2 Nonrepeatable read — A transação SQL T1 lê uma linha. Em seguida a transação SQL T2 altera ou exclui essa linha e executa o comando COMMIT. Se T1 tentar ler essa linha
novamente, pode receber o valor alterado ou descobrir que a linha foi excluída. (ISO-ANSI Working Draft) Foundation (SQL/Foundation), August 2003, ISO/IEC JTC 1/SC 32,
25-jul-2003, ISO/IEC 9075-2:2003 (E) (N. do T.)
3 Phantom read — A transação SQL T1 lê um conjunto de linhas N que satisfazem a uma condição de procura. Em seguida, a transação SQL T2 executa comandos SQL que geram
uma ou mais linhas que satisfazem a condição de procura usada pela transação T1. Se depois a transação SQL T1 repetir a leitura inicial com a mesma condição de procura, será
obtida uma coleção diferente de linhas. (ISO-ANSI Working Draft) Foundation (SQL/Foundation), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-2:2003 (E) (N.
do T.)
101
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
comando SELECT enxerga um instantâneo do banco de dados, como esse era no instante em que a consulta começou a
executar. Deve ser observado que dois comandos SELECT sucessivos podem enxergar dados diferentes, mesmo estando
dentro da mesma transação, se outras transações efetivarem alterações durante a execução do primeiro comando SELECT.
Os comandos UPDATE, DELETE e SELECT FOR UPDATE se comportam do mesmo modo que o SELECT para encontrar
as linhas de destino: somente encontram linhas de destino efetivadas até o momento do início do comando. Entretanto,
no momento em que foi encontrada, alguma linha de destino pode ter sido atualizada (ou excluída ou marcada para
atualização) por outra transação simultânea. Nesse caso, a transação que pretende atualizar fica aguardando a transação
de atualização que começou primeiro: efetivar ou desfazer. Se a transação de atualização que começou primeiro desfizer
as atualizações, então seus efeitos são negados e a segunda transação de atualização pode prosseguir com a atualização
da linha original encontrada. Se a transação de atualização que começou primeiro efetivar as atualizações, a segunda
transação de atualização ignora a linha caso tenha sido excluída pela primeira transação de atualização, senão tenta
aplicar sua operação na versão atualizada da linha. A condição de procura do comando (a cláusula WHERE) é avaliada
novamente para verificar se a versão atualizada da linha ainda corresponde à condição de procura. Se corresponder, a
segunda transação de atualização prossegue sua operação começando a partir da versão atualizada da linha.
Devido à regra acima, é possível um comando de atualização enxergar um instantâneo inconsistente: pode enxergar os
efeitos dos comandos simultâneos de atualização que afetam as mesmas linhas que está tentando atualizar, mas não
enxerga os efeitos desses comandos de atualização nas outras linhas do banco de dados. Esse comportamento torna o
Read Committed inadequado para os comandos envolvendo condições de procura complexas. Entretanto, é apropriado
para casos mais simples.
Exemplificando, consideremos a atualização do saldo bancário pela transação mostrada Figura 10.1.
BEGIN;
UPDATE conta SET saldo = saldo + 100.00 WHERE num_conta = 12345;
UPDATE conta SET saldo = saldo - 100.00 WHERE num_conta = 7534;
COMMIT;
Se duas transações desse tipo tentam mudar simultaneamente o saldo da conta 12345, é claro que se deseja que a
segunda transação comece a partir da versão atualizada da linha da conta. Uma vez que cada comando afeta apenas
uma linha predeterminada, permitir enxergar a versão atualizada da linha não cria nenhum problema de inconsistência.
Como no modo Read Committed, cada novo comando começa com um novo instantâneo incluindo todas as transações
efetivadas até esse instante; de qualquer modo, os próximos comandos na mesma transação vão enxergar os efeitos
das transações simultâneas efetivadas. O ponto em questão é se, dentro de um único comando, é enxergada uma visão
totalmente consistente do banco de dados.
O isolamento parcial da transação fornecido pelo modo Read Committed é adequado para muitas aplicações, e esse
Sistemas de Banco de Dados
modo é rápido e fácil de ser utilizado. Entretanto, para aplicações que efetuam consultas e atualizações complexas,
pode ser necessário garantir uma visão do banco de dados com consistência mais rigorosa que a fornecida pelo modo
Read Committed.
O nível Serializável fornece o isolamento de transação mais rigoroso. Esse nível emula a execução serial das transações,
como se todas as transações fossem executadas uma após a outra, em série, em vez de simultaneamente. Entretanto, as
aplicações que utilizam esse nível de isolamento devem estar preparadas para tentar executar novamente as transações,
devido a falhas de serialização.
102
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Quando uma transação está no nível serializável, o comando SELECT enxerga apenas os dados efetivados antes da
transação começar; nunca enxerga dados não efetivados ou alterações efetivadas durante a execução da transação
por transações simultâneas. Entretanto, o comando SELECT enxerga os efeitos das atualizações anteriores executadas
dentro da sua própria transação, mesmo que ainda não tenham sido efetivadas. É diferente do Read Committed, porque
o comando SELECT enxerga um instantâneo do momento de início da transação, e não do momento de início do comando
corrente dentro da transação. Portanto, comandos SELECT sucessivos dentro de uma mesma transação sempre enxergam
os mesmos dados.
Os comandos UPDATE, DELETE e SELECT FOR UPDATE se comportam do mesmo modo que o comando SELECT para
encontrar as linhas de destino: somente encontram linhas de destino efetivadas até o momento do início da transação.
Entretanto, alguma linha de destino pode ter sido atualizada (ou excluída ou marcada para atualização) por outra transação
simultânea no momento em que foi encontrada. Nesse caso, a transação serializável aguarda a transação de atualização
que começou primeiro efetivar ou desfazer as alterações. Se a transação que começou primeiro desfizer as alterações,
então seus efeitos são negados e a transação serializável pode prosseguir com a atualização da linha original encontrada.
Porém, se a transação que começou primeiro efetivar (e realmente atualizar ou excluir a linha, e não apenas selecionar
para atualização), então a transação serializável é cancelada e é apresentada uma mensagem de erro, pois uma transação
serializável não pode alterar linhas alteradas por outra transação após a transação serializável ter começado.
Quando a aplicação receber essa mensagem de erro deverá interromper a transação corrente e tentar executar novamente
toda a transação a partir do início. Da segunda vez em diante, a transação passa a enxergar a alteração efetivada
anteriormente como parte da sua visão inicial do banco de dados e, portanto, não existirá conflito lógico em usar a nova
versão da linha como ponto de partida para atualização na nova transação.
Deve ser observado que somente as transações que fazem atualizações podem precisar de novas tentativas; as transações
somente para leitura nunca estão sujeitas a conflito de serialização.
O modo serializável fornece uma garantia rigorosa que cada transação enxerga apenas visões totalmente consistentes do
banco de dados. Entretanto, a aplicação deve estar preparada para executar novamente a transação quando atualizações
simultâneas tornarem impossível sustentar a ilusão de uma execução serial. Como o custo de refazer transações complexas
pode ser significativo, esse modo é recomendado somente quando as transações, efetuando atualizações, contenham
lógica suficientemente complexa a ponto de produzir respostas erradas no modo Read Committed. Habitualmente, o
modo serializável é necessário quando a transação executa vários comandos sucessivos que necessitam enxergar visões
idênticas do banco de dados.
3. Bloqueio Explícito
Diversos SGBDs, baseados na linguagem SQL, fornecem vários modos de bloqueio para controlar o acesso simultâneo
aos dados nas tabelas. A maioria dos comandos SQL obtém, automaticamente, bloqueios nos modos apropriados para
garantir que as tabelas referenciadas não serão excluídas ou alteradas de forma incompatível enquanto o comando
estiver executando. Por exemplo, o comando ALTER TABLE não pode executar simultaneamente com outras operações
na mesma tabela.
Pós-Graduação a Distância
Os nomes dos modos de bloqueio são históricos pois, de alguma forma, os nomes refletem a utilização típica de cada
modo de bloqueio — mas as semânticas são todas as mesmas. A única diferença real entre um modo de bloqueio e
outro é o conjunto de modos de bloqueio que cada um conflita. Duas transações não podem obter bloqueios com modos
conflitantes na mesma tabela ao mesmo tempo (Entretanto, uma transação nunca conflita consigo mesma. Por exemplo,
pode obter o bloqueio ACCESS EXCLUSIVE e posteriormente obter o bloqueio ACCESS SHARE na mesma tabela). Podem
ser obtidos simultaneamente modos de bloqueio não conflitantes por muitas transações. Em particular, deve ser observado
103
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
que alguns modos de bloqueio são autoconflitantes. Por exemplo, o modo de bloqueio ACCESS EXCLUSIVE não pode ser
obtido por mais de uma transação ao mesmo tempo, enquanto outros não são autoconflitantes. Por exemplo, o modo de
bloqueio ACCESS SHARE pode ser obtido por várias transações ao mesmo tempo. Uma vez obtido, o modo de bloqueio
permanece até o fim da transação.
• ROW SHARE: Conflita com os modos de bloqueio EXCLUSIVE e ACCESS EXCLUSIVE. O comando SELECT
FOR UPDATE obtém o bloqueio nesse modo na(s) tabela(s) de destino (além do bloqueio no modo ACCESS
SHARE para as demais tabelas referenciadas mas não selecionadas FOR UPDATE).
• ROW EXCLUSIVE: Conflita com os modos de bloqueio SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e
ACCESS EXCLUSIVE. Os comandos UPDATE, DELETE e INSERT obtêm esse modo de bloqueio na tabela de
destino (além do modo de bloqueio ACCESS SHARE nas outras tabelas referenciadas). Em geral, este modo
de bloqueio é obtido por todos os comandos que alteram os dados da tabela.
• SHARE UPDATE EXCLUSIVE: Conflita com os modos de bloqueio SHARE UPDATE EXCLUSIVE, SHARE,
SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Este modo protege a tabela contra alterações
simultâneas no esquema e a execução do comando VACUUM. Obtida pelo comando VACUUM (sem a opção
FULL).
• SHARE: Conflita com os modos de bloqueio ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW
EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Esse modo protege a tabela contra alterações simultâneas
nos dados. Obtido pelo comando CREATE INDEX.
• SHARE ROW EXCLUSIVE: Conflita com os modos de bloqueio ROW EXCLUSIVE, SHARE UPDATE
EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Esse modo de bloqueio
não é obtido automaticamente por nenhum comando do PostgreSQL.
• EXCLUSIVE: Conflita com os modos de bloqueio ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE,
SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS EXCLUSIVE. Esse modo permite apenas bloqueios
ACCESS SHARE simultâneos, ou seja, somente leituras da tabela podem prosseguir em paralelo com uma
transação que obteve esse modo de bloqueio. Esse modo de bloqueio não é obtido automaticamente por
nenhum comando do PostgreSQL.
• ACCESS EXCLUSIVE: Conflita com todos os modos de bloqueio (ACCESS SHARE, ROW SHARE, ROW
EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE e ACCESS
Sistemas de Banco de Dados
EXCLUSIVE). Esse modo garante que a transação que o obteve é a única acessando a tabela de qualquer
forma. Obtido pelos comandos ALTER TABLE, DROP TABLE, REINDEX, CLUSTER e VACUUM FULL. Esse é,
também, o modo de bloqueio padrão para o comando LOCK TABLE sem a especificação explícita do modo.
Dica 1: Somente o bloqueio ACCESS EXCLUSIVE bloqueia o comando SELECT (sem a cláusula FOR UPDATE).
104
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Além dos bloqueios em nível de tabela, existem os bloqueios no nível de linha. O bloqueio em nível de linha é obtido
automaticamente para uma linha específica quando a linha é atualizada (ou excluída ou marcada para atualização). O
bloqueio é mantido até a transação efetivar ou desfazer as alterações. Os bloqueios em nível de linha não afetam a
consulta aos dados; bloqueiam apenas escritas na mesma linha. Para obter um bloqueio em nível de linha sem, na verdade,
modificá-la, a linha deve ser selecionada por meio do comando SELECT FOR UPDATE. Deve ser observado que, após ser
obtido um bloqueio em nível de linha, a transação pode atualizar essa linha várias vezes sem medo de conflito.
De forma geral, os SGDs baseados em SQL não guardam em memória qualquer informação sobre as linhas alteradas,
portanto não existe limite de número de linhas bloqueadas de cada vez. Entretanto, o bloqueio de uma linha pode causar
escrita no disco; por exemplo, o comando SELECT FOR UPDATE altera as linhas selecionadas para marcá-las, ocasionando
escrita em disco.
Além dos bloqueios de tabela e de linha, também são utilizados bloqueios compartilhados e exclusivos no nível de página,
para controlar o acesso de leitura e escrita nas páginas da tabela no shared buffer pool. Esses bloqueios são liberados
imediatamente após a linha ser lida ou atualizada.
Normalmente os desenvolvedores de aplicação não precisam se preocupar com bloqueios em nível de página, sendo
mencionados somente para o assunto ficar completo.
3.3. Impasses
A utilização de bloqueios explícitos pode aumentar a probabilidade de acontecerem impasses (deadlocks), onde duas (ou
mais) transações mantêm bloqueios que a outra deseja. Por exemplo, se a transação 1 obtiver um bloqueio exclusivo
na tabela A e, depois, tentar obter um bloqueio exclusivo na tabela B, enquanto a transação 2 já possui um bloqueio
exclusivo na tabela B, e agora deseja obter um bloqueio exclusivo na tabela A, então nenhuma das duas transações
pode prosseguir. Nesse tipo de situação, é necessário que o SGBD detecte as situações de impasse, resolvendo-as,
interrompendo uma das transações envolvidas, permitindo que a(s) outra(s) prossiga(m). O ponto sensível desse tipo de
solução é saber exatamente qual transação será interrompida; é difícil prever, não se devendo confiar na previsão de
tratamento automático.
Deve ser observado que os impasses também podem ocorrer como resultado de um bloqueio no nível de linha, podendo
ocorrer mesmo que não se use bloqueios explícitos. Considere o caso onde existam duas transações simultâneas alterando
uma tabela. A primeira transação executa a instrução apresentada na Figura 10.2.
Esse comando obtém um bloqueio no nível de linha na linha com o número da conta especificado. Depois, a segunda
Pós-Graduação a Distância
105
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
O primeiro comando UPDATE é bem-sucedido ao obter o bloqueio no nível de linha na linha especificada e, prossegue,
atualizando a linha. Entretanto, o segundo comando UPDATE descobre que a linha a ser atualizada está bloqueada e, fica
aguardando a transação que obteve o bloqueio terminar. A transação 2, agora, está aguardando a transação 1 completar
para poder continuar. Agora, a transação 1 executa (Figura 10.4):
A transação 1 tenta obter um bloqueio no nível de linha na linha especificada, mas não pode: a transação 2 já possui esse
bloqueio. Portanto, fica aguardando a transação 2 terminar. Assim sendo, a transação 1 está bloqueada pela transação
2, e a transação 2 está bloqueada pela transação 1: uma condição de impasse. Nesse caso, é necessário que o SGBD
detecte essa situação e interrompa uma das transações.
Geralmente a melhor defesa contra os impasses é evitá-los, tendo certeza de que todas as aplicações que utilizam o banco
de dados obtêm bloqueios em vários objetos em uma ordem consistente. No exemplo anterior, se as duas transações
tivessem atualizado as linhas na mesma ordem, não teria ocorrido nenhum impasse. Deve-se garantir, também, que o
primeiro bloqueio obtido em um objeto em uma transação seja aquele com o modo mais alto que será necessário para
esse objeto. Se for impraticável verificar essa situação antecipadamente, então os impasses podem ser tratados em
tempo de execução tentando executar novamente as transações interrompidas pelos impasses.
Enquanto a situação de impasse não for detectada, uma transação em busca de um bloqueio no nível de tabela ou no nível
de linha ficará aguardando indefinidamente pela liberação dos bloqueios conflitantes. Isso significa que é uma péssima
idéia as aplicações manterem transações abertas por longos períodos de tempo (por exemplo, aguardando a entrada de
dados pelo usuário).
Para garantir a validade corrente de uma linha e protegê-la contra atualizações simultâneas, deve ser utilizado o comando
SELECT FOR UPDATE ou uma declaração LOCK TABLE apropriada. O comando SELECT FOR UPDATE bloqueia apenas
as linhas retornadas contra atualizações simultâneas, enquanto o LOCK TABLE bloqueia toda a tabela.
As verificações de validade globais requerem considerações extras. Por exemplo, uma aplicação bancária pode desejar
verificar se a soma de todos os créditos em uma tabela é igual à soma de todos os débitos em outra tabela, num momento
Sistemas de Banco de Dados
em que as duas tabelas estão sendo ativamente atualizadas. Comparar os resultados de dois comandos SELECT SUM(...)
sucessivos não funciona confiavelmente no modo Read Committed, porque o segundo comando, provavelmente, vai
incluir resultados de transações não contados pelo primeiro comando. Realizar as duas somas em uma mesma transação
serializável fornece uma imagem precisa dos efeitos das transações efetivadas antes do início da transação serializável
— mas pode ser legitimamente questionado se a resposta ainda era relevante na hora em que foi entregue.
Se a própria transação serializável introduziu algumas alterações antes de tentar efetuar a verificação de consistência,
o valor prático da verificação se torna ainda mais discutível, porque agora são incluídas algumas, mas não todas as
alterações ocorridas após o início da transação. Em casos como esse, uma pessoa cuidadosa pode desejar bloquear
106
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
todas as tabelas necessárias para a verificação, para obter uma imagem da situação atual acima de qualquer suspeita.
Um bloqueio no modo SHARE (ou superior) garante não haver alterações não efetivadas na tabela bloqueada, fora as
alterações efetuadas pela própria transação corrente.
Deve ser observado, também, que quando se depende de bloqueios explícitos para evitar alterações simultâneas, deve ser
utilizado o modo Read Committed ou, no modo serializável, tomar o cuidado de obter os bloqueios antes de executar os
comandos. Um bloqueio obtido por uma transação serializável garante que nenhuma outra transação alterando a tabela
está executando, mas se o instantâneo enxergado pela transação for anterior à obtenção do bloqueio, pode ser que seja
anterior a algumas alterações na tabela que agora estão efetivadas.
O instantâneo de uma transação serializável é, na verdade, tirado no início da sua primeira consulta ou comando de
alteração de dados (SELECT, INSERT, UPDATE ou DELETE) sendo, portanto, possível obter bloqueios explicitamente
antes do instantâneo ser tirado.
5. Bloqueio e Índices
Os vários tipos de índice são tratados como mostrado a seguir.
• Índices B-tree: São utilizados bloqueios no nível de página, compartilhados ou exclusivos, de curta duração,
para acesso de leitura/escrita. Os bloqueios são liberados imediatamente após cada linha do índice ser lida ou
inserida. Os índices B-tree fornecem a mais alta simultaneidade, sem condições de impasse.
• Índices GiST e R-tree: São utilizados bloqueios no nível de índice, compartilhados ou exclusivos, para acesso
de leitura/escrita. Os bloqueios são liberados após o comando terminar.
• Índices Hash: São utilizados bloqueios no nível de página compartilhados e exclusivos para acessos de
leitura/escrita. Os bloqueios são liberados após a página ser processada. Os bloqueios no nível de página
fornecem uma simultaneidade melhor que os bloqueios no nível de índice, mas podem ocorrer impasses.
Em resumo, o índice B-tree oferece o melhor desempenho para aplicações simultâneas; uma vez que também possui mais
funcionalidades do que o índice hash, é o tipo de índice recomendado para aplicações simultâneas que necessitam indexar
dados escalares. Para tratar dados não escalares, os índices B-tree obviamente não podem ser utilizados; nessa situação,
os que desenvolvem a aplicação devem estar cientes do desempenho relativamente pobre dos índices GiST e R-tree.
Pós-Graduação a Distância
107
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
1. Introdução
Existem algumas tarefas de manutenção que precisam ser realizadas regularmente para manter um servidor funcionando
sem problemas. É responsabilidade do administrador do banco de dados instalar os scripts apropriados, e verificar se a
execução está sendo bem-sucedida.
Uma tarefa de manutenção óbvia é a geração das cópias de segurança dos dados em períodos regulares. Sem uma cópia
de segurança recente, não há como fazer a recuperação após um desastre (falha de disco, incêndio, remoção por engano
de uma tabela crítica).
Outra tarefa de manutenção importante é a limpeza periódica do banco de dados, além do gerenciamento do arquivo de
registro (log).
2. Rotina de Limpeza
Cada SGBD possui um conjunto de comandos para efetuar rotinas de limpeza. No PostgreSQL o comando VACUUM é
utilizado para essa função e necessita ser executado regularmente para:
• recuperar o espaço em disco ocupado pelas linhas atualizadas e removidas.
A frequência e a abrangência das operações de VACUUM, realizadas devido aos motivos acima, variam dependendo
das necessidades da instalação. Portanto, os administradores de banco de dados devem compreender essas questões e
desenvolver uma estratégia de manutenção apropriada.
De forma geral, um comando UPDATE ou DELETE em uma linha não remove imediatamente a versão antiga da linha. Essa
abordagem é necessária para obter os benefícios do controle de simultaneidade multiversão. A versão da linha não pode
ser removida enquanto houver possibilidade de ser acessada por outras transações. Mas no final, uma versão de linha
desatualizada ou excluída não terá mais interesse para nenhuma transação. O espaço ocupado deve ser recuperado para
ser reutilizado pelas novas linhas, evitando um crescimento sem fim da necessidade de espaço em disco.
Obviamente, uma tabela que recebe atualizações ou exclusões frequentes necessita ser limpa com mais frequência que
Sistemas de Banco de Dados
A forma padrão encontra as versões antigas das linhas e torna seus espaços disponíveis para ser utilizado novamente
dentro da tabela, mas não faz muito esforço para diminuir o tamanho do arquivo da tabela e devolver o espaço em disco
para o sistema operacional.
No PostgreSQL, se for necessário devolver espaço em disco para o sistema operacional pode ser utilizado o comando
VACUUM FULL — mas qual é a vantagem de liberar espaço em disco que deverá ser alocado novamente em breve?
Execuções do comando VACUUM padrão com frequência moderada é uma abordagem melhor do que a execução do
comando VACUUM FULL com baixa frequência, para manutenção de tabelas muito atualizadas.
108
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
A prática recomendada para a maioria das instalações é agendar o comando VACUUM para todo o banco de dados uma
vez por dia, em horário de pouca utilização, suplementado por limpezas mais frequentes das tabelas muito atualizadas se
for necessário (Havendo vários bancos de dados em um agrupamento, não deve ser esquecido de limpar cada um deles;
o programa vacuumdb pode ser útil). Deve ser utilizado o VACUUM simples, e não o VACUUM FULL, para recuperação
rotineira de espaço.
O comando VACUUM FULL é recomendado para os casos onde se sabe que foi excluída a maior parte das linhas da
tabela e, portanto, o tamanho estável da tabela pode ser reduzido substancialmente pela abordagem mais agressiva do
comando VACUUM FULL.
Havendo uma tabela cujo conteúdo é excluído periodicamente, deve ser considerada a execução do comando TRUNCATE
em vez de utilizar DELETE seguido por VACUUM.
O planejador de comandos depende das informações estatísticas sobre o conteúdo das tabelas para poder gerar bons
planos para os comandos. Essas estatísticas são coletadas pelo comando ANALYZE, que pode ser chamado por si próprio
ou como um passo opcional do comando VACUUM. É importante que as estatísticas estejam razoavelmente precisas,
senão o desempenho do banco de dados poderá ser degradado por planos mal escolhidos.
Assim como a execução do comando VACUUM para recuperar espaço, atualizações frequentes das estatísticas são mais
úteis para tabelas muito atualizadas que para tabelas raramente atualizadas, mas mesmo nas tabelas muito atualizadas
pode não haver necessidade de atualizar as estatísticas, se a distribuição dos dados não mudar muito. Uma regra empírica
simples é pensar sobre quanto os valores mínimos e máximos das colunas da tabela mudam. Por exemplo, uma coluna
timestamp contendo a data e hora da atualização da linha terá um valor máximo aumentando constantemente na medida
em que forem atualizadas ou adicionadas linhas à tabela; esse tipo de coluna, provavelmente, precisa de atualizações
mais frequentes das estatísticas do que, digamos, uma coluna contendo URLs de páginas acessadas em sítios da Web. A
coluna URL pode ser modificada com a mesma frequência, mas a distribuição estatística de seus valores provavelmente
muda de forma relativamente lenta.
É possível executar o comando ANALYZE em tabelas específicas, e mesmo em colunas específicas da tabela. Portanto,
existe flexibilidade para atualizar algumas estatísticas com mais frequência que outras se for requerido pela aplicação.
Entretanto, na prática, a utilidade dessa funcionalidade é duvidosa.
A prática recomendada, para a maioria das instalações, é agendar a execução do comando ANALYZE para todo o banco
de dados uma vez por dia, em horário de pouca utilização; é útil sua combinação com a execução do comando VACUUM
todas as noites. Entretanto, nas instalações onde as estatísticas das tabelas mudam de forma relativamente lenta,
pode-se considerar que essa frequência seja demasiada, e que a execução do comando ANALYZE com uma frequência
mais baixa seja suficiente.
Dica 1: Embora possa não ser muito produtivo aumentar a frequência de execução do comando ANALYZE
por coluna, pode valer a pena fazer ajustes por coluna do nível de detalhe das estatísticas coletadas pelo
comando ANALYZE. Colunas que são muito utilizadas em cláusula WHERE, e que contêm uma distribuição
Pós-Graduação a Distância
de dados muito irregular, podem requerer um histograma dos dados com granulação mais fina que as demais.
Veja o comando ALTER TABLE SET STATISTICS.
3. Rotina de Reindexação
Em algumas situações vale a pena reconstruir índices periodicamente, utilizando o comando REINDEX. Existe, também,
a aplicação contrib/reindexdb que pode reindexar todo o banco de dados.
109
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Se for simplesmente direcionada a saída stderr do postmaster para um arquivo, haverá uma saída de registro, mas a
única maneira de truncar o arquivo de registro será parando e reiniciando o postmaster, o que pode ser adequado em
um ambiente de desenvolvimento, mas poucos ambientes de produção vão considerar esse comportamento aceitável.
Outra abordagem para gerenciar a saída do registro, apropriada para ambientes de produção, é enviar a saída para syslog
e deixar que algum programa cuide da rotação do registro. Se for desejado automatizar a rotação do registro, pode ser
configurado o programa logrotate para trabalhar com os arquivos de registro do syslog1.
Como para tudo que contém dados importantes, devem ser feitas cópias de segurança dos bancos de dados regularmente.
Embora o procedimento seja essencialmente simples, é importante possuir uma compreensão básica das técnicas e
princípios subjacentes.
Existem duas abordagens fundamentalmente diferentes para fazer cópia de segurança dos dados do PostgreSQL:
• Método SQL-dump.
5. Método SQL-dump
A ideia por trás do Método SQL-dump é gerar um arquivo texto contendo comandos SQL que, ao serem processados pelo
servidor, recriam o banco de dados no mesmo estado em que esse se encontrava quando o arquivo foi gerado.
O PostgreSQL disponibiliza o programa utilitário pg_dump para essa finalidade. A forma básica de utilização desse
programa é:
pg_dump nome_do_banco_de_dados > arquivo_de_saída
Conforme pode ser visto, o programa pg_dump escreve o seu resultado na saída padrão. Será visto abaixo como isso
pode ser útil.
O pg_dump é uma aplicação cliente normal do PostgreSQL (embora seja particularmente astuta). Isso significa que o
procedimento de cópia de segurança pode ser realizado a partir de qualquer hospedeiro remoto que possua acesso ao
banco de dados. Porém, deve ser lembrado que o pg_dump não opera com permissão especial. Em particular, é necessário
possuir acesso de leitura a todas as tabelas que se deseja fazer cópia de segurança. Portanto, na prática, quase sempre
Sistemas de Banco de Dados
Para especificar qual servidor de banco de dados o pg_dump deve se conectar devem ser utilizadas as opções de linha
de comando -h hospedeiro e -p porta. O hospedeiro padrão é o hospedeiro local, ou o que estiver especificado na variável
de ambiente PGHOST. De maneira semelhante, a porta padrão é indicada pela variável de ambiente PGPORT ou, na falta
dessa, pelo padrão de compilação.
1 Syslog é um mecanismo que permite que qualquer comando registre mensagens na console do sistema e/ou em um arquivo. O daemon syslogd recebe as mensagens dos comandos
e envia para o destino descrito no arquivo de configuração ( /etc/syslog.conf ). O syslogd daemon lê a configuração quando é inicializado e quando recebe um signal de hangup (
kill -HUP processo )
110
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Assim como qualquer outra aplicação cliente do PostgreSQL, o pg_dump se conecta por padrão ao banco de dados cujo
nome é igual ao nome do usuário corrente do sistema operacional. Para que seja outro, deve ser especificada a opção
-U, ou definida a variável de ambiente PGUSER. Não deve ser esquecido que as conexões do pg_dump estão sujeitas aos
mecanismos normais de autenticação de cliente.
As cópias de segurança criadas pelo pg_dump são consistentes internamente, ou seja, as atualizações feitas no banco
de dados enquanto o pg_dump está executando não estão presentes na cópia de segurança. O pg_dump não bloqueia
outras operações no banco de dados enquanto está executando (Exceto as operações que necessitam operar com modo
de bloqueio exclusivo, como o VACUUM FULL).
Dica 1: Quando o esquema do banco de dados é dependente dos OIDs (como chaves-estrangeiras, por exemplo)
deve-se instruir o pg_dump para que também inclua os OIDs. Para que isso seja feito, deve ser utilizada
a opção de linha de comando -o. Também, não são feitas cópias de segurança dos “objetos grandes” por
padrão. Se forem utilizados objetos grandes, deve ser vista a página de referência do programa pg_dump .
Dica 1: As cópias de segurança produzidas pelo pg_dump são relativas a template0. Isso significa que todas
as linguagens, procedimentos, etc., adicionados a template1, também serão incluídos na cópia de segurança
feita pelo pg_dump. Como resultado, se estiver sendo utilizado um banco de dados template1 personalizado,
ao ser feita a restauração deve ser criado um banco de dados vazio a partir de template0, conforme mostrado
no exemplo acima.
Pós-Graduação a Distância
O mecanismo mostrado acima não é cômodo nem apropriado para fazer a cópia de segurança de todo o agrupamento de
bancos de dados. Por esse motivo, é fornecido o programa pg_dumpall . O pg_dumpall faz a cópia de segurança de todos
os bancos de dados de um agrupamento, e também salva dados de todo o agrupamento, como os usuários e grupos. A
forma básica de utilização desse programa é:
pg_dumpall > arquivo_de_saída
111
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Na verdade, pode ser especificado qualquer nome de banco de dados existente para começar, mas se estiver sendo feita
a restauração em um agrupamento vazio, então template1 é a única escolha disponível. É sempre necessário possuir
acesso de superusuário do banco de dados para fazer a restauração de uma cópia de segurança gerada pelo pg_dumpall,
para poder restaurar as informações de usuário e de grupo.
Uma vez que o PostgreSQL permite a existência de tabelas maiores do que o tamanho máximo de arquivo do sistema
operacional, pode ser problemático fazer a cópia de segurança de uma tabela como essa em um arquivo, uma vez que
o arquivo resultante provavelmente será maior do que o tamanho máximo permitido pelo sistema operacional. Como o
pg_dump pode escrever na saída padrão, podem ser utilizadas as ferramentas padrão do Unix para superar esse possível
problema.
Pode ser utilizado o programa de compressão favorito como, por exemplo, o gzip.
pg_dump nome_do_banco_de_dados | gzip > nome_do_arquivo.gz
O comando split permite dividir a saída em blocos de tamanho aceitável para o sistema de arquivos subjacente. Por
exemplo, para fazer blocos de 1 megabyte:
pg_dump nome_do_banco_de_dados | split -b 1m - nome_do_arquivo
Restaurar com
createdb nome_do_banco_de_dados
cat nome_do_arquivo* | psql nome_do_banco_de_dados
Se o PostgreSQL foi construído em um sistema com a biblioteca de compressão zlib instalada, o formato de cópia de
segurança personalizado comprime os dados ao escrever o arquivo de saída. Produz cópias de segurança com tamanhos
semelhantes às produzidas, utilizando o gzip, mas tem a vantagem adicional de permitir a restauração seletiva das
tabelas. O comando abaixo gera a cópia de segurança do banco de dados, utilizando o formato de cópia de segurança
personalizado (custom dump format):
pg_dump -Fc nome_do_banco_de_dados > nome_do_arquivo
O formato de cópia de segurança personalizado não é um script para o psql, devendo ser restaurado pelo pg_restore.
Para obter detalhes devem ser vistas as páginas de referência do pg_dump e do pg_restore .
112
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
5.4. Precauções
O pg_dump (e consequentemente o pg_dumpall) possui algumas poucas limitações causadas pela dificuldade de reconstruir
certas informações a partir dos catálogos do sistema.
Especificamente, a ordem utilizada pelo pg_dump para escrever os objetos não é muito sofisticada. Isso pode causar problemas
como, por exemplo, quando são utilizadas funções como valor padrão de colunas. A única solução é reorganizar manualmente
a cópia de segurança. Se forem criadas dependências circulares no esquema, então haverá mais trabalho a ser feito.
Por motivo de compatibilidade com as versões anteriores, o pg_dump não faz cópia de segurança dos objetos grandes
por padrão. Para fazer cópia de segurança dos objetos grandes deve ser utilizado o formato de saída personalizado ou o
formato tar, e utilizada a opção -b do pg_dump. Para obter detalhes deve ser vista a página de referência do pg_dump.
O diretório contrib/pg_dumplo, da árvore do código fonte do PostgreSQL, também contém um programa que pode ser
utilizado para fazer cópias de segurança dos objetos grandes.
Entretanto, existem duas restrições que fazem com que esse método seja impraticável ou, pelo menos, inferior ao pg_dump:
1. O servidor de banco de dados deve estar parado para que se possa obter uma cópia de segurança
utilizável. Meias medidas, como impedir todas as conexões, não funcionam, porque sempre existe
alguma “buferização” em andamento. Por essa razão também não é aconselhável confiar em sistemas
de arquivo que dizem suportar “instantâneos consistentes” (consistent snapshots).É desnecessário
dizer que, também, é necessário parar o servidor antes de restaurar os dados.
2. Caso tenha se aprofundado nos detalhes da organização do sistema de arquivos do banco de dados,
poderá estar tentado a fazer cópias de segurança ou restauração de apenas algumas determinadas
tabelas ou bancos de dados a partir de seus respectivos arquivos ou diretórios. Isso não funciona,
porque as informações contidas nesses arquivos possuem apenas meia verdade. A outra metade está
nos arquivos de registro de efetivação pg_clog/*, que contêm o status de efetivação de todas as
transações. O arquivo da tabela somente possui utilidade com essa informação. É claro que também
não é possível restaurar apenas uma tabela e seus dados associados em pg_clog, porque isso torna
todas as outras tabelas do agrupamento de bancos de dados inúteis. Portanto, as cópias de segurança
do sistema de arquivos somente funcionam para a restauração completa de todo o agrupamento de
bancos de dados.
Uma abordagem alternativa para cópias de segurança do sistema de arquivos é fazer um “instantâneo consistente” do
diretório de dados, se o sistema de arquivos possuir essa funcionalidade (e se há confiança que foi implementado de
Pós-Graduação a Distância
forma correta). Esse tipo de instantâneo salva os arquivos do banco de dados em um estado onde o servidor de banco
de dados não foi parado de forma apropriada; portanto, quando o servidor de banco de dados é iniciado acessando um
diretório restaurado a partir de uma cópia de segurança desse tipo, considera que o servidor caiu e refaz o registro do
WAL. Isso não é um problema, mas deve-se estar atento a esse fato (e certifique-se de incluir os arquivos do WAL na
cópia de segurança).
Deve ser observado que a cópia de segurança do sistema de arquivos não será necessariamente menor que a do Método
SQL-dump. Ao contrário, é mais provável que seja maior; por exemplo, o pg_dump não necessita fazer cópia de segurança
dos índices, mas apenas dos comandos para recriá-los.
113
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
A administração dessa abordagem é mais complexa que a administração das abordagens anteriores, mas existem alguns
benefícios significativos:
• O ponto de partida não precisa ser uma cópia de segurança totalmente consistente. Toda inconsistência
interna na cópia de segurança é corrigida quando o WAL é refeito (o que não é muito diferente do que
acontece durante a recuperação de uma queda). Portanto, não é necessário um sistema operacional com
capacidade de tirar instantâneos, basta apenas o tar, ou outra ferramenta semelhante.
• Como pode ser reunida uma sequência indefinidamente longa de arquivos de segmento do WAL para serem
refeitos, pode ser obtida uma cópia de segurança contínua simplesmente continuando a fazer cópias dos
arquivos de segmento do WAL. Isso é particularmente útil para bancos de dados grandes, onde pode não ser
conveniente fazer cópias de segurança completas regularmente.
• Não existe nada que diga que as entradas do WAL devem ser refeitas até o fim. Pode-se parar de refazer
em qualquer ponto, e obter um instantâneo consistente do banco de dados como se tivesse sido tirado no
instante da parada. Portanto, essa técnica suporta a recuperação para um determinado ponto no tempo:
é possível restaurar voltando o banco de dados para o estado em que se encontrava a qualquer instante
posterior ao da realização da cópia de segurança base.
• Se outra máquina, carregada com a mesma cópia de segurança base do banco de dados, for alimentada
continuamente com a série de arquivos de segmento do WAL, será criado um sistema reserva a quente (hot
standby): a qualquer instante essa outra máquina pode ser ativada com uma cópia quase atual do banco de
dados.
Da mesma forma que o método de cópia de segurança no nível de sistema de arquivos simples, esse método suporta
apenas a restauração de todo o agrupamento de bancos de dados, e não a restauração de apenas um subconjunto desse.
Requer, também, grande volume de armazenamento de arquivos: a cópia de segurança base pode ser grande, e um sistema
carregado gera vários megabytes de tráfego para o WAL que precisam ser guardados. Ainda assim, é o método de cópia
de segurança preferido para muitas situações onde é necessária uma alta confiabilidade.
Para fazer uma recuperação bem-sucedida utilizando cópia de segurança em-linha, é necessária uma sequência contínua de
Sistemas de Banco de Dados
arquivos de segmento do WAL guardados, que venha desde, pelo menos, o instante em que foi feita a cópia de segurança
base do banco de dados. Para começar, deve ser configurado e testado o procedimento para fazer cópia dos arquivos de
segmento do WAL, antes de ser feita a cópia de segurança base do banco de dados. Assim sendo, primeiro será explicada
a mecânica para fazer cópia dos arquivos de segmento do WAL.
Em um sentido abstrato, a execução do sistema PostgreSQL produz uma sequência indefinidamente longa de entradas
no WAL. O sistema divide fisicamente essa sequência em arquivos de segmento do WAL, normalmente com 16 MB cada
114
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
(embora o tamanho possa ser alterado durante a construção do PostgreSQL). São atribuídos nomes numéricos aos arquivos
de segmento para refletir sua posição na sequência abstrata do WAL. Quando não é feita cópia dos arquivos de segmento
do WAL, normalmente o sistema cria apenas uns poucos arquivos de segmento e, depois, “recicla-os”, renomeando os
arquivos que não são mais de interesse com número de segmento mais alto. Assume-se não existir mais interesse em um
arquivo de segmento cujo conteúdo preceda o ponto de verificação anterior ao último, podendo, portanto, ser reciclado.
Quando é feita a cópia dos arquivos de segmento do WAL, deseja-se capturar o conteúdo de cada arquivo quando esse é
completado, guardando os dados em algum lugar antes do arquivo de segmento ser reciclado para ser reutilizado.
Dependendo da aplicação e dos periféricos disponíveis, podem haver muitas maneiras de “guardar os dados em algum
lugar”: os arquivos de segmento podem ser copiados para outra máquina usando um diretório NFS montado, podem ser
escritos em uma unidade de fita (havendo garantia que os arquivos poderão ser restaurados com seus nomes originais),
podem ser agrupados e gravados em CD, ou de alguma outra forma. Para que o administrador de banco de dados tenha a
máxima flexibilidade possível, o PostgreSQL tenta não assumir nada sobre como as cópias serão feitas. Em vez disso, o
PostgreSQL deixa o administrador escolher o comando a ser executado para copiar o arquivo de segmento completado para
o local de destino. O comando pode ser tão simples como cp, ou pode envolver um script complexo para o interpretador
de comandos — tudo depende do administrador.
O comando a ser executado é especificado por meio do parâmetro de configuração archive_command, que, na prática, é
sempre colocado no arquivo postgresql.conf. Na cadeia de caracteres do comando, todo %p é substituído pelo caminho
absoluto do arquivo a ser copiado, enquanto todo %f é substituído pelo nome do arquivo apenas. Se for necessário
incorporar o caractere % ao comando, deve ser escrito %%. A forma mais simples de um comando útil é algo como:
archive_command = ‘cp -i %p /mnt/servidor/dir_copias/%f </dev/null’
Esse comando irá copiar os arquivos de segmento do WAL, prontos para serem copiados, para o diretório /mnt/servidor/
dir_copias (Isso é um exemplo, e não uma recomendação, e pode não funcionar em todas as plataformas).
O comando para realizar a cópia é executado sob a propriedade do mesmo usuário que está executando o servidor
PostgreSQL. Como a série de arquivos do WAL contém efetivamente tudo que está no banco de dados, deve haver
certeza que a cópia está protegida contra olhos curiosos; por exemplo, colocando a cópia em diretório sem acesso para
grupo ou para todos.
É importante que o comando para realizar a cópia retorne o status de saída zero se, e somente se, for bem-sucedido. Ao
receber o resultado zero, o PostgreSQL assume que a cópia do arquivo de segmento do WAL foi bem-sucedida, e remove
ou recicla o arquivo de segmento. Entretanto, um status diferente de zero informa ao PostgreSQL que o arquivo não foi
copiado; serão feitas tentativas periódicas até ser bem-sucedida.
Geralmente o comando de cópia deve ser projetado de tal forma que não sobrescreva algum arquivo de cópia preexistente.
Essa é uma característica de segurança importante para preservar a integridade da cópia no caso de um erro do
administrador (tal como enviar a saída de dois servidores diferentes para o mesmo diretório de cópias). Aconselha-se a
testar o comando de cópia proposto para ter certeza que não sobrescreve um arquivo existente, e que retorna um status
diferente de zero nesse caso. Tem sido observado que cp -i faz isso corretamente em algumas plataformas, mas não em
outras. Se o comando escolhido não tratar esse caso corretamente por conta própria, deve ser adicionado um comando
Pós-Graduação a Distância
Ao projetar a configuração de cópia deve ser considerado o que vai acontecer quando o comando de cópia falhar repetidas
vezes, seja porque alguma funcionalidade requer intervenção do operador, ou porque não há espaço para armazenar a
cópia. Essa situação pode ocorrer, por exemplo, quando a cópia é escrita em fita e não há um sistema automático para
troca de fitas: quando a fita ficar cheia, não será possível fazer outras cópias enquanto não for trocada. Deve-se garantir
que qualquer condição de erro, ou solicitação feita a um operador humano, seja relatada de forma apropriada para que
115
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
a situação possa ser resolvida o mais rápido possível. Enquanto a situação não for resolvida, continuarão sendo criados
novos arquivos de segmento do WAL no diretório pg_xlog.
A velocidade do comando de cópia não é importante, desde que possa acompanhar a taxa média de geração de dados
para o WAL. A operação normal prossegue mesmo que o processo de cópia fique um pouco atrasado. Se o processo de
cópia ficar muito atrasado, vai aumentar a quantidade de dados perdidos caso ocorra um desastre. Significa, também,
que o diretório pg_xlog vai conter um número grande de arquivos de segmento que ainda não foram copiados, podendo,
inclusive, exceder o espaço livre em disco. Aconselha-se que o processo de cópia seja monitorado para garantir que
esteja funcionando da forma planejada.
Havendo preocupação em se poder recuperar até o presente instante, devem ser efetuados passos adicionais para garantir
que o arquivo de segmento do WAL corrente, parcialmente preenchido, também seja copiado para algum lugar. Isso é
particularmente importante no caso do servidor gerar pouco tráfego para o WAL (ou tiver períodos ociosos onde isso
acontece), uma vez que pode levar muito tempo até que o arquivo de segmento fique totalmente preenchido e pronto para
ser copiado. Uma forma possível de tratar essa situação é definir uma entrada no cron [1] que, periodicamente, talvez
uma vez por minuto, identifique o arquivo de segmento do WAL corrente e o guarde em algum lugar seguro. Então, a
combinação dos arquivos de segmento do WAL guardados, com o arquivo de segmento do WAL corrente guardado, será
suficiente para garantir que o banco de dados pode ser restaurado até um minuto, ou menos, antes do presente instante.
Atualmente esse comportamento não está presente no PostgreSQL, porque não se deseja complicar a definição de
archive_command requerendo que esse acompanhe cópias bem-sucedidas, mas diferentes, do mesmo arquivo do WAL. O
archive_command é chamado apenas para segmentos do WAL completados. Exceto no caso de novas tentativas devido
à falha, só é chamado uma vez para um determinado nome de arquivo.
Ao escrever o comando de cópia, deve ser assumido que os nomes dos arquivos a serem copiados podem ter comprimento
de até 64 caracteres, e que podem conter qualquer combinação de letras ASCII, dígitos e pontos. Não é necessário
recordar o caminho original completo (%p), mas é necessário recordar o nome do arquivo (%f).
Deve ser lembrado que embora a cópia do WAL permita restaurar toda modificação feita nos dados dos bancos de dados do
PostgreSQL, não restaura a alterações feitas nos arquivos de configuração (ou seja, nos arquivos postgresql.conf, pg_hba.
conf e pg_ident.conf), uma vez que esses arquivos são editados manualmente, em vez de por meio de operações SQL.
3. Utiliza SELECT pg_start_backup(‘rótulo’); onde rótulo é qualquer cadeia de caracteres que se deseje
usar para identificar unicamente essa operação de cópia de segurança (Uma boa prática é utilizar o
caminho completo de onde se deseja colocar o arquivo de cópia de segurança). A função pg_start_backup
cria o arquivo rótulo da cópia de segurança, chamado backup_label, com informações sobre a cópia de
segurança, no diretório do agrupamento. Para executar esse comando, não importa qual banco de dados
do agrupamento é usado para fazer a conexão. O resultado retornado pela função pode ser ignorado;
Sistemas de Banco de Dados
mas se for relatado um erro, esse deve ser tratado antes de prosseguir.
4. Realizar a cópia de segurança utilizando qualquer ferramenta conveniente para cópia de segurança do
sistema de arquivos, como tar ou cpio. Não é necessário, nem desejado, parar a operação normal do
banco de dados enquanto a cópia é feita.
116
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Não é necessário ficar muito preocupado com o tempo decorrido entre a execução de pg_start_backup e o início da
realização da cópia de segurança, nem entre o fim da realização da cópia de segurança e a execução de pg_stop_backup;
uns poucos minutos de atraso não vão criar nenhum problema. Entretanto, deve haver certeza que as operações são
realizadas sequencialmente, sem que haja sobreposição.
Deve haver certeza que a cópia de segurança inclui todos os arquivos sob o diretório do agrupamento de bancos de
dados (por exemplo, /usr/local/pgsql/data). Se estiverem sendo utilizados espaços de tabelas que não residem sob esse
diretório, deve-se ter o cuidado de incluí-los também (e ter certeza que a cópia de segurança guarda vínculos simbólicos
como vínculos, senão a restauração vai danificar os espaços de tabelas).
Entretanto, podem ser omitidos da cópia de segurança os arquivos sob o subdiretório pg_xlog do diretório do agrupamento.
Essa pequena complicação a mais vale a pena ser feita porque reduz o risco de erros na restauração. É fácil de ser feito
se pg_xlog for um vínculo simbólico apontando para algum lugar fora do agrupamento, o que é uma configuração comum
por razões de desempenho.
Para poder utilizar essa cópia de segurança base, devem ser mantidas por perto todas as cópias dos arquivos de segmento
do WAL gerados no momento ou após o início da mesma. Para ajudar a realizar essa tarefa, a função pg_stop_backup
cria o arquivo de histórico de cópia de segurança, que é armazenado imediatamente na área de cópia do WAL. Esse
arquivo recebe um nome derivado do primeiro arquivo de segmento do WAL, que é necessário possuir para fazer uso da
cópia de segurança.
Por exemplo, se o arquivo do WAL tiver o nome 0000000100001234000055CD, o arquivo de histórico de cópia de
segurança vai ter um nome parecido com 0000000100001234000055CD.007C9330.backup. A segunda parte do nome
do arquivo representa a posição exata dentro do arquivo do WAL, podendo normalmente ser ignorada.
Uma vez que o arquivo contendo a cópia de segurança base tenha sido guardado em local seguro, podem ser apagados
todos os arquivos de segmento do WAL com nomes numericamente precedentes a esse número. O arquivo de histórico
de cópia de segurança é apenas um pequeno arquivo texto. Contém a cadeia de caracteres rótulo fornecida à função
pg_start_backup, assim como as horas de início e fim da cópia de segurança. Se o rótulo for utilizado para identificar
onde está armazenada a cópia de segurança base do banco de dados, então basta o arquivo de histórico de cópia de
segurança para se saber qual é o arquivo de cópia de segurança a ser restaurado, no caso disso precisar ser feito.
Uma vez que é necessário manter por perto todos os arquivos de segmento do WAL copiados desde a última cópia de
segurança base, o intervalo entre essas cópias de segurança geralmente deve ser escolhido tendo por base quanto
armazenamento se deseja consumir para os arquivos do WAL guardados.
Também deve ser considerado quanto tempo se está preparado para despender com a restauração, no caso de ser
necessário fazer uma restauração — o sistema terá que refazer todos os segmentos do WAL, o que pode ser muito
demorado se tiver sido decorrido muito tempo desde a última cópia de segurança base.
Também vale a pena notar que a função pg_start_backup cria no diretório do agrupamento de bancos de dados um
arquivo chamado backup_label, que depois é removido pela função pg_stop_backup. Esse arquivo fica guardado como
parte do arquivo de cópia de segurança base. O arquivo rótulo de cópia de segurança inclui a cadeia de caracteres rótulo
fornecida para a função pg_start_backup, assim como a hora em que pg_start_backup foi executada, e o nome do
Pós-Graduação a Distância
arquivo de segmento inicial do WAL. Em caso de dúvida, é possível olhar dentro do arquivo de cópia de segurança base
e determinar com exatidão de qual sessão de cópia de segurança esse arquivo provém.
Também é possível fazer a cópia de segurança base enquanto o postmaster está parado. Nesse caso, obviamente não
podem ser utilizadas as funções pg_start_backup e pg_stop_backup, sendo responsabilidade do administrador controlar a
que cópia de segurança cada arquivo pertence, e até quanto tempo atrás os arquivos de segmento do WAL associados vão.
117
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Suponhamos que seja necessário recuperar a partir da cópia de segurança. O procedimento está mostrado abaixo:
1. Parar o postmaster, se estiver executando.
2. Copiar, se houver espaço para isso, todo o diretório de dados do agrupamento, e todos os espaços de
tabelas, para um lugar temporário, para o caso de necessidade. Deve ser observado que essa medida
de precaução requer que haja espaço no sistema suficiente para manter duas cópias do banco de
dados existente. Se não houver espaço suficiente, é necessário pelo menos uma cópia do conteúdo do
subdiretório pg_xlog do diretório de dados do agrupamento, porque pode conter arquivos de segmento
do WAL que não foram copiados quando o sistema parou.
3. Apagar todos os arquivos e subdiretórios existentes sob o diretório de dados do agrupamento, e sob os
diretórios raiz dos espaços de tabelas em uso.
4. Restaurar os arquivos do banco de dados a partir da cópia de segurança base. Deve-se tomar cuidado
para que sejam restaurados com o dono correto (o usuário do sistema de banco de dados, e não o
usuário root), e com as permissões corretas. Se estiverem sendo utilizados espaços de tabelas, deve
ser verificado se foram restaurados corretamente os vínculos simbólicos no subdiretório pg_tblspc/.
5. Remover todos os arquivos presentes no subdiretório pg_xlog; porque esses vêm da cópia de segurança
base e, portanto, provavelmente estão obsoletos. Se o subdiretório pg_xlog não fizer parte da cópia
de segurança base, então esse subdiretório deve ser criado, assim como o subdiretório pg_xlog/
archive_status.
6. Copiar para o diretório pg_xlog, arquivos de segmento do WAL, porventura existentes e que não foram
copiados para o diretório de cópias, mas que foram salvos no passo 2; é melhor copiá-los em vez de
movê-los, para que ainda existam arquivos não modificados, caso ocorra algum problema e o processo
tenha de ser recomeçado.
8. Iniciar o postmaster. O postmaster vai entrar no modo de recuperação e prosseguir lendo os arquivos do
WAL necessários. Após o término do processo de recuperação, o postmaster muda o nome do arquivo
recovery.conf para recovery.done (para impedir que entre novamente no modo de recuperação no caso
de uma queda posterior), e depois começa as operações normais de banco de dados.
9. Deve ser feita a inspeção do conteúdo do banco de dados para garantir que a recuperação foi feita
até onde deveria ser feita. Caso contrário, deve-se retornar ao passo 1. Se tudo correu bem, liberar o
acesso aos usuários retornando pg_hba.conf à sua condição normal.
A parte chave de todo esse procedimento é a definição do arquivo contendo o comando de recuperação, que descreve
Sistemas de Banco de Dados
como se deseja fazer a recuperação, e até onde a recuperação deve ir. Pode ser utilizado o arquivo recovery.conf.sample
(geralmente presente no diretório de instalação share) na forma de um protótipo1.
O único parâmetro requerido no arquivo recovery.conf é restore_command, que informa ao PostgreSQL como trazer de
volta os arquivos de segmento do WAL copiados. Como no archive_command, esse parâmetro é uma cadeia de caracteres
para o interpretador de comandos. Pode conter %f, que é substituído pelo nome do arquivo do WAL a ser trazido de volta,
e %p, que é substituído pelo caminho absoluto para onde o arquivo do WAL será copiado. Se for necessário incorporar o
caractere % ao comando, deve ser escrito %%. A forma mais simples de um comando útil é algo como:
1 O arquivo recovery.conf.sample está presente no diretório /src/backend/access/transam da distribuição do código fonte e do CVS. (N. do T.)
118
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
Esse comando irá copiar os arquivos de segmento do WAL previamente guardados a partir do diretório /mnt/servidor/
dir_copias. É claro que pode ser utilizado algo muito mais complicado, talvez um script que solicite ao operador a
montagem da fita apropriada.
É importante que o comando retorne um status de saída diferente de zero em caso de falha. Será solicitado ao comando
os arquivos do WAL cujos nomes não estejam presente entre as cópias; deve retornar um status diferente de zero quando
for feita a solicitação. Essa não é uma condição de erro. Deve-se tomar cuidado para que o nome base do caminho %p
seja diferente de %f; não deve ser esperado que sejam intercambiáveis.
Os arquivos de segmento do WAL que não puderem ser encontrados entre as cópias, serão procurados no diretório pg_xlog/;
isto permite que os arquivos de segmento recentes, ainda não copiados, sejam utilizados. Entretanto, os arquivos de
segmento que estiverem entre as cópias terão preferência sobre os arquivos em pg_xlog. O sistema não sobrescreve os
arquivos presentes em pg_xlog quando busca os arquivos guardados.
Normalmente, a recuperação prossegue por meio de todos os arquivos de segmento do WAL, portanto restaurando o banco
de dados até o presente momento (ou tão próximo quanto se pode chegar utilizando os segmentos do WAL). Mas se for
necessário recuperar até algum ponto anterior no tempo (digamos, logo antes do DBA júnior ter apagado a tabela principal
de transação de alguém), deve-se simplesmente especificar no arquivo recovery.conf o ponto de parada requerido. O ponto
de parada, conhecido como “destino da recuperação”, pode ser especificado tanto pela data e hora quanto pelo término
de um ID de transação específico. Até o momento em que este manual foi escrito, somente podia ser utilizada a opção
data e hora, pela falta de ferramenta para ajudar a descobrir com precisão o identificador de transação a ser utilizado.
Dica 1: O ponto de parada deve estar situado após o momento de término da cópia de segurança base (o
momento em que foi executada a função pg_stop_backup). A cópia de segurança não pode ser utilizada
para recuperar até um momento em que a cópia de segurança base estava em andamento (Para recuperar
até esse ponto, deve-se retornar para uma cópia de segurança base anterior e refazer a partir dessa cópia).
Essas definições somente podem ser feitas no arquivo recovery.conf, e são aplicadas apenas durante a recuperação. As
definições deverão ser definidas novamente nas próximas recuperações que se desejar realizar. As definições não podem
ser alteradas após a recuperação ter começado.
1. restore_command (string): O comando, para o interpretador de comandos, a ser executado para trazer
de volta os segmentos da série de arquivos do WAL guardados. Esse parâmetro é requerido. Todo %f
presente na cadeia de caracteres é substituído pelo nome do arquivo a ser trazido de volta das cópias,
e todo %p é substituído pelo caminho absoluto para onde o arquivo será copiado no servidor. Se for
necessário incorporar o caractere % ao comando, deve ser escrito %%. É importante que o comando
retorne o status de saída zero se, e somente se, for bem-sucedido. Será solicitado ao comando os
arquivos cujos nomes não estejam presentes entre as cópias; deve retornar um status diferente de zero
quando for feita a solicitação.
Pós-Graduação a Distância
119
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
diferente. As transações que serão recuperadas são aquelas que foram efetivadas antes (e opcionalmente
incluindo) da transação especificada. Somente pode ser especificado um entre recovery_target_xid e
recovery_target_time. O padrão é recuperar até o fim do WAL. O ponto de parada preciso também é
influenciado por recovery_target_inclusive.
7.3. Cronologias
A capacidade de restaurar um banco de dados para um determinado ponto anterior no tempo cria algumas complexidades
que são semelhantes às das narrativas de ficção científica sobre viagem no tempo e universos paralelos. Por exemplo,
na história original do banco de dados talvez tenha sido removida uma tabela importante às 5:15 da tarde de terça-feira.
Imperturbável, o administrador pega a cópia de segurança e faz uma restauração para o ponto no tempo 5:14 da tarde
de terça feira, e o sistema volta a funcionar. Nessa história do universo do banco de dados, a tabela nunca foi removida.
Mas suponha que mais tarde seja descoberto que essa não foi uma boa ideia, e que se deseja voltar para algum ponto
posterior da história original. Mas isso não poderá ser feito, porque quando o banco de dados foi posto em atividade
esse sobrescreveu alguns dos arquivos de segmento do WAL que levariam ao ponto no tempo onde agora quer se chegar.
Portanto, realmente é necessário fazer distinção entre a série de entradas no WAL geradas após a recuperação para um
ponto no tempo, e aquelas geradas durante a história original do banco de dados.
Para lidar com esses problemas, o PostgreSQL possui a noção de cronologias (timelines). Cada vez que é feita uma
recuperação no tempo anterior ao fim da sequência do WAL, é criada uma nova cronologia para identificar a série de
registros do WAL geradas após a recuperação (entretanto, se a recuperação prosseguir até o final do WAL, não é criada
uma nova cronologia: apenas se estende a cronologia existente). O número identificador da cronologia é parte dos
nomes dos arquivos de segmento do WAL e, portanto, uma nova cronologia não sobrescreve os dados do WAL gerados
pelas cronologias anteriores. É possível, na verdade, guardar muitas cronologias diferentes. Embora possa parecer uma
funcionalidade sem utilidade, muitas vezes é de grande valia. Considere a situação onde não se tem certeza absoluta de
até que ponto no tempo deve ser feita a recuperação e, portanto, devem ser feitas muitas tentativas de recuperação até
ser encontrado o melhor lugar para se desviar da história antiga. Sem as cronologias, esse processo em pouco tempo
cria uma confusão impossível de ser gerenciada. Com as cronologias, pode ser feita a recuperação até qualquer estado
anterior, inclusive os estados no desvio de cronologia abandonados posteriormente.
Toda vez que é criada uma nova cronologia, o PostgreSQL cria um arquivo de “história da cronologia”, que mostra de
Sistemas de Banco de Dados
que cronologia foi feito o desvio, e quando. Os arquivos de cronologia são necessários para permitir o sistema buscar
os arquivos de segmento do WAL corretos ao fazer a recuperação a partir de uma área de cópias que contém várias
cronologias. Portanto, esses arquivos são guardados na área de cópias como qualquer arquivo de segmento do WAL. Os
arquivos de cronologia são apenas pequenos arquivos-texto sendo, portanto, barato e apropriado mantê-los guardados
indefinidamente (ao contrário dos arquivos de segmento que são grandes). É possível, caso se deseje fazê-lo, adicionar
comentários aos arquivos de cronologia para fazer anotações personalizadas sobre como e porque foi criada uma
determinada cronologia. Esses comentários são muito úteis quando há um grande número de cronologias criadas como
resultado de experiências.
120
Armazenamento de Dados, Indexação, Processamento de Consultas e Projeto Físico Unidade IV
O comportamento padrão de recuperação é fazê-lo ao longo da cronologia, que era a cronologia corrente quando foi feita
a cópia de segurança base. Se for desejado executar a recuperação utilizando uma cronologia filha (ou seja, deseja-se
retornar para algum estado que foi gerado após uma tentativa de recuperação), é necessário especificar o identificador
da cronologia de destino no arquivo recovery.conf. Não é possível fazer a recuperação para um estado que foi um desvio
anterior à cópia de segurança base.
Pós-Graduação a Distância
121
Para (não) Finalizar
Ao chegarmos ao final da disciplina, esperamos que os conhecimentos aqui transcritos e os trabalhos desenvolvidos
tenham contribuído no sentido de incrementar suas habilidades no trato com Sistemas de Gerenciamento de Banco de
Dados, bem como para despertar para a importância do tema.
No intuito de aprimorarmos o nosso trabalho, solicitamos que sejam enviadas sugestões ou críticas sobre a disciplina
para o tutor.
Sistemas de Banco de Dados
122
Referências
CODD, E. F. A relational model of data for large shared data banks. Revista CACM volume = 6,1970
_____. Further normalization of the data base relational model, In: Rustin [1972], pg 33-64 (1972).
ELMASRI, R. Sistema de banco de dados - Fundamentos e Aplicações, 4. Ed. s/l: Pearson Education, s/d.
HEUSER, C. A. Projeto de banco de dados, 4. ed. Porto Alegre: Livros Didáticos, Porto Alegre, 2001
KORTH, H. F.; SILBERSCHATZ, A. Sistema de banco de dados. São Paulo: Makron Books, 1995.
KROENKE, D. M. Banco de dados – fundamentos, projeto e implementação. Rio de Janeiro: LTC, 1998.
MECENAS, I. Banco de dados: do modelo conceitual à implementação física. Rio de Janeiro: Alta Books, 2005.
NADEAU, T.; LIGHTSTONE, S.; TEOREY, T. Projeto e modelagem de bancos de dados, 4. Ed. Campus/Elsevier.
RAMALHO, J. A. A.. SQL: A Linguagem dos bancos de dados. São Paulo: Berkeley Brasil, 1999.
SUDARSHAN, S.; SILBERSCHATZ, A.; KORTH, F.H. Sistemas de banco de dados. 3. Ed. S. Paulo: Makron Books,
1999
TAKAI, O. K.; ITALIANO, I. C.; FERREIRA, J. E. Introdução a banco de dados. São Paulo: DCC/IME/USP, 2005.
Pós-Graduação a Distância
123
Apêndice I
A Tabela I.1 lista todos os termos (tokens) que são palavras-chave no padrão SQL. O padrão SQL faz distinção entre
palavras-chave reservadas e não reservadas. De acordo com o padrão, as reservadas são as únicas palavras-chave reais;
nunca são permitidas como identificadores. As não reservadas somente possuem significado especial em determinados
contextos; podem ser utilizadas como identificador em outros contextos. Em sua maior parte, as palavras-chave não
reservadas são, na verdade, nomes de tabelas e funções nativas especificadas pelo padrão SQL.
Essencialmente, o conceito de palavra-chave não reservada existe apenas para declarar a associação dessa palavra com
um significado predefinido em alguns contextos.
Existem algumas palavras-chave não reservadas que não podem ser utilizadas como nome de função ou de tipo de dado,
estando devidamente indicado. Em sua maioria, essas palavras representam funções nativas ou tipos de dado com sintaxe
especial. A função ou o tipo ainda está disponível, mas não pode ser redefinido pelo usuário. Na coluna “reservada”
estão os termos permitidos apenas como títulos de coluna utilizando “AS” e, talvez, em muito poucos outros contextos.
Algumas palavras-chave reservadas são permitidas como nome de função; isso também está indicado na tabela.
Como regra geral, se acontecerem erros indevidos do analisador em comandos contendo como identificador qualquer
uma das palavras-chave listadas, deve-se tentar colocar o identificador entre aspas para ver se o problema desaparece.
124
Apêndice I
BY reservada reservada
C não reservada não reservada
CACHE
CALL reservada
CALLED não reservada
CARDINALITY não reservada
CASCADE reservada reservada
CASCADED reservada reservada
CASE reservada reservada
CAST reservada reservada
CATALOG reservada reservada
CATALOG_NAME não reservada não reservada
CHAIN não reservada
CHAR reservada reservada
Pós-Graduação a Distância
125
Apêndice I
CONVERSION
CONVERT não reservada reservada
COPY
CORRESPONDING reservada reservada
COUNT não reservada reservada
CREATE reservada reservada
CREATEDB
CREATEUSER
126
Apêndice I
DESTROY reservada
DESTRUCTOR reservada
DETERMINISTIC reservada
DIAGNOSTICS reservada reservada
DICTIONARY reservada
DISCONNECT reservada reservada
DISPATCH não reservada
127
Apêndice I
128
Apêndice I
129
Apêndice I
M não reservada
MAP reservada
MATCH reservada reservada
MAX não reservada reservada
MAXVALUE
MESSAGE_LENGTH não reservada não reservada
MESSAGE_OCTET_LENGTH não reservada não reservada
MESSAGE_TEXT não reservada não reservada
130
Apêndice I
OF reservada reservada
OFF reservada
OFFSET
OIDS
OLD reservada
ON reservada reservada
ONLY reservada reservada
131
Apêndice I
PREORDER reservada
PREPARE reservada reservada
PRESERVE reservada reservada
PRIMARY reservada reservada
PRIOR reservada reservada
PRIVILEGES reservada reservada
PROCEDURAL
PROCEDURE reservada reservada
132
Apêndice I
SAVEPOINT reservada
SCALE não reservada não reservada
SCHEMA reservada reservada
SCHEMA_NAME não reservada não reservada
SCOPE reservada
SCROLL reservada reservada
SEARCH reservada
133
Apêndice I
STATEMENT reservada
STATIC reservada
STATISTICS
STDIN
STDOUT
STORAGE
STRICT
STRUCTURE reservada
134
Apêndice I
135
Apêndice I
136
Apêndice II
As expressões de valor são utilizadas em diversos contextos, como na lista de seleção do comando SELECT, como
novos valores das colunas nos comandos INSERT e UPDATE, e na condição de procura em vários comandos. Algumas
vezes, o resultado de uma expressão de valor é chamado de escalar, para distingui-lo do resultado de uma expressão de
tabela (que é uma tabela). As expressões de valor são, portanto, chamadas também de expressões escalares (ou mesmo
simplesmente de expressões). A sintaxe da expressão permite o cálculo de valores a partir de partes primitivas utilizando
operações aritméticas, lógicas, de conjunto e outras.
• Um construtor de matriz.
Existe outra expressão de valor entre parênteses, útil para agrupar sub-expressões e mudar precedências. Em acréscimo
a essa lista, existem diversas construções que podem ser classificadas como uma expressão, mas que não seguem
qualquer regra geral de sintaxe. Possuem, normalmente, a semântica de uma função ou de um operador. Um exemplo
é a cláusula IS NULL.
1. Referências à coluna
Uma coluna pode ser referenciada usando a forma correlação.nome_da_coluna, onde correlação é o nome de uma tabela,
Pós-Graduação a Distância
possivelmente qualificado pelo nome do esquema, ou definido por meio da cláusula FROM, ou uma das palavras-chave
NEW ou OLD (NEW e OLD somente podem aparecer nas regras de reescrita, enquanto os outros nomes de correlação
podem ser usados em qualquer declaração SQL). O nome da correlação e o ponto separador podem ser omitidos se o
nome da coluna for único entre todas as tabelas utilizadas no comando corrente.
137
Apêndice II
2. Parâmetros posicionais
É utilizada uma referência a um parâmetro posicional para indicar um valor fornecido externamente a uma declaração
SQL. Os parâmetros são utilizados na definição de funções SQL e de comandos preparados. Algumas bibliotecas cliente
também suportam a especificação de valores de dados, separado da cadeia de caracteres do comando SQL e, nesses
casos, os parâmetros são utilizados para fazer referência a valores de dados fora de linha. A forma de fazer referência
a um parâmetro é: $número
CREATE FUNCTION dept(text) RETURNS dept AS ‘SELECT * FROM dept WHERE nome = $1’ LANGUAGE SQL;
Nesse caso, $1 será substituído pelo primeiro argumento da função quando essa for chamada.
3. Índices
Se uma expressão produzir um valor do tipo matriz, então um elemento específico do valor matricial pode ser extraído
escrevendo:
expressão [índice]
Nesse caso, os colchetes [ ] devem aparecer literalmente. Cada índice é por si só uma expressão, que deve produzir um
valor inteiro.
Geralmente, a expressão matricial deve estar entre parênteses, mas os parênteses podem ser omitidos quando a expressão
a ser indexada é apenas a referência a uma coluna ou a um parâmetro posicional. Podem ser concatenados vários índices
quando a matriz original for multidimensional. Por exemplo:
minha_tabela.matriz_coluna[4]
minha_tabela.matriz_duas_dim[17][34]
$1[10:42]
(funcao_matriz(a,b))[42]
4. Escolha de campo
Se uma expressão produzir um valor do tipo composto (tipo linha), então pode-se extrair um campo específico da linha
escrevendo:
Sistemas de Banco de Dados
expressão.nome_do_campo
Geralmente, a expressão de linha deve estar entre parênteses, mas os parênteses podem ser omitidos quando a expressão
de seleção for apenas uma referência a tabela ou a um parâmetro posicional. Por exemplo,
minha_tabela.minha_coluna
$1.alguma_coluna
(funcao_de_linha(a,b)).col3
Portanto, uma referência à coluna qualificada é, na verdade, apenas um caso especial da sintaxe de seleção de campo.
138
Apêndice II
5. Chamadas de operador
Existem três sintaxes possíveis para chamada de operador:
• expressão operador expressão (operador binário-intermediário);
onde o termo operador segue as regras de sintaxe ou é uma das palavras-chave AND, OR ou NOT, ou é um nome de
operador qualificado na forma:
OPERATOR(esquema.nome_do_operador)
Quais são os operadores existentes, e se são unários ou binários, depende de quais operadores foram definidos pelo
sistema e pelo usuário.
6. Chamadas de função
A sintaxe para chamada de função é o nome da função (possivelmente qualificado pelo nome do esquema), seguido por
sua lista de argumentos entre parênteses:
função ([expressão [, expressão ... ]] )
7. Funções de agregação
Uma expressão de agregação representa a aplicação de uma função de agregação nas linhas selecionadas pela consulta.
Uma função de agregação reduz vários valores de entrada a um único valor de saída, tal como a soma ou a média dos
valores entrados. A sintaxe da expressão de agregação é uma das seguintes:
• nome_da_agregação (expressão);
• nome_da_agregação ( * ).
onde nome_da_agregação é uma agregação definida anteriormente (possivelmente qualificado pelo nome do esquema),
e expressão é qualquer expressão de valor que não contenha uma expressão de agregação.
Pós-Graduação a Distância
A primeira forma de expressão de agregação chama a função de agregação para todas as linhas de entrada onde a
expressão fornecida produz um valor não nulo (na verdade, é decisão da função de agregação ignorar ou não os valores
nulos — porém, todas as funções-padrão o fazem). A segunda forma é idêntica à primeira, porque ALL é o padrão. A
terceira forma chama a função de agregação para todos os valores distintos não nulos da expressão, encontrados nas
linhas de entrada. A última forma chama a função de agregação uma vez para cada linha de entrada, independentemente
do valor ser nulo ou não; como nenhum valor específico de entrada é especificado, geralmente é útil apenas para a função
de agregação count().
139
Apêndice II
Por exemplo, count(*) retorna o número total de linhas de entrada; count(f1) retorna o número de linhas de entrada, onde
f1 não é nulo; count(distinct f1) retorna o número de valores distintos não nulos de f1.
Uma expressão de agregação pode aparecer apenas na lista de resultados ou na cláusula HAVING do comando SELECT.
Seu uso é proibido nas outras cláusulas, tal como WHERE, porque essas cláusulas são avaliadas logicamente antes dos
resultados das agregações estarem formados.
Quando uma expressão de agregação aparece em uma subconsulta, normalmente a agregação é avaliada a partir das
linhas da subconsulta. Porém ocorre uma exceção quando o argumento da agregação contém apenas variáveis do nível
externo: a agregação então pertence ao nível externo mais próximo, sendo avaliada a partir das linhas dessa consulta.
A expressão de agregação como um todo é, então, uma referência externa para a subconsulta onde aparece, agindo
como uma constante em qualquer avaliação da subconsulta. A restrição de aparecer apenas na lista de resultados ou na
cláusula HAVING se aplica com respeito ao nível da consulta que a agregação pertence.
8. Conversões de tipo
Uma conversão de tipo (type cast) especifica a conversão de um tipo de dado em outro. O PostgreSQL aceita duas
sintaxes equivalentes para conversão de tipo:
CAST ( expressão AS tipo )
expressão::tipo
Quando a conversão é aplicada a uma expressão de valor de tipo conhecido, representa uma conversão em tempo de
execução. A conversão será bem sucedida apenas se estiver disponível uma operação de conversão de tipo adequada.
Deve ser observado que isso é sutilmente diferente da utilização de conversão com constantes. Uma conversão aplicada a
uma literal cadeia de caracteres sem adornos representa a atribuição inicial do tipo ao valor constante literal e, portanto,
será bem-sucedida para qualquer tipo (se o conteúdo do literal cadeia de caracteres possuir uma sintaxe válida para
servir de entrada para o tipo de dado).
Geralmente a conversão explícita de tipo pode ser omitida quando não há ambigüidade em relação ao tipo que a expressão
de valor deve produzir (por exemplo, quando é atribuída a uma coluna de tabela); o sistema aplica automaticamente a
conversão de tipo nesses casos. Entretanto, a conversão automática de tipo é feita apenas para as conversões marcadas
nos catálogos do sistema como “OK para aplicar implicitamente”. As outras conversões devem ser chamadas por meio
da sintaxe de conversão explícita. Essa restrição tem por finalidade impedir que aconteçam conversões surpreendentes
aplicadas em silêncio.
Também é possível especificar uma conversão de tipo utilizando a sintaxe na forma de função:
nome_do_tipo ( expressão )
Entretanto, somente funciona para os tipos cujos nomes também são válidos como nome de função. Por exemplo, double
precision não pode ser utilizado dessa maneira, mas a forma equivalente float8 pode. Também, os nomes interval, time e
timestamp somente podem ser utilizados dessa maneira se estiverem entre aspas, devido a conflitos sintáticos. Portanto, o
Sistemas de Banco de Dados
uso da sintaxe de conversão na forma de função pode ocasionar inconsistências, devendo ser evitada em novas aplicações.
9. Subconsultas escalares
Uma subconsulta escalar é um comando SELECT comum, entre parênteses, que retorna exatamente uma linha com uma
coluna. O comando SELECT é executado e o único valor retornado é utilizado na expressão de valor envoltória. É errado
utilizar uma consulta que retorne mais de uma linha ou mais de uma coluna como subconsulta escalar, porém, se durante
uma determinada execução a subconsulta não retornar nenhuma linha, não acontece nenhum erro: o resultado escalar
140
Apêndice II
é assumido como nulo. A subconsulta pode fazer referência a variáveis da consulta envoltória, as quais atuam como
constantes durante a avaliação da subconsulta.
Por exemplo, a consulta abaixo retorna a maior população de cidade de cada estado:
SELECT nome, (SELECT max(populacao) FROM cidades WHERE cidades.estado = estados.nome) FROM estados;
O tipo de dado do elemento da matriz é o tipo comum das expressões membro, determinado pela utilização das mesmas
regras das construções UNION e CASE.
Os valores matriz multidimensional podem ser construídos aninhando construtores de matriz. Nos construtores internos,
a palavra chave ARRAY pode ser omitida. Por exemplo, esses dois comandos produzem o mesmo resultado:
SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];
array
---------------
{{1,2},{3,4}}
(1 linha)
SELECT ARRAY[[1,2],[3,4]];
array
---------------
{{1,2},{3,4}}
(1 linha)
Uma vez que as matrizes multidimensionais devem ser retangulares, os construtores internos no mesmo nível devem
produzir submatrizes com dimensões idênticas. Os elementos construtores de matriz multidimensional podem ser qualquer
coisa que produza uma matriz do tipo apropriado, e não apenas uma construção sub-ARRAY. Por exemplo:
Também é possível construir uma matriz a partir do resultado de uma subconsulta. Nessa forma, o construtor de matriz é
escrito com a palavra chave ARRAY seguida por uma subconsulta entre parênteses, e não entre colchetes. Por exemplo:
141
Apêndice II
A subconsulta deve retornar uma única coluna. A matriz unidimensional produzida terá um elemento para cada linha no
resultado da subconsulta, com o tipo do elemento correspondendo ao da coluna de saída da subconsulta.
Além disso, se o resultado da expressão puder ser determinado avaliando apenas algumas de suas partes, então as outras
subexpressões podem nem ser avaliadas. Por exemplo, se for escrito
SELECT true OR alguma_funcao();
então alguma_funcao() não será (provavelmente) chamada. Esse é o mesmo caso de quando é escrito
SELECT alguma_funcao() OR true;
Deve ser observado que isso não é o mesmo que os “curtos circuitos” esquerda para direita de operadores booleanos
encontrados em algumas linguagens de programação.
Como conseqüência, não é bom utilizar funções com efeitos colaterais como parte de expressões complexas. É
particularmente perigoso confiar em efeitos colaterais, ou na ordem de avaliação nas cláusulas WHERE e HAVING, porque
essas cláusulas são reprocessadas inúmeras vezes como parte do desenvolvimento do plano de execução. As expressões
booleanas (combinações de AND/OR/NOT) nessas cláusulas podem ser reorganizadas em qualquer forma permitida pelas
leis da álgebra booleana.
Quando for essencial obrigar a ordem de avaliação, pode ser utilizada uma construção CASE. Por exemplo, essa é uma
forma não confiável para tentar evitar uma divisão por zero na cláusula WHERE:
SELECT ... WHERE x <> 0 AND y/x > 1.5;
A construção CASE utilizada dessa forma impede as tentativas de otimização devendo, portanto, ser utilizada
apenas quando for necessário (Nesse exemplo em particular, sem dúvida seria melhor evitar o problema escrevendo
y > 1.5*x).
Sistemas de Banco de Dados
142
Apêndice III
143
Apêndice III
144
Apêndice III
145