Notas de Aula Banco de Dados André Luís Duarte Sistema de Informação FEPI – 2014 Banco de Dados Sumário Capítulo 1 – Projeto Lógico de Banco de Dados .......................................................... 5 1.1 – Introdução – Sistema: Uma Visão Geral ............................................................ 5 1.2 – Modelagem Lógica de Sistemas .......................................................................... 7 1.3 – Banco de Dados – Conceitos ............................................................................... 8 1.4 – Sistemas de Banco de Dados e Modelos de Dados ............................................. 9 1.5 – Modelagem e seus objetivos ................................................................................ 9 Capítulo 2 – Modelo Conceitual .................................................................................. 11 Modelo Entidade-Relacionamento e Seus Conceitos ................................................. 11 2.1 – Abstração e Modelagem de Dados .................................................................... 11 2.2 – O Método Entidade-Relacionamento ................................................................ 12 2.3 Entidades e Conjuntos de Entidades ..................................................................... 13 2.4 – Atributos ............................................................................................................ 14 2.4.A – Atributos Simples e Compostos................................................................. 15 2.4.B – Atributos Multivalorados ........................................................................... 15 2.4.C – Atributos Opcionais ou Mandatário .......................................................... 16 2.4.D – Atributos Determinantes ou Identificadores .............................................. 16 2.5 – Relacionamentos e Classes de Relacionamentos............................................... 16 2.6 – Auto-Relacionamento ........................................................................................ 19 2.7 – Atributos de Relacionamentos ........................................................................... 21 2.8 – Relacionamentos Parciais e Totais .................................................................... 21 2.9 – Relacionamentos Múltiplos ............................................................................... 21 2.10 – Agregações ...................................................................................................... 22 2.11 – Generalização / Especialização ....................................................................... 25 2.12 – Chaves ............................................................................................................. 26 2.13 – Conjunto de Entidades Forte e Fraco .............................................................. 26 2.14 – Restrições de Mapeamento .............................................................................. 27 2.15 – Reduzindo o Diagrama E/R a tabelas .............................................................. 28 2.15.1 – Representação de Conjuntos de Entidades Fortes ................................... 28 2.15.2 – Representação de Conjuntos de Entidades Fracos .................................. 29 2.15.3 – Representação de Conjuntos de Relacionamentos ................................... 30 Capítulo 3 – Modelo Relacional .................................................................................. 32 3.1 – Introdução .......................................................................................................... 32 3.2 – Estrutura de Banco de Dados Relacionais ......................................................... 32 3.2.1 – Estrutura básica ......................................................................................... 32 3.2.2 – Esquema de Banco de Dados ..................................................................... 33 3.2.3 – Linguagens de Consulta ............................................................................. 36 3.3 – Álgebra Relacional ............................................................................................ 37 3.3.1 – Operações Fundamentais ........................................................................... 39 3.3.2 Definição Formal da Álgebra Relacional ..................................................... 47 3.3.3 – Operações Adicionais ................................................................................. 47 3.4 – Modificação no Banco de Dados com Álgebra Relacional ............................... 54 3.4.1 – Remoção ..................................................................................................... 54 3.4.2 – Inserção ...................................................................................................... 55 3.4.3 – Atualização ................................................................................................. 56 3.5 – Visões de Usuário .............................................................................................. 57 3.5.1 – Definição de Visão ..................................................................................... 58 3.5.2 – Atualizações com Visões e Valores Vazios ................................................. 59 André Luís Duarte 2 [email protected] Capítulo 4 – Linguagem Relacional Comercial ......................................................... 62 4.1 – Introdução .......................................................................................................... 62 4.2 – SQL.................................................................................................................... 62 4.2.1 – Histórico ..................................................................................................... 62 4.2.2 – Estrutura básica ......................................................................................... 63 4.2.3 – Operações de conjuntos e tuplas duplicadas ............................................. 64 4.2.4 – Operações com conjuntos........................................................................... 64 4.2.5 – Predicados e junções .................................................................................. 66 4.2.6 – Pertinência a conjuntos .............................................................................. 68 4.2.7 – Variáveis tupla............................................................................................ 69 4.2.8 – Comparação de conjuntos .......................................................................... 70 4.2.9 – Teste de relações vazias ............................................................................. 71 4.2.10 – Ordenação da exibição de tuplas ............................................................. 73 4.2.11 – Funções agregadas ................................................................................... 73 4.2.12 – A potência de SQL .................................................................................... 75 4.2.13 – Modificação do Banco de Dados.............................................................. 75 4.2.13.1 – Remoção (delete) ................................................................................... 76 4.2.13.2 – Inserção (insert)..................................................................................... 77 4.2.13.2 – Atualização (update) .............................................................................. 78 4.2.14 – Valores Vazios .......................................................................................... 79 4.2.15 – Visões ........................................................................................................ 80 4.2.16 – Definição de Dados .................................................................................. 81 Capítulo 5 – Restrições de Integridade ....................................................................... 83 5.1 – Introdução .......................................................................................................... 83 5.2 – Restrições de domínio ....................................................................................... 83 5.2.1 – Tipos de Domínio ........................................................................................... 83 5.2.2 – Tipos de domínios em SQL ......................................................................... 84 5.2.3 – Valores vazios ............................................................................................. 84 5.3 – Integridade Referencial...................................................................................... 85 5.3.1 – Conceitos básicos ....................................................................................... 85 5.3.2 – Integridade Referencial em SQL ................................................................ 86 5.4 – Asserções ........................................................................................................... 87 5.5 – Gatilhos (TRIGGERS) ...................................................................................... 88 Capítulo 6 – Normalização (ou normatização) .......................................................... 90 6.1 – Introdução .......................................................................................................... 90 6.2 – Conceitos ........................................................................................................... 91 6.2.1 Revisão dos conceitos relevantes .................................................................. 93 6.2.2 Dependência Funcional (DF) ........................................................................ 93 6.2.2.1 Trivialidade ................................................................................................ 95 6.2.2.2 Transitividade ............................................................................................. 95 6.2.2.3 Dependência funcional irredutível à esquerda .......................................... 95 6.2.2.4 Anomalias de atualização........................................................................... 96 6.2.2 Decomposição sem perdas ............................................................................ 98 6.2.3 Junção (Join) ................................................................................................. 99 6.2.4 Projeções ....................................................................................................... 99 6.3 Importância da Normalização ............................................................................... 99 6.4 Normalização estudo de caso ............................................................................... 99 6.4.1 1ª Forma normal (1FN) ............................................................................... 101 6.4.1.1 Normalização e atributos compostos ....................................................... 102 6.4.2 2ª Forma Normal (2FN) .............................................................................. 103 3 André Luís Duarte Banco de Dados 6.4.3 3ª Forma Normal (3FN) .............................................................................. 105 Observações sobre as anomalias ......................................................................... 107 5.4.3.4 Forma Normal de Boyce/Codd (BCNF) ................................................... 108 6.5 Normalização e integridade ................................................................................ 108 6.6 Desnormalização ................................................................................................ 108 Bibliografia .................................................................................................................. 111 André Luís Duarte 4 [email protected] Capítulo 1 – Projeto Lógico de Banco de Dados 1.1 – Introdução – Sistema: Uma Visão Geral Um Banco de Dados (BD) consiste em uma coleção de dados que possuem algum relacionamento entre si. O conjunto de software e “hardware” utilizados a fim de prover o acesso seguro e manipulação dos dados do BD, é conhecidos como Sistema Gerenciador de Banco de Dados (SGBD). O conjunto formado pelo Banco de Dados e o Sistema Gerenciador de Banco de Dados, é comumente chamado de Sistema de Banco de Dados (SBD). O objetivo principal da utilização de um sistema de banco de dados é prover um ambiente seguro e eficiente na manipulação das informações dos sistemas clientes, podendo ser tanto o armazenamento quanto à recuperação destas informações. Um banco de dados possui as seguintes características: é uma coleção lógica e coerente de dados que possuem um significado intrínseco; é projetado, construído e populado com dados que tenham um propósito específico; representa algum aspecto (parte) do mundo real; TABELAS LÓGICAS INFORMAÇÕES PARA O USUÁRIO BANCO DE DADOS (Arquivo Físico) Figura1.1 – Representação física de um banco de dados Uma característica importante da abordagem Banco de Dados é que os SGBD mantêm não somente os dados, mas também a forma como os mesmos se encontram armazenados (estrutura de cada arquivo, tipo e o formato de armazenamento de cada dado, restrições, etc) em um local chamado catálogo do SGBD. Estas informações são 5 André Luís Duarte Banco de Dados conhecidas como “meta dados” e juntamente com os dados em si provêm uma descrição completa do banco de dados. No processamento tradicional de arquivos isto não ocorre, já que a estrutura de armazenamento e manipulação deve estar descrita no próprio código do programa de manipulação. Com isto, uma alteração na estrutura de armazenamento ou no próprio dado, vai obrigar a alteração de todo o código responsável pela manipulação deste dado. Programas de Aplicação / Consulta Software para processar manipulação Sistema de Banco de Dados SGBD Software de Acesso aos Dados Meta Dados Dados Figura 1.2 - Um ambiente de Sistema de Banco de Dados A adoção ou não de um sistema de banco de dados deve levar em conta algumas questões. Podemos citar algumas vantagens e desvantagens na utilização de um SBD: Vantagens: - Controle de redundância: em um sistema tradicional de arquivos, o armazenamento e processamento de informações redundantes geram uma perda na qualidade, no tempo e na facilidade de atualizações destes sistemas; - Compartilhamento de dados: um SGBD pode fornecer acesso concorrente aos dados do sistema, permitindo que várias aplicações acessem aos dados simultaneamente; - Restrição a acessos não autorizados: um SGBD pode possuir sub- sistemas que controlem o acesso não autorizado aos dados armazenados; André Luís Duarte 6 [email protected] - Tolerância a falhas: um Sistema de Banco de Dados pode fornecer recursos rápidos e seguros para tratar possíveis falhas tanto de software quanto de hardware, garantindo assim a integridade das informações; Desvantagens: - Alto investimento inicial: muitas vezes o custo gerado na adoção de um Sistema de Banco de Dados pode não ser atrativo a fim de substituir um sistema de arquivos tradicional; - Sobrecarga no gerenciamento: normalmente ocorre uma sobrecarga na provisão de controle de segurança, controle de concorrência, recuperação e integração de funções; - Necessidade de treinamento e aperfeiçoamento de profissionais: este item é essencial, pois de nada adianta adotarmos um sistema complexo e moderno e se não temos um administrador capacitado para sua manipulação; O desenvolvimento correto do projeto de um sistema de banco de dados que atenda as exigências de segurança e eficiência, é talvez, a parte principal em projetos de empresas ligadas ao desenvolvimento de sistemas, pois geram grandes custos em casos de revisão e correção. Para que o desenvolvimento possa ocorrer de forma segura, é necessário que se adote e utilize metodologias e técnicas que minimizem custos e gastos gerados por falhas no projeto. 1.2 – Modelagem Lógica de Sistemas A modelagem lógica de sistemas consiste no encadeamento lógico dos componentes do sistema com a finalidade de prover ao analista, ferramentas para análise e entendimento do funcionamento real do sistema modelado. Esta modelagem é um importante meio de comunicação entre a equipe de analistas e o cliente para que toda a estrutura lógica do sistema seja “mapeada” de forma correta, possibilitando assim a identificação e correção de erros e mal entendidos em fases anteriores ao desenvolvimento. 7 André Luís Duarte Banco de Dados CAA CBB ABC AAA BBB CCC ABC BAA CBC CCC AAA BBB Figura 1.3 – Necessidade da modelagem na comunicação A modelagem lógica abrange todos os elementos existentes em um SGBD (softwares, redes, discos, estruturas, dados, meta dados, etc). 1.3 – Banco de Dados – Conceitos Banco de Dados: é o arquivo físico, em dispositivos periféricos, onde estão armazenados os dados de um ou mais sistemas a fim de serem manipulados pelo sistema cliente. Sistema Gerenciador de Banco de Dados: é o conjunto de software e hardware utilizados no gerenciamento (armazenamento e recuperação) dos dados no banco de dados. Dado: é o valor do campo quando armazenado no banco de dados. (Ex. o valor do campo “Nome do Cliente” para quem se está fazendo a entrada dos dados). Conteúdo do Campo: é o valor do campo armazenado no banco de dados. (Ex. o valor do campo “Nome do Cliente”, sem ser, momentaneamente utilizado, armazenado no banco de dados). Informação: é o valor que este campo representa para as atividades da empresa. (Ex. qual o nome dos clientes localizados em Itajubá. A resposta a esta consulta é a informação). André Luís Duarte 8 [email protected] Modelo de banco de dados: representa a estrutura física no qual o armazenamento dos dados foi projetado. Pode ser modelo relacional, modelo hierárquico e modelo em rede. 1.4 – Sistemas de Banco de Dados e Modelos de Dados Foi discutido anteriormente no que um sistema de banco de dados deve ser o mais seguro e confiável possível e que este deve ser projetado de forma a evitar erros e correções que gerem um custo adicional muito grande ao projeto. Para efetuar este planejamento, devemos primeiramente identificar e definir como as entidades deste sistema serão constituídas. Esta imagem gráfica de toda base de informações necessárias para a construção de um determinado sistema, pode ser denominada por “Modelos de Dados” e pode possuir vários níveis de abstração. Os modelos de dados podem ser basicamente de dois tipos: Alto nível: ou modelo de dado conceitual, possibilita uma visão mais próxima do mundo real. É o modo como o usuário visualiza os dados realmente. Baixo nível: ou modelo de dado físico, fornece uma visão mais detalhada de como os dados estão realmente armazenados. 1.5 – Modelagem e seus objetivos A organização atual de algumas corporações de negócios possibilita, em uma análise mais abrangente, a identificação de alguns elementos chaves para o bom andamento dos negócios. Isso permite que regras de negócio sejam elaboradas e isto sirva como pedras fundamentais para orientar as atividades de toda a organização. Estas definições estratégicas fazem parte da política de negócio adotado pelas empresas, bem como pelas características próprias do ramo de atividade de cada uma delas. Alguns exemplos destas definições podem ser denominados como “regras de negócios” e são listadas abaixo: Levantamento das personagens; Eventos e procedimentos envolvidos com o dia a dia da organização; Características particulares a cada um destes elementos Relacionamento entre eles; 9 André Luís Duarte Banco de Dados Objetivos finais da organização; Prioridades da empresa; etc Essa tarefa de levantamento e estruturação dos dados segundo as regras de negócio de determinada empresa é denominada de “Modelagem de Dados”. Essa modelagem ocorre em níveis diferentes de abstração contemplando desde a visão geral dos negócios até os detalhes de uma parte específica do conjunto, gerando assim uma visão com vários subsistemas. Podemos definir então que o objetivo da modelagem de dados é definir o contexto dos dados em que os diversos sistemas funcionam. Por causa disto, o conteúdo produzido pela modelagem de dados deve ser o mais fiel possível ao sistema real, e suas especificações não devem implicar em nenhuma implementação física em particular evitando assim viciar a análise pela restrição do ponto de vista do analista. André Luís Duarte 10 [email protected] Capítulo 2 – Modelo Conceitual Modelo Entidade-Relacionamento e Seus Conceitos 2.1 – Abstração e Modelagem de Dados Como discutido no capítulo anterior, chamamos de modelagem de dados a tarefa de levantamento e estruturação dos dados segundo as regras de negócio de determinada empresa. Como cada entidade pode utilizar estas informações de diferentes maneiras, o conjunto gerado nesta análise deve possibilitar vários níveis de visões, a fim de obter um mapa completo do modelo de dados. A partir deste ponto podemos então definir “Modelos de Dados” como sendo uma abstração de dados que é utilizada para fornecer a representação conceitual utilizando conceitos lógicos como objetos, suas propriedades e seus relacionamentos. A estrutura detalhada e a organização de cada arquivo são descritas no catálogo do banco de dados. A Figura2.1 mostra um exemplo de projeto lógico de banco de dados onde as informações vão sofrendo análises até gerar um modelo conceitual que represente com fidelidade toda estrutura do minimundo estudado Figura2.1 – Exemplo de projeto lógico de banco de dados 11 André Luís Duarte Banco de Dados 2.2 – O Método Entidade-Relacionamento Em 1976 o Prof. Peter Chen propôs um metodologia chamada “EntidadeRelacionamento” a fim de poder representar na forma de diagramas o modelo de dados, auxiliando o analista a examinar o esquema da empresa do ponto de vista das regras de negócios da empresa e não do ponto de vista do programador de aplicação. O Método Entidade-Relacionamento (E/R) ou Modelo de Entidade / Relacionamento (MER), foi proposto a fim de acrescentar um estágio intermediário ao projeto lógico de banco de dados. Posteriormente, a comunidade de estudos na área de modelagem acrescentou novos conceitos e técnicas ampliando assim a metodologia proposta originalmente. As principais características da modelagem E/R são: Representação gráfica da modelagem através de um diagrama chamado “Diagrama de E/R” Preocupação com a semântica dos relacionamentos Ideal para comunicação com usuários leigos Independência de sistema gerenciador de banco de dados Permite a construção de modelos mais estáveis A fim de trabalharmos com o método E/R de forma mais eficiente e segura, devemos possuir uma compreensão de alguns conceitos básicos que serão vistos com mais detalhes nos tópicos seguintes. São eles: Entidade: conjunto de qualquer coisa que possua características próprias Atributos: características de uma Entidade Relacionamentos: vinculo ou associação entre Entidades A partir destas definições mais simplificadas podemos analisar e identificar estas estruturas no exemplo do diagrama E/R a seguir: André Luís Duarte 12 [email protected] Figura2.2 – Exemplo de um diagrama E/R 2.3 Entidades e Conjuntos de Entidades Entidade ou conjunto de entidades são quaisquer “coisas” do mundo real sobre as quais se deseja guardar algum tipo de informação. São exemplos típicos: Pessoas – física ou jurídica (funcionário, empresa, fornecedor, cliente, etc) Objetos – materiais ou abstratos (produto, veículo, disciplina, projeto, etc) Eventos – (pedido, viagem, empréstimo, vendas, etc) Devemos tomar cuidado quando identificamos as entidades pois existem elementos que não podem ser considerados como entidades: Entidade com apenas um elemento; Operações e saídas do sistema; Pessoas que manipulam o sistema (usuários do sistema); Cargos específicos; Geralmente as entidades são representadas por um retângulo contendo o nome da entidade (um substantivo singular) posicionado ao centro. Figura2.3 – Representação gráfica de uma entidade segundo o método E/R Uma entidade geralmente possui várias manifestações dela mesma. Por exemplo, a entidade funcionário representa todos os funcionários da empresa e não somente um 13 André Luís Duarte Banco de Dados funcionário (analista, programador, gerente de qualidade, etc). A estas manifestações chamamos de ocorrências ou como iremos nos referir “instâncias” da entidade. 2.4 – Atributos Dada uma entidade que seja de nosso interesse, chamamos de atributos o conjunto de informações mais relevantes e que possam descrevê-la com precisão. É muito importante que durante a modelagem, identifiquemos todos os atributos requeridos para o funcionamento adequado dos processos de negócio, pois estes permanecem constantes para todos os seus relacionamentos e os atributos são independentes das outras entidades. São exemplos de atributos de entidades (instâncias): nome, número de chamada, sexo, cargo, carga horária, etc. A representação original para os atributos no diagrama E/R é uma elipse ou um círculo contendo o nome do atributo e este é ligado a sua respectiva entidade através de uma linha contínua. Veja figura a seguir: Figura2.4 – Exemplos de notações para atributos A representação acima na maioria das vezes é pouco prática e uma das maneiras mais utilizadas é a representada a seguir: Figura2.5 – Notação mais usual para atributos André Luís Duarte 14 [email protected] Os atributos podem assumir valores de acordo com a sua natureza. O conjunto destes valores é chamado de domínio do atributo. Os atributos podem ser caracterizados por cardinalidade de atributo e pode ser mínima e máxima. Esta é representada no diagrama pelos valores entre parênteses separados por vírgula. Quando a cardinalidade não é especificada no atributo, assume-se que esta é (1,1). A figura a seguir mostra um exemplo onde a entidade professor deve possuir um ou mais títulos (no mínimo um título e no máximo n títulos). Figura2.6 – No exemplo a presença de pelo manos um título é obrigatória 2.4.A – Atributos Simples e Compostos O atributo denominado “simples” ou “atômico” é o atributo de determinada entidade que não pode ser subdividido em partes. O atributo denominado “composto” é o atributo que pode ser subdividido em outras sub-partes e cada uma destas possui um significado próprio e são independentes entre si. Figura2.7 – Representação de atributo composto 2.4.B – Atributos Multivalorados São atributos que podem assumir mais de um valor para cada entidade (instância) e é representado no diagrama E/R com um “asterisco” (*) ou pela Figura2.8. Estes atributos devem possui cardinalidade máxima de atributo maior do que 1. Figura2.8 – Diagrama que representa atributos multivalorados 15 André Luís Duarte Banco de Dados Figura2.9 – Representações para atributos multivalorados Os atributos que não podem assumir mais de um valor para cada entidade (instância) são chamados de atributo simplesmente valorado. 2.4.C – Atributos Opcionais ou Mandatário São os atributos que possuem cardinalidade mínima de atributo igual a zero, por exemplo, (0,n). 2.4.D – Atributos Determinantes ou Identificadores É o atributo que permite identificar uma instância da entidade de forma única. Muitas vezes, este identificador pode ser formado pela composição de dois ou mais atributos da entidade. O identificador ou atributo determinante deve estar representado no diagrama E / R sublinhado, como mostrado na Figura2.9. 2.5 – Relacionamentos e Classes de Relacionamentos Além de conhecermos as entidades, é muito importante conhecermos como estas se relacionam entre si. A definição mais formal para relacionamento em banco de dados diz que: “um tipo relacionamento R entre n entidades (E1, E2, E3, ..., Em) é o conjunto de associações entre entidades deste tipo”. Isto significa que cada instância de relacionamento r1 em R é uma associação de entidades, onde a associação inclui exatamente uma entidade de cada tipo participante no relacionamento. No exemplo da Figura2.10 abaixo podemos verificar o relacionamento entre dois tipos de entidades (empregado e departamento) e o relacionamento entre elas (trabalha para). André Luís Duarte 16 [email protected] Para cada relacionamento, participam apenas uma entidade de cada tipo, porém, uma entidade pode participar de mais de um relacionamento. Figura2.10 – Exemplo de um relacionamento No exemplo anterior podemos notar que a ocorrência da entidade empregado, sempre estará associada a ocorrência da entidade departamento. Podemos então batizar esta associação (relacionamento) de “trabalha para” (ou pertence) visto que um funcionário sempre vai trabalhar para (pertencer a) um departamento da empresa. O relacionamento é representado no diagrama E / R como um losango contendo o nome do relacionamento. Figura2.11 – Relacionamento entre entidades Um relacionamento possui uma característica importante chamada de cardinalidade que é considerada uma “restrição imposta pelo estado das entidades no seu mini-mundo” . A cardinalidade em um atributo consiste na especificação do sentido da associação entre as entidades envolvidas. No exemplo anterior podemos verificar que para cada ocorrência da entidade funcionário deve existir uma e somente uma ocorrência da entidade departamento. Por outro lado para cada ocorrência da entidade departamento, deve existir uma ou mais ocorrências da entidade funcionário, haja visto que um departamento pode possuir 17 André Luís Duarte Banco de Dados vários funcionários. Por isto dizemos que neste caso a cardinalidade do relacionamento trabalha para é de um para muitos ou 1:N (um para ene) e é representado da seguinte forma no diagrama E / R. Figura2.12 – Cardinalidade de um relacionamento Os relacionamentos de cardinalidade 1:N são clássicos, pois representam a maioria das situações encontradas no desenvolvimento de sistemas comerciais. Contudo existem teoricamente relacionamentos que possuem outras cardinalidades e que são considerados como variantes do relacionamento de cardinalidade 1:N. Podemos citar então o relacionamento de cardinalidade 1:1 (um para um) e seu exemplo é mostrado na figura a seguir. Figura2.13 – Exemplo de relacionamento de cardinalidade 1:1 Apesar de existirem muitas situações que sugerem relacionamento de cardinalidade (1:1), devemos sempre desconfiar de tais relacionamentos e analisar se as duas entidades envolvidas não são na realidade uma só. Uma forma de fazermos esta análise, é verificarmos se o principal identificador da primeira entidade é diferente do principal identificador da segunda, caso não o sejam, provavelmente estamos interpretando dois aspectos diferentes da mesma entidade. Um exemplo de relacionamento (N:N) pode ser observado na Figura2.15. Figura2.14 – Exemplo de relacionamento de cardinalidade (N:N) André Luís Duarte 18 [email protected] 2.6 – Auto Relacionamento Ao trabalharmos situações e componentes do dia-a-dia de empresas, poderemos encontrar casos em que instâncias da mesma entidade se relacionam entre si por apresentarem uma estrutura de natureza hierárquica. São exemplos clássicos a modelagem de estruturas de produtos e a representações de hierarquias de pessoal. Para ilustrarmos este tipo de relacionamento, vamos propor o estudo de dois casos. Suponha a existência de uma empresa estruturada em departamentos que por sua vez são compostos por conjunto de funcionários. Alguns funcionários são supervisores de outros funcionários e este modelo é representado na seguinte tabela. Tabela2.1 – Tabela de descrição dos departamentos Podemos observar na Tabela2.1 que existem ocorrências da entidade funcionário que se relacionam com outras ocorrências dessa mesma entidade. Isso caracteriza um tipo de relacionamento chamado de reflexivo na entidade funcionário e pode ser representado no modelo E / R como mostrado na Figura2.16. Figura2.15 – Auto relacionamento (relacionamento reflexivo) entre funcionários A tabela a seguir apresenta uma parte dos produtos comercializados por uma empresa no setor de montagem, manutenção e venda de equipamentos de informática. 19 André Luís Duarte Banco de Dados Podemos notar que na lista existem produtos básicos (placa de vídeo, unidade de disco flexível, unidade de cd-rom, etc) que não podem ser decompostos em partes menores (pelo menos baseado no objetivo de negócio da empresa). Contudo existem outros produtos que chamamos de compostos, pois são formados pela combinação de produtos mais simples (o computador e o Kit multimídia). Verificamos também que um produto composto pode participar na formação de outro produto composto. Tabela2.2 – Lista parcial de produtos comercializados por uma empresa Com isso temos a ocorrência da entidade produto que se relaciona com outras ocorrências da própria entidade. Notamos que em um relacionamento entre dois produtos, um representa o papel de composto e o outro o papel de componente. Um produto pode ser componente de zero ou mais produtos e um produto pode ser composto de zero ou mais componentes. A representação do auto relacionamento anterior é mostrada na Figura2.17. Figura2.16 – Auto relacionamento entre produtos André Luís Duarte 20 [email protected] Como podemos observar existem auto relacionamentos ou relacionamento recursivo de qualquer cardinalidade, no caso, (N:N). 2.7 – Atributos de Relacionamentos É quando um determinado relacionamento possui atributos, também conhecido como relacionamento valorado. Por exemplo: Jussara trabalha 25 horas no projeto Aprender. Jussara: instância da entidade funcionário Aprender: instância da entidade projeto Trabalha em: relacionamento entre a entidade funcionário e projeto Figura2.17 – Exemplo de atributo de relacionamento 2.8 – Relacionamentos Parciais e Totais Outra restrição importante nos relacionamentos é chamada de participação e pode ser total ou parcial. Relacionamento parcial é quando nem todos os elementos de uma ou mais entidades participam do relacionamento. Em oposição relacionamento total é quando todos os elementos de uma ou mais entidades participam do relacionamento. Podemos ver claramente estes exemplos por exemplo no relacionamento entre funcionário gerencia departamento. A entidade funcionário possui participação parcial no relacionamento pois nem todo funcionário gerencia um departamento (existem funcionários que só trabalham no departamento). Já a entidade departamento possui participação total no relacionamento pois todos os departamentos são gerenciados por algum funcionário. Já no relacionamento funcionário trabalha em departamento, a participação é total para ambas as entidades. 2.9 – Relacionamentos Múltiplos Até este momento nosso estudo levou em conta relacionamento entre duas entidades. Este tipo de relacionamento é chamado de relacionamento binário. O relacionamento 21 André Luís Duarte Banco de Dados múltiplo é uma extensão do relacionamento binário para um número qualquer de entidades. Figura2.18 – Exemplo de relacionamento ternário ou múltiplo Outro exemplo clássico é o relacionamento entre cliente, vendedor e produto. Geralmente podemos analisar este tipo de relacionamentos agrupando as entidades de maneira conveniente. 2.10 – Agregações O modelo E / R proposto por Peter Chen na década de 70 sofreu algumas adaptações e extensões a fim de torná-lo mais completo e abrangente. Uma destas extensões é denominada agregação e foi proposta a fim de representar algumas situações de relacionamentos N:N que não poderiam ser representadas utilizando o modelo da forma como foi proposto. A agregação é uma abstração por meio da qual relacionamentos são tratados como entidades de nível superior. É representada por um retângulo envolvendo as entidades e relacionamentos participantes. Podemos então construir objetos compostos a partir de objetos componentes. Podemos olhar para agregação como temos olhado até agora para os outros componentes, ou seja, uma entidade é uma agregação de atributos, um relacionamento é uma agregação de entidades e atributos, um atributo composto é uma agregação de atributos mais simples, etc. André Luís Duarte 22 [email protected] Vamos propor o seguinte cenário a fim de contextualizar nosso exemplo: A turma computação foi requisitada para desenvolver projetos computacionais dentro do campus universitário. Para isto, a turma deve formar grupos de analistas a fim de que possam acompanhar os projetos. Um analista pode participar de mais de um projeto ao mesmo tempo. Baseados neste caso têm-se o seguinte diagrama E/R: n Analista n Alocado Projeto Figura2.19 – Exemplo de agregação situação 1 Vamos agora supor que o Analista João que trabalha no Projeto de Levantamento de Regras de Negócio (P_LRN) requisitou um computador notebook no LPD e um veículo de transporte para se locomover e a analista Márcia requisitou o mesmo equipamento notebook para o projeto de modelagem entidade relacionamento (P_MER). Vamos impor uma consideração, um analista só poderá requisitar um recurso se for para utilização em um projeto. Não deve haver problemas com o compartilhamento do notebook, pois a utilização no projeto P_MER depende da finalização do projeto P_LRN. Como o recurso foi requisitado por um analista para utilização em um projeto, é de se esperar que estejam disponíveis informações a respeito do analista e projeto para o qual o recurso será utilizado. Por isto não podemos relacionar o recurso unicamente ao analista nem somente ao projeto, o que nos obriga a visualizarmos o relacionamento entre a entidade ANALISTA e PROJETO inclusive estas, como uma única entidade. Graficamente teremos o seguinte. 23 André Luís Duarte Banco de Dados n n Analista Projeto Alocado n Requisita n Recurso Figura2.20 – Exemplo completo de agregação Outro exemplo seguindo a mesma ideia é na modelagem de um funcionário que trabalha em um departamento e utiliza uma máquina. n n Funcionário Projeto Trabalha n Utiliza n Máquina Figura2.21 – Outro exemplo de agregação Este tipo de abstração estabelece um relacionamento “é-parte-de” entre os componentes e a classe. Poderemos encontrar também a seguinte representação para agregação: n Funcionário n Trabalha Projeto n Utiliza n Máquina Figura2.22 – Outra representação para agregação André Luís Duarte 24 [email protected] 2.11 – Generalização / Especialização É um tipo de abstração que define um relacionamento de subconjunto entre os elementos de duas ou mais classes. Temos então que: todas as abstrações definidas para a classe genérica, são herdadas por todas as classes que são subconjuntos. Este tipo de estrutura é utilizada no diagrama E/R para enfatizar as semelhanças entre tipos de entidades de nível superior e ocultar suas diferenças. É representada no diagrama E/R por um triângulo com o rótulo “é um(a)”. A generalização / especialização pode ser classificada em: Generalização total (t): quando cada elemento da classe genérica é mapeada para pelo menos um elemento das classes especializadas. Nome CPF Pessoa é uma Homem t Mulher Próstata Gestações Figura2.21 – Exemplo de generalização total Generalização parcial (p): quando existe algum elemento da classe genérica que não é mapeado para nenhum elemento das subclasses. Cor Dimensões Veículo é um Carro Motor p Bicicleta Manopla Figura2.22 – Exemplo de generalização parcial 25 André Luís Duarte Banco de Dados 2.12 – Chaves Conceitualmente vimos que entidades e relacionamentos individuais são distintos. Porém, numa visão mais prática e real, essa diferença deve ser expressa em termos dos atributos das entidades e dos relacionamentos envolvidos. Para conseguir esta distinção, devemos lançar mão do conceito de “chave primária” (superchave) e “chave candidata”. Uma chave primária é um atributo ou conjunto de atributos que representam uma instância da entidade de forma única. Uma chave candidata possui a mesma definição de chave primária, porém esta não deve possuir nenhum subconjunto próprio que seja uma chave candidata. Podemos ver alguns exemplos de chaves candidatas na Tabela2.3 a seguir. Atributo CPF RG Nome1 Endereço1 Nome + Endereço Nome + CPF2 Chave candidata Sim Sim Não Não Sim Não Chave primária Sim Sim Não Não Sim Não 1 – Depende do tamanho do banco de dados a ser desenvolvido. 2 – CPF é uma chave candidata individualmente. Tabela2.3 – Exemplos de chave candidatas 2.13 – Conjunto de Entidades Forte e Fraco Durante a modelagem poderemos encontrar entidades com atributos suficientes para formar chaves candidatas e então escolhermos dentre estas a mais apropriada para ser a chave primária da entidade. A entidade que possui uma chave primária é dita entidade ou conjunto de entidades forte. Porém, existirão situações onde o conjunto de entidades não vai possuir atributos que possam formar chaves candidatas (nem individualmente nem em grupos). Sem chaves candidatas não poderemos definir uma chave primária para a entidade. A este conjunto de entidades (que não possuem chave primária) damos o nome de entidade ou conjunto de entidades fraco. André Luís Duarte 26 c o n ° N s ta a ld a [email protected] o ã ç a n ti a r n t ta a ° a u N D Q o S n n Conta Transação Log Figura2.23 – Exemplo de conjunto de entidade forte e fraco 2.14 – Restrições de Mapeamento Ao analisar um sistema, o analista deve estar atento para as restrições impostas na elaboração dos modelos em um banco de dados. Vamos estudar inicialmente duas destas restrições. A primeira é chamada de restrição de cardinalidade do mapeamento, estas expressam o número de entidades às quais outras entidades podem se associar. Elas podem ser, cardinalidade mínima ou cardinalidade máxima. No caso de cardinalidade máxima, elas podem assumir as combinações um-para-um, um-para-muitos, muitos-para-um e muitos-para-muitos. No caso da cardinalidade mínima deve-se analisar o contexto, pois obviamente, elas dependerão do mundo real que está sendo modelado. A dependência de existência forma outra importante classe de restrições. Quando a existência de uma entidade E1 depende da existência de outra entidade E2, dizemos que E1 é dependente de E2. A entidade E2 é chamada de entidade dominante e E1 é chamada de entidade subordinada. ua a l nt i d or ad C e ód u n i tá ig ri o o Entidades que possuem chave primária, sempre serão entidades dominantes (forte), o at r a o Vendedor D (0,n) n Efetua Q al ip T 1(1,1) V N C P F om e entidades subordinadas (fracas). 1(0,1) Venda V enquanto as entidades que não possuírem chave primária própria serão geralmente (1,n) n Possui Itens Figura2.24 – Conjunto de entidades fraco não possuem chaves candidatas 27 André Luís Duarte Banco de Dados 2.15 – Reduzindo o Diagrama E/R a tabelas 2.15.1 – Representação de Conjuntos de Entidades Fortes Seja um conjunto de entidades forte E com atributos descritivos a1, a2, ..., an. Representamos esta entidade por uma tabela chamada E com n colunas distintas, cada uma correspondendo a um dos atributos de E. Cada linha nesta tabela corresponde a uma instância do conjunto de entidades E. Como primeiro exemplo iremos trabalhar o conjunto de entidades “Conta” presente no diagrama mostrado na Figura2.25. De acordo com o diagrama E/R, a entidade conta possui dois atributos Número Conta e Saldo. Dizemos que D1 representa o conjunto de todos os números de conta e D2 representa o conjunto de todos os saldos. As linhas da Tabela Conta devem ser constituídas de uma da N ta N o C me P R F u C a id ad e V 2 D2 . n S úm er al o do co nt a dupla (V1, V2), onde V1 é um número de conta tal que V 1 D1 e V2 é um saldo tal que n Cliente Possui Conta 1 N ú Log m e ro tr a nD Q s aata ua çã n o tia n Transação Figura2.25 – Diagrama E/R para cliente-conta-transação Chamamos de produto cartesiano D1 D2 o conjunto de todas as combinações possíveis das linhas de D1 e D2. A Tabela Conta geralmente irá conter um subconjunto do conjunto resultante do produto cartesiano. Matematicamente TabelaConta D1 D2 . Generalizando, se tivermos uma tabela de n colunas, representamos o produto cartesiano de D1, D2, ...,Dn por: André Luís Duarte 28 [email protected] D1 x D2 x .. x .Dn - 1 x Dn 630 1000 259 2000 183 1300 ... ... (630,1000)(630,2000)(630,1300) (259,1000)(259,2000)(259,1300) (183,1000)(183,2000)(183,1300) (...,...) número-conta 259 630 401 700 199 467 115 183 118 225 210 Figura2.26 – Produto cartesiano D1xD2 saldo 1000 2000 1500 1500 500 900 1200 1300 2000 2500 2200 Tabela2.4 – Tabela Conta Da mesma forma a TabelaCliente será reduzida para a seguinte forma. Nome-cliente Rafael Jucimara Lucas Davi Samuel Lisley Talita cpf-cliente rua cidade-cliente 12345678901 Albino Itajubá 36582945871 Souza Divinópolis 25478965210 Cardoso Maria da Fé 65001452036 Rodrigues Itajubá 80145800478 Seabra Itajubá 15844452102 Jurandir Maria da Fé 35810023695 Pereira Itajubá Tabela2.5 – Tabela Cliente Como podemos observar, a entidade cliente possui quatro atributos, Nome, CPF, Rua, Cidade. A tabela correspondente irá possuir quatro colunas sendo uma para cada atributo. 2.15.2 – Representação de Conjuntos de Entidades Fracos Seja A um conjunto de entidades fraco com atributos a1, a2, ..., ar. Dizemos que B é o conjunto de entidades forte B do qual A depende. Dizemos que a chave primária de B consiste dos atributos b1, b2, ..., bs. Representamos o conjunto de entidades A por uma tabela chamada A que possuirá uma coluna que irá representar cada atributo do conjunto {a1,a2,...,ar}U{b1,b2,...,bs}. Vamos analisar o conjunto de entidades Transação da figura 2.25. Este conjunto possui três atributos, Número transação, Data, Quantia. 29 André Luís Duarte Banco de Dados Como podemos notar, nenhum atributo pode ser usado individualmente ou em conjunto para formar uma chave primária. Por isto este conjunto é dito conjunto de entidades fraco. A chave primária do conjunto de entidades Conta, do qual Transação é dependente, é Número conta. Com base nestes dados, a tabela Transação será representada por uma tabela contendo quatro colunas, Número conta, Número transação, Data e Quantia. número-conta 259 630 401 700 199 259 115 199 259 número-transação 5 11 22 69 103 6 53 104 7 data 11/05/2003 17/05/2003 23/05/2003 28/05/2003 03/06/2003 07/06/2003 07/06/2003 13/06/2003 17/06/2003 quantia +50 +70 -300 -500 +900 -44 +120 -200 -79 Tabela2.6 – Representação da entidade Transação 2.15.3 – Representação de Conjuntos de Relacionamentos Seja R um conjunto de relacionamentos envolvendo os conjuntos de entidades E1, E2, ..., En. Digamos que atributo(R) consista em n atributos. Representamos este conjunto de relacionamentos por uma tabela chamada R com n colunas distintas, cada uma correspondendo a um atributo de atributo(R). Vamos analisar o relacionamento “<possui>” entre “[conta]” e “[usuário]”. Antes, porém, é importante notarmos que este relacionamento irá se tornar uma tabela, e nomearmos uma tabela de “possui” ficaria um tanto estranho e não será tão intuitivo para a finalidade aqui estudada como é na representação E/R. Por isso, iremos chamar este relacionamento de contacliente. O conjunto de relacionamento contacliente envolve os seguintes conjuntos de entidade: Cliente, com chave primária cpf Conta, com chave primária número-conta Uma vez que o conjunto de relacionamentos possui o atributo data, a tabela contacliente irá possuir três colunas, cpf, número-conta, data. André Luís Duarte 30 [email protected] cpf 12345678901 36582945871 25478965210 65001452036 80145800478 15844452102 35810023695 número-conta 259 630 401 700 199 259 115 data 17/02/2003 17/02/2003 23/02/2003 01/03/2003 07/03/2003 07/03/2003 15/04/2003 Tabela2.7 – Representação do relacionamento contacliente (possui) os iv ld o er o Sa 1 n Cliente N úm Agência C N om e PF R ua C id ad e co nt a At C N mostrado na Figura2.27 a seguir. id om ad e e Como exemplo final, consideremos o conjunto de relacionamentos do diagrama n CCA Conta Figura2.27 – Relacionamento ternário conta-cliente-agência Este relacionamento envolve três conjuntos de entidades: Cliente, com chave primária cpf Conta, com chave primária número-conta Agência, com chave primária nome-agência Analogamente de acordo com o estudo realizado até este momento, teremos a tabela que irá representar o conjunto de relacionamentos CCA. cpf 12345678901 36582945871 25478965210 65001452036 80145800478 15844452102 35810023695 número-conta 259 630 401 700 199 259 115 nome-agência Av BPS Rua Rodrigues Av 1° de junho Rua Nova Av Major Rua Carneiro Alameda A Tabela2.8 – Representação do relacionamento CCA 31 André Luís Duarte Banco de Dados Capítulo 3 – Modelo Relacional 3.1 – Introdução Historicamente o modelo relacional é um modelo novo. Os primeiros sistemas de Banco de Dados foram baseados nos modelos hierárquicos ou em rede. O Modelo Relacional estabeleceu-se como o modelo de dados principal para sistemas de processamento de dados comerciais, mas, além disso, também foi utilizado como ferramenta CASE para projetos em diversos ambientes. 3.2 – Estrutura de Banco de Dados Relacionais Um BDR consiste em uma coleção de tabelas, cada qual designada por um nome único. Cada tabela possui uma estrutura similar àquela apresentada na redução do ME/R em tabelas. Uma linha numa tabela representa um relacionamento entre um conjunto de valores. Uma vez que uma tabela é um conjunto destes relacionamentos, existe uma correspondência entre o conceito de tabela e o conceito matemático de relação. 3.2.1 – Estrutura básica Considere a tabela representada a seguir. nome-agência número-conta nome-cliente saldo Centro 101 Lucas 500 Morro Chic 215 André 700 Boa Vista 102 Jussara 400 Varginha 305 Duarte 350 Boa Vista 201 Davi 900 BPS 222 Samuel 700 Avenida 217 Mateus 750 Centro 105 Mateus 850 Tabela 3.1 – Relação depósito A Tabela 3.1 possui quatro atributos: nome-agência, número-conta, nome-cliente, saldo. Para cada atributo existe um conjunto de valores possíveis que chamamos de domínio daquele atributo. Para o atributo nome-agência o domínio é o conjunto de todos os nomes de agências. Seja então D1 o conjunto dos nomes de agência, D2 o conjunto de números de contas, D3 o conjunto de nomes de clientes e D4 o conjunto de todos os saldos. Podemos então André Luís Duarte 32 [email protected] verificar que qualquer linha de depósito deverá conter valores quádruplos (v1, v2, v3, v4) onde v1 é um nome de agência, v2 é um número de conta, v3 é um nome de cliente e v4 é um saldo de conta, ou seja, v1 está no domínio de D1, v2 está no domínio de D2, etc. Geralmente depósito conterá apenas um subconjunto de todas as linhas possíveis, ou seja, depósito é um subconjunto de D1 D2 D3 D4 . Geralmente uma tabela de n colunas precisa ser um subconjunto de D1 D2 D3 D4 ... Dn 1 Dn . Devido ao fato de as tabelas serem essencialmente relações, encontraremos na literatura conceitual os termos matemáticos relação e tupla no lugar de tabela e linha, por isso, assumiremos esta nomenclatura. Na relação depósito da Tabela3.1, existem oito tuplas. Digamos que a variável tupla t refira-se à primeira tupla da relação. Usamos a notação para representar o valor de t no atributo nome agência. Assim: t[número-conta]=101 é o valor de t no atributo número da conta, nome do cliente e saldo seguem a mesma idéia. De outro modo podemos escrever t[1] para representar o valor da tupla t no primeiro atributo (nome-agência), t[2] para representar o número da conta e assim por diante. Uma vez que a relação é um conjunto de tuplas, usaremos a notação t r para representar que a tupla t está na relação r. Por enquanto, vamos considerar que todas as relações r possuem domínio atômico, ou seja, os elementos do domínio são elementos indivisíveis. 3.2.2 – Esquema de Banco de Dados Geralmente um esquema relacional é uma lista de atributos e de seus domínios correspondentes1. Quando necessitarmos explicitar nosso domínio, o faremos logo após 1 Não iremos definir precisamente o domínio de cada atributo pois necessitamos do conceito de integridade que será visto mais adiante. 33 André Luís Duarte Banco de Dados cada atributo da relação. Por exemplo: (nome-agência:cadeia número-conta: cadeia, etc). Devemos sempre atribuir um nome a um esquema relacional. Nomes começando com letras maiúsculas serão usados para esquemas de relações e nomes começando com letras minúsculas para relações. Baseado na notação proposta, Esquema-depósito representará o esquema relacional para a relação depósito. Assim: Esquema-depósito=(nome-agência, número-conta, nome-cliente, saldo) Note que depósito é uma relação num esquema Depósito, ou seja, depósito(Esquema-depósito) Como outro exemplo, vamos considerar a relação cliente. O esquema para esta relação é: Esquema-cliente(nome-cliente, rua-cliente, cidade-cliente) Podemos dizer que analogamente um esquema relacional corresponde à noção de definição de tipo em uma linguagem de programação, também uma variável corresponde a uma instância de uma relação, já que ambas em um determinado instante possuem um valor. nome-cliente rua cidade-cliente Junior Rodrigues Itajubá André Seabra Maria da Fé Jussara Rodrigues Itajubá Lislei Seabra Maria da Fé Samuel Cardoso Pouso Alegre Duarte Arlindo Brasópolis Davi Zaroni Paraisópolis Talita Major Brasópolis Lucas Coronel Piranguinho Mariana Nova Sta Rita Tiago Corrêa Cristina Mateus Lamounier Brasópolis Tabela3.2 – Relação cliente O uso de atributos comuns em esquemas relacionais é uma forma de relacionar tuplas de relações distintas. Suponha que desejamos achar as cidades onde os clientes da agência Morro Chic moram. Vamos assumir a relação mostrada na Tabela3.1 e propor uma outra relação mostrada na Tabela3.2. André Luís Duarte 34 [email protected] Primeiro observamos a relação depósito para encontrar todos os clientes da agência Morro Chic. Para cada cliente, examinamos a relação cliente para encontrar a cidade na qual reside. Podemos pensar que um esquema relacional representando todas as informações seria melhor. Para um usuário a idéia de se utilizar um só esquema relacional é interessante, mas vamos analisar este cenário. Suponhamos, então, o seguinte esquema relacional. Esquema-conta-info=(nome-agência,número-conta,nome-cliente,saldo,ruacliente,cidade-cliente) A primeira coisa que podemos observar é que se um cliente possui diversas contas, precisamos listar seu endereço uma vez para cada conta. Esta repetição é dispendiosa e pode ser evitada pelo uso de duas relações. Outro problema é se um cliente possui mais de uma conta, mas não forneceu seu endereço. Não podemos construir uma tupla sobre Esquema-conta-info, uma vez que os valores para rua e cidade do cliente não são conhecidos. Para poder representar tuplas incompletas, precisamos utilizar valores nulos. No exemplo anterior utilizando duas relações, uma sobre Esquema-depósito e outra sobre Esquema-cliente, podemos representar um cliente cujos dados do endereço são desconhecidos sem utilizar valores nulos, ou seja: nome-agência número-conta nome-cliente saldo rua-cliente cidade-cliente Centro 101 Lucas 500 Coronel Piranguinho Morro Chic 215 André 700 NULO NULO Boa Vista 102 Jussara 400 NULO NULO Varginha 305 Duarte 350 Arlindo Brasópolis Tabela3.3 – Esquema-conta-info nome-agência número-conta nome-cliente saldo Centro 101 Lucas 500 Morro Chic 215 André 700 Boa Vista 102 Jussara 400 Varginha 305 Duarte 350 Tabela3.4 – Esquema-conta nome-cliente rua-cliente cidade-cliente Lucas Coronel Piranguinho Lislei Seabra Maria da Fé Tabela3.5 – Esquema-informação 35 André Luís Duarte Banco de Dados Nem sempre poderemos eliminar valores vazios. Veremos que este tipo de informação causa dificuldades no acesso e atualização do banco de dados. Sempre que possível, devemos eliminar valores nulos do banco. Por enquanto assumiremos que os esquemas de relação não possuem valores nulos. Posteriormente estudaremos critérios que nos ajudam a decidir quando um conjunto de esquema é melhor do que o outro em termos de repetição de valores e da existência de valores nulos. 3.2.3 – Linguagens de Consulta Uma linguagem de consulta é uma linguagem na qual o usuário requisita informações de um banco de dados. São tipicamente de mais alto nível em relação às linguagens de programação. Podem ser classificadas como procedural e não procedural. Examinaremos duas linguagens puristas: a álgebra relacional é procedural enquanto que o cálculo relacional de tupla e o calculo relacional de domínio são não procedural. Para nosso estudo consideremos o seguinte diagrama E/R mostrado na seguinte figura. Saldo Conta n° Depósito Agência Cliente Cidade Cidade Ativos Rua Nome Nome Empréstimo Empréstimo n° Quantia Figura3.1 – Diagrama E/R para um empreendimento bancário Consideremos também os seguintes esquemas de relacionamentos e suas relações. André Luís Duarte 36 [email protected] Esquema-agência=(nomeagência,ativos,cidadeagência) Esquema-cliente=(nomecliete,ruacliente,cidadecliente) Esquema-depósito=(nomeagência,númeroconta,nomecliente,saldo) Esquema-empréstimo=(nomeagência,numeroempréstimo,nomecliente,quantia) nome-agência número-empréstimo nome-cliente quantia Centro 17 Junior 1000 BPS 23 André 2000 Boa Vista 15 Jussara 1500 Centro 14 Ana 1500 Morro Chic 93 Lislei 500 Varginha 11 Duarte 900 Canudos 29 Davi 1200 Sul 16 Talita 1300 Centro 18 Lucas 2000 Boa Vista 25 Mariana 2500 Avenida 10 Tiago 2200 Tabela3.6 – Relação empréstimo nome-agência Centro BPS Boa Vista Morro Chic Varginha Canudos Sul Avenida ativos cidade-agência 9000000 Cristina 2100000 Piranguinho 1700000 São José 400000 São José 8000000 São José 300000 Jacareí 3700000 Maria da Fé 7100000 Cristina Tabela3.7 – Relação agência 3.3 – Álgebra Relacional A álgebra relacional é uma linguagem de consulta procedural. Ela consiste de um conjunto de operações que usam uma ou duas relações como entrada e produzem uma nova relação como resultado. 37 André Luís Duarte Banco de Dados As operações fundamentais da álgebra relacional são selecionar, projetar, produto cartesiano, renomear, união e diferença de conjuntos. Além das operações fundamentais existem interseção de conjuntos, junção natural, divisão e atribuição. As operações selecionar, projetar e renomear são chamadas de unárias, pois operam sobre uma única relação. As outras três são operações binárias por operarem com pares de relações. O seguinte panorama ilustra de forma intuitiva a álgebra relacional. AX AY A X BX Y BY B C CX CY PROJETAR SELECIONAR PRODUTO CARTESIANO UNIÃO a1 b1 INTERSEÇÃO b1 c1 a1 b1 c1 a2 b2 b2 c2 a2 b2 c2 a3 b3 b3 c3 a3 b3 c3 DIFERENÇA ax x ay y a az bx cy DIVISÃO JUNÇÃO NATURAL Figura3.2 – Panorama da álgebra relacional André Luís Duarte 38 [email protected] 3.3.1 – Operações Fundamentais 3.3.1.A – Operação Selecionar A operação selecionar seleciona tuplas que satisfazem um dado predicado. Utiliza-se a letra grega (sigma) para representar seleção. O predicado aparece como subscrito de . A relação argumento é dada entre parênteses. Exemplo 1 Selecionar as tuplas da relação empréstimo onde agência é centro. nomeagência"Centro" empréstimo nome-agência número-empréstimo nome-cliente quantia Centro 15 Jussara 1500 Centro 25 Mateus 2500 Centro 18 Lucas 2000 Tabela3.8 – Relação resultante da consulta nomeagência"Centro" empréstimo Exemplo 2 Encontrar todas as tuplas nas quais a quantia emprestada é maior do que $1200,00. quantia1200empréstimo Podemos utilizar os operadores , , , , , , além de combinar predicados com os conectivos (e) e (ou). Exemplo 3 Encontrar as tuplas pertencentes a empréstimos maiores que $1200,00 feitos pela agência do centro. nomeagência"Centro" quantia1200empréstimo O predicado de seleção pode ser usado para comparar dois atributos. Considere o esquema relacional Esquema-usuário=(nome-cliente,nome-gerente), indicando que um cliente possui um gerente pessoal. nome-cliente nome-gerente André Lucas Jussara Antônio Lucas Lucas Tabela3.9 – Relação Usuário A Ttabela3.9 mostra a relação usuário(Esquema-usuário). 39 André Luís Duarte Banco de Dados Exemplo 4 Encontrar todos os clientes que têm o mesmo nome do seu gerente pessoal. nomeclientenome gerente(usuário) A relação resultante da consulta acima é dada pela seguinte tabela. nome-cliente nome-gerente Lucas Lucas Tabela3.10 – Relação resultante da consulta nomeclientenome gerente(usuário) 3.3.1.B – Operação Projetar No exemplo anterior, obtivemos a relação (nome-cliente, nome-gerente) na qual t[nomecliente]=t[nome-gerente] para todas as tuplas t. Esta listagem é redundante pois poderíamos ter somente uma listagem. A operação projetar permite a geração desta listagem pois é uma operação unária que da como resultado sua relação argumento com certas colunas deixadas de fora. Como uma relação é um conjunto, quaisquer linhas duplicadas são deixadas de fora. A projeção é representada pela letra grega (pi maiúscula). Listamos os atributos que queremos que apareçam nos resultados como subscrito de . O argumento de relação segue a letra entre parênteses. Exemplo 5 Suponha que desejamos uma relação mostrando os clientes e as agências das quais eles tomaram empréstimo não importando a quantia ou o número do empréstimo. nome agência, nomeusuário(empréstimo) Exemplo 6 Dê o nome dos clientes que possuem o mesmo nome dos seus gerentes pessoais. nomeusuário nomeusuário nome gerenteusuário Note que ao invés de dar o nome da relação como argumento da operação de projeção, damos uma expressão de consulta que nos retorna uma relação. André Luís Duarte 40 [email protected] 3.3.1.C – Operação Produto Cartesiano Até agora, obtivemos informações de apenas uma relação de cada vez. A operação produto cartesiano nos permite combinar informações a partir de diversas relações. A operação produto cartesiano é representada pela (cruz) e trata-se de uma operação binária. Usaremos a notação r1 r 2 para representar o produto cartesiano entre as relações r1 e r2. Lembremos que uma relação é definida como sendo um subconjunto de um produto cartesiano de um conjunto de domínios. Definindo nomes de atributos para a relação resultante Um problema que surge ao trabalhar com a operação produto cartesiano é como ficam os nomes dos atributos da relação resultante. Suponha que desejamos encontrar os usuários atendidos pelo gerente Lucas, bem como as cidades nas quais estes usuários vivem. Precisamos da informação na relação usuário e na relação cliente. A Tabela3.11 mostra a relação. O esquema relação para r é: (usuário.nome-cliente,usuário.nome-gerente,cliente.nome-cliente, cliente.rua-cliente,cliente.cidade-cliente) usuário. nome-cliente André André André André André André André Jussara Jussara Jussara Jussara Jussara Jussara Jussara Lucas Lucas Lucas Lucas Lucas Lucas Lucas nome-gerente Lucas Lucas Lucas Lucas Lucas Lucas Lucas Antônio Antônio Antônio Antônio Antônio Antônio Antônio Lucas Lucas Lucas Lucas Lucas Lucas Lucas cliente. nome-cliente Lucas André Jussara Lislei Samuel Duarte Davi Lucas André Jussara Lislei Samuel Duarte Davi Lucas André Jussara Lislei Samuel Duarte Davi Tabela3.11 – Relação resultante rua-cliente Rodrigues Seabra Rodrigues Seabra Cardoso Arlindo Zaroni Rodrigues Seabra Rodrigues Seabra Cardoso Arlindo Zaroni Rodrigues Seabra Rodrigues Seabra Cardoso Arlindo Zaroni cidade-cliente Itajubá Maria da Fé Itajubá Maria da Fé São José Brasópolis Paraisópolis Itajubá Maria da Fé Itajubá Maria da Fé São José Brasópolis Paraisópolis Itajubá Maria da Fé Itajubá Maria da Fé São José Brasópolis Paraisópolis r usuário cliente 41 André Luís Duarte Banco de Dados Simplesmente ligamos todos os atributos de ambas as relações e ligamos o nome da relação da qual veio o atributo original. Para os atributos que aparecem em apenas um dos dois esquemas, utilizamos somente o nome do atributo e para os que se repetem usamos a dupla nome-relação.nome-atributo, afim de evitar ambiguidades. O esquema para a relação será: (usuário.nome-cliente,nome-gerente,cliente.nome-cliente,rua-cliente,cidade-cliente) Agora que conhecemos o esquema relacional para r usuário cliente , que tuplas aparecem em r? Uma tupla de r será constituída a partir de cada par de tuplas possíveis; uma da relação usuário e uma da relação cliente. Assuma que tenhamos n1 tuplas em usuário e n2 tuplas em cliente. Existem então n1 n2 maneiras possíveis de combinar as tuplas de ambas as relações. Em particular, note que, para algumas tuplas t de r pode ocorrer: tusuário.nome cliente tcliente .nome cliente Geralmente se temos relações r1R1 e r 2R2 , então r1 r 2 é uma relação cujo esquema é a concatenação de R1 e R2. A relação R contém todas as tuplas t para qual existe uma tupla t1 em r1 e t2 em r2 onde tR1 t1R1 e tR2 t 2R2 . Retomando a consulta “dê todos os usuários do gerente Lucas e a cidade em que eles vivem”. Consideremos a relação r usuário cliente . Se escrevemos nome gerente"Lucas" (usuário cliente ) , então teremos a Tabela 3.12 mostrada a seguir. Ou seja, temos uma relação pertencente à “Lucas”. Note que a coluna usuário.nomecliente contém apenas clientes de “Lucas”. Uma vez que a operação produto cartesiano associa qualquer tupla de cliente a qualquer tupla de usuário, sabemos que algumas tuplas em usuário cliente possuem a informação desejada. Isto irá ocorrer nos casos onde usuário.nome- cliente=cliente.nome-cliente. Logo teremos o seguinte. André Luís Duarte 42 [email protected] usuário.nomeclientecliente.nomecliente nome gerente"Lucas" usuário cliente Com esta expressão teremos as tuplas da relação usuário cliente que: Pertencem a “Lucas” Têm a rua e cidade do cliente de “Lucas” usuário. nome-gerente nome-cliente André Lucas André Lucas André Lucas André Lucas André Lucas André Lucas André Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas Lucas cliente. nome-cliente Lucas André Jussara Lislei Samuel Duarte Davi Lucas André Jussara Lislei Samuel Duarte Davi Tabela3.12 – Relação resultante rua-cliente Rodrigues Seabra Rodrigues Seabra Cardoso Arlindo Zaroni Rodrigues Seabra Rodrigues Seabra Cardoso Arlindo Zaroni cidade-cliente Itajubá Maria da Fé Itajubá Maria da Fé São José Brasópolis Paraisópolis Itajubá Maria da Fé Itajubá Maria da Fé São José Brasópolis Paraisópolis nome gerente"Lucas" (usuário cliente ) Finalizando, como queremos o nome dos clientes e a cidade em que eles vivem, fazemos uma projeção. usuário.nomecliente,cidadecliente usuário.nomeclientecliente.nomecliente nome gerente"Lucas" usuário cliente O resultado desta expressão é a resposta correta para a nossa consulta. 3.3.1.D – Operação Renomear Na consulta apresentada anteriormente, introduzimos a convenção de nomear atributo por nome-relação.nome-atributo a fim de eliminarmos possíveis ambiguidades ao acessar as tuplas. Outra forma de ambiguidade que pode ocorrer é quando a mesma relação aparece mais de uma vez na consulta. Suponha que desejamos os nomes de todos os clientes que moram na mesma rua e na mesma cidade que André. Podemos obter rua e cidade de André através da consulta 43 André Luís Duarte Banco de Dados rua, cidade cliente nome cliente" André" cliente Entretanto, para encontrarmos outros clientes com esta rua e cidade, devemos nos referir à relação cliente uma segunda vez. pcliente rua,cidadecliente nomecliente" André" cliente Onde p é um predicado de seleção que requer que os valores de cidade-cliente e rua sejam iguais. Para obtermos a consulta desejada, necessitamos nos referir a rua e cidade na mesma tabela. Já sabemos que não podemos ter a mesma nomenclatura pois estaríamos criando uma ambiguidade não desejada. Para resolver este problema, utilizamos a operação Renomear, representada pela letra (Rô minúscula) na expressão. x r Esta expressão retornará a relação r com o nome x. agora podemos renomear uma referência à relação duas vezes sem ambiguidades. Usando o nome cliente2 como um segundo nome para a relação cliente, temos a expressão. cliente.nome cliente cliente2.rua cliente.rua cliente2.cidade cliente cliente.cidade cliente cliente rua,cidade cliente nome cliente" André" cliente2 cliente 3.3.1.E – Operação União Como na teoria dos conjuntos, a operação união é representada pelo símbolo . Para analisarmos esta operação, vamos supor que o banco deseja saber o nome de todos os clientes que possuem uma relação (conta, empréstimo ou ambos) com a agência Boa Vista. Para fazermos esta consulta (produzirmos esta listagem) precisamos das informações da relação empréstimo e da relação depósito. Podemos encontrar todos os clientes com um empréstimo na agência Boa Vista com a seguinte expressão: André Luís Duarte 44 [email protected] nomecliente nomeagência"BoaVista" empréstimo Podemos encontrar todos os clientes que possuem uma conta na agência Boa Vista com a expressão: nomecliente nomeagência"BoaVista" depósito Para solucionarmos o problema proposto aqui, devemos fazer a união entre os dois conjuntos, ou seja, todos os clientes que aparecem em uma ou em ambas as relações. Assim, a expressão que nos dá o resultado desejado é: nomecliente nomeagência"BoaVista" empréstimo nomecliente nomeagência"BoaVista" depósito A relação resultante para esta expressão é: nome-cliente Jussara Mariana Davi Tabela3.13 – Relação resultante da consulta nome cliente nome agência" BoaVista" empréstimo nome cliente nome agência" BoaVista" depósito Note que existem três tuplas no resultado apesar de existirem dois solicitadores de empréstimo e dois depositantes. Isto se deve porque como as relações são conjuntos, os valores duplicados são eliminados. É importante observar que precisamos nos assegurar de que as uniões sejam feitas entre relações compatíveis. Não faz sentido promovermos a união entre relações com número de atributos diferentes, ou relações que não possuem domínios em comum. Logo, para que uma operação união r s seja válida, necessitamos de que duas condições sejam cumpridas: As relações envolvidas devem ter o mesmo grau, ou seja, devem possuir o mesmo número de atributos; Os domínios do i-ésimo atributo de r e de s devem ser os mesmos; 45 André Luís Duarte Banco de Dados 3.3.1.F – Operação Diferença de Conjuntos A operação diferença de conjuntos nos permite encontrar tuplas que estejam em uma relação e não estejam em outra relação. É representada pelo símbolo matemático de subtração –. A expressão r s resulta em uma relação contendo as tuplas que estão em r mas não estão em s. Exemplo 7 Encontrar todos os clientes da agência Boa Vista que tenham uma conta, mas não um empréstimo. nomecliente nomeagência"BoaVista" depósito nomecliente nomeagência"BoaVista" empréstimo A relação resultante para esta consulta aparece na tabela a seguir. nome-cliente Davi Tabela3.13 – Relação resultante da consulta nomecliente nome agência"BoaVista" depósito nomecliente nome agência"BoaVista" empréstimo Exemplo 8 Dê a conta com o maior saldo. Intuitivamente poderíamos pensar em escrever uma consulta comparando na mesma relação o atributo saldo procurando pelo maior valor. Se escrevêssemos a consulta depósito.saldod .saldodepósito d depósito teríamos como resultado todos os valores exceto os menores valores. Exercício de fixação Crie a relação para a expressão anterior e comprove que ela exibe somente os menores valores. André Luís Duarte 46 [email protected] Este resultado não nos ajuda muito, porém, se fizermos a comparação inversa, ou seja, depósito.saldod .saldodepósito d depósito teremos todos os valores exceto os maiores. Exercício de fixação Crie a relação para a expressão anterior e comprove que ela exibe somente os maiores valores. De uma forma mais completa, depósito.saldo depósito.saldod .saldodepósito d depósito . Se utilizarmos a operação diferença, poderemos obter da relação depósito as tuplas que não constam na relação anterior, assim, a expressão saldo depósito depósito.saldo depósito.saldod .saldo depósito d depósito possui os maiores valores para os saldos existentes na relação depósito. 3.3.2 Definição Formal da Álgebra Relacional Uma expressão geral da álgebra relacional é constituída a partir de sub expressões menores. Sejam E1 e E2 expressões da álgebra relacional. Então, as seguintes são expressões da álgebra relacional: E1 E 2 E1 E 2 E1 E 2 p E1 , onde p é um predicado sobre atributos que ocorrem em E1 s E1 , onde s é uma lista de alguns atributos que ocorrem em E1 x E1 , onde x é o novo nome para a relação E1 3.3.3 – Operações Adicionais As operações fundamentais são suficientes para representar qualquer consulta da álgebra relacional. As operações que serão estudadas neste tópico, não acrescentam 47 André Luís Duarte Banco de Dados nenhuma potência à álgebra relacional, mas simplificam algumas consultas comuns que são longas demais para serem expressas. 3.3.3.A – Operação Intersecção de Conjuntos Observe que qualquer expressão que usa a intersecção na álgebra relacional pode ser reescrita substituindo-se a operação intersecção por um par de diferenças entre conjuntos, assim, r s r r s . Assim, a operação intersecção representado pelo símbolo , não é uma operação fundamental nem acrescenta potência à consulta. Exemplo 9 Suponha que desejamos encontrar todos os clientes com um empréstimo e uma conta na agência Boa Vista. Usando a operação intersecção podemos escrever nomecliente nomeagência"BoaVista" depósito nomecliente nomeagência"BoaVista" empréstimo Exercício de fixação Crie a relação para a expressão anterior e comprove que o resultado é uma relação com Esquema (nome-cliente) e a tupla Jussara. 3.2.3.B – Operação Junção Natural Frequentemente desejamos simplificar uma consulta que requer um produto cartesiano. Uma consulta que envolve um produto cartesiano inclui, normalmente, uma operação de seleção no resultado desse produto. A operação junção natural é uma operação binária que permite combinar certas seleções e um produto cartesiano em uma operação e é representada pelo símbolo . Exemplo 10 Dê os clientes que têm um empréstimo no banco e as cidades em que vivem. André Luís Duarte 48 [email protected] Uma solução que poderíamos desenvolver para o problema anterior é a expressão utilizando somente as operações fundamentais apresentada a seguir: empréstimo.nomeclient,cidadecliente empréstimo.nomeclientecliente.nomecliente empréstimo cliente Ou seja, tomamos o produto cartesiano entre as relações empréstimos e cliente, depois selecionamos aquelas tuplas que pertencem a um único nome-cliente. A operação junção natural forma um produto cartesiano dos seus dois argumentos, faz uma seleção forçando uma igualdade sobre os atributos comuns em ambos os esquemas relacionais e remove as tuplas duplicadas. Assim a consulta anterior pode ser reescrita utilizando a operação junção por: nome-cliente cidade-cliente Junior Itajubá André Maria da Fé Jussara Itajubá Lislei Maria da Fé Duarte Brasópolis Davi Paraisópolis Talita Pouso Alegre Lucas Piranguinho Mariana Santa Rita Tiago Cristina Tabela3.14 – Relação resultante da expressão com junção Uma vez que os esquemas para empréstimo e cliente têm o atributo nome-cliente em comum, a operação junção combina cada par de tuplas em uma única tupla na união dos dois esquemas. Depois de executar a projeção, obtemos a relação mostrada anteriormente. Podemos agora definir formalmente a junção natural. 49 André Luís Duarte Banco de Dados Considere dois esquemas de relações R e S, que são listas de atributos. Se considerarmos os esquemas como conjuntos ao invés de listas, poderemos escreveras expressões R S 2 como sendo os atributos que são comuns a R e S, e também, R S como sendo os atributos que estão em R, S ou em ambos os esquemas. Considere agora duas relações r(R) e s(S)*1. A ligação natural de r e s, representada por , é uma relação sobre o esquema R S *2. É a projeção em R S de uma seleção sobre r s *3, onde o predicado requer que r. A s. A *4. Para cada atributo A em R S *5. Formalmente: = R S r . A1 s. A1 r . A2 s. A2 ... r . An s. An r s onde R S A1, A2,..., An Vamos propor uma ilustração a fim de facilitar o entendimento da teoria apresentada. Para isto, vamos supor os esquemas Pessoa={número, nome, idade,casado} e Ócio={dia, mês, nome, idade}. Vamos considerar também R Pessoa e SÓcio. *1 r número nome Idade casado 1 Bido 21 S 2 Muca 30 N 3 Luca 17 N Tabela3.15 – relação pessoa *2 2 s dia 03 14 21 Mês 02 03 04 nome Bido Jú Luca idade 21 18 17 Tabela3.16 – relação ócio R S = {número, nome, idade, casado, dia, mês} Note que nos referimos à intersecção e união de atributos em esquemas e não tuplas em relações. André Luís Duarte 50 [email protected] *3 rs número pessoa.nome pessoa.idade casado 1 Bido 21 S 1 Bido 21 S 1 Bido 21 S 2 Muca 30 N 2 Muca 30 N 2 Muca 30 N 3 Luca 17 N 3 Luca 17 N 3 Luca 17 N dia 03 14 21 03 14 21 03 14 21 mês 02 03 04 02 03 04 02 03 04 ócio.nome ócio.idade Bido 21 Jú 18 *4 Luca 17 Bido 21 Jú 18 Luca 17 Bido 21 Jú 18 *4 Luca 17 Tabela3.17 – relação rxs *5 R S nome, idade número 1 3 nome Bido Luca idade 21 17 casado S N Tabela3.18 – relação dia 03 21 mês 02 04 , Exemplo 10 Dê os ativos e os nomes de todas as agências que possuem depositantes, isto é, clientes com uma conta, vivendo em Brasópolis. Note que não há necessidade de colocarmos a junção entre parênteses pelo fato da operação junção natural ser associativa. nome-agência Varginha Avenida Centro ativo 8M 7.1M 90M Tabela3.19 – relação resultante da junção do Exemplo 10 Exemplo 11 Dê todos os clientes que possuem tanto uma conta como um empréstimo na agência Boa Vista. 51 André Luís Duarte Banco de Dados A consulta que foi proposta no Exemplo 9 poderia ser resolvida com a expressão acima. Este exemplo ilustra o fato de que na álgebra relacional é possível escrever diversas expressões equivalentes e bastante diferente uma da outra. Sejam r(R) e s(S) relações com nenhum atributo em comum, isto é, R S . Então, . 3.3.3.C – Operação Divisão A operação divisão é representada pelo símbolo matemático de divisão , serve para consultas onde se pode incluir a frase “para todos”. Exemplo 12 Suponha que desejamos encontrar todos os clientes que têm uma conta em todas as agências em Cristina. Podemos encontrar todos os pares nome-cliente e nome-agência para os clientes que possuem alguma conta numa agência escrevendo r 2 nomecliente,nomeagência depósito nome-cliente Lucas André Jussara Duarte Davi Samuel Mateus Mateus nome-agência Centro Morro Chic Boa Vista Varginha Boa Vista BPS Avenida Centro Tabela3.21 – relação resultante da consulta r 2 nomecliente,nomeagência depósito Podemos localizar todas as agências em Cristina utilizando a expressão r1 nome agência cidade"Cristina" agência André Luís Duarte 52 [email protected] nome-agência Avenida Centro Tabela3.20 – relação resultante da consulta r1 nome agência cidade"Cristina" agência Agora precisamos encontrar clientes que aparecem em r2 com cada nome de agência em r1, ou seja, para toda tupla existente em r1 achar uma tupla correspondente a cada valor em r2. Neste caso, podemos escrever: nomecliente,nomeagência depósito nome agência cidade"Cristina" agência O resultado para esta expressão é uma relação que possui o esquema (nome-cliente) e contém a tupla (Mateus). Formalmente, podemos escrever: Sejam r(R) e s(S) relações e seja S R . A relação r s é uma relação no esquema RS. Uma tupla t está em r s se, para cada tupla ts em s existe uma tupla tr em r satisfazendo as regras: tr S ts S tr R S t R S Exercício de Fixação Comprove baseado na definição formal anterior que o resultado para o Exemplo 12 é realmente uma relação que possui o esquema (nome-cliente) e contém a tupla (Mateus). Finalmente podemos definir a operação divisão em termos de operações básicas da seguinte forma: r s RS r RS R S r s r Exercício de Fixação Comprove baseado na expressão anterior que o resultado para o Exemplo 12 é verdadeiro. 53 André Luís Duarte Banco de Dados 3.3.3.D – Operação Atribuição Durante os estudos realizados, pudemos observar que algumas expressões podem se tornar extremamente complexas, bem mais do os exemplos vistos. Por isso é interessante escrever uma expressão da álgebra relacional em partes. Para fazer isto, utilizamos a operação atribuição, que é representada pela (seta à esquerda), para uma variável temporária do tipo relação. A operação atribuição funciona de maneira similar à atribuição em linguagem de programação, sendo assim, podemos reescrever a operação divisão utilizando a seguinte forma: temp R S r temp R S temp s r O resultado da expressão à direita da seta é atribuído para a variável de tipo relação à esquerda. Este resultado não é exibido para o usuário mas pode ser utilizado em expressões subsequentes. Com a operação atribuição as expressões da álgebra relacional podem ser escritas como um programa sequencial consistindo em uma série de atribuições seguidas por uma expressão cujo valor é exibido como resultado da consulta. A atribuição deve sempre, em caso de consultas, ser feita para uma variável temporária, pois, as atribuições para relações permanentes consistem em uma modificação no banco de dados. 3.4 – Modificação no Banco de Dados com Álgebra Relacional As modificações no banco de dados na álgebra relacional são expressões usando o operador de atribuição. As atribuições são feitas para relações presentes no banco de dados atual. 3.4.1 – Remoção Uma requisição de remoção é expressa da mesma forma que uma consulta, contudo, em vez de exibir o resultado, removem-se as tuplas da seleção. Podemos remover apenas tuplas inteiras, não sendo possível a remoção de parte das tuplas. A remoção é expressa André Luís Duarte 54 [email protected] da álgebra relacional como r r E onde r é uma relação e E é uma expressão (consulta) da álgebra relacional. Exemplo 13 Remova todas as contas de André. depósito depósito nomecliente" André" depósito Exemplo 14 Remova todos os empréstimos com número entre 1300 e 1500. depósito depósito númeroempréstimo1300númeroempréstimo1500depósito Exemplo 15 Remova todas as contas da agência localizada em Itajubá. r1 cidadeagência"Itajubá" depósito agência r 2 nomeagência,númeroconta,nomecliente,saldo r1 depósito depósito r 2 Observe que utilizamos relações temporárias a fim de simplificar nossa expressão. 3.4.2 – Inserção Utilizando a operação de inserção podemos inserir dados em uma relação especificando os valores ou escrevendo uma consulta cujo resultado é o conjunto de tuplas a serem inseridas. Obviamente, os valores dos atributos para tuplas inseridas precisam ser elementos do domínio do atributo. Na álgebra relacional expressamos uma inserção por r r E , onde r é uma relação e E é uma expressão da álgebra relacional. A expressão de uma tupla simples é expressa fazendo com que a expressão E seja uma relação constante contendo uma única tupla. Exemplo 14 55 André Luís Duarte Banco de Dados Suponha que desejamos inserir o fato de que André tem $1200 na conta 9732 na agência Boa Vista. depósito depósito " BoaVista " ,9732, " André",1200 De modo geral, na maioria dos casos, iremos inserir tuplas que são o resultado de uma consulta. Exemplo 15 Suponha que desejamos abrir uma poupança de $200 para todos os clientes com empréstimo na agência “Boa Vista”. Digamos que o número do empréstimo sirva como número da conta para novas poupanças. Teremos: r1 nome agência " BoaVista " empréstimo r 2 nome agência, número empréstimo, nome cliente r1 depósito depósito r 2 200 Como podemos observar, especificamos diversas tuplas ao invés de uma só. Cada tupla tem nome-agência (”BoaVista”), um número-empréstimo (serve como número da conta), o nome-cliente de empréstimo (o qual está sendo dado uma conta) e o saldo inicial ($200). 3.4.3 – Atualização Em muitas situações (a grande maioria) desejaremos alterar um valor de uma tupla sem mudar todos os valores da tupla. Se fizermos esta mudança usando remoção e inserção, podemos não ser capaz de reter os valores que não queremos alterar. Em vez disto, usaremos a operação alteração representada pela letra grega possui a forma (delta minúsculo) e que A Er , onde r é o nome de uma relação com atributo A que recebe o valor da expressão E. A expressão E é qualquer expressão aritmética, ou não, envolvendo constantes e atributos no esquema da relação r. Exemplo 16 Suponha que o pagamento de juros esteja sendo feito e o saldo de todas as contas seja acrescido em 5%. André Luís Duarte 56 [email protected] saldo saldo 1,05depósito A “instrução” acima é aplicada uma vez para cada tupla em depósito. Exemplo 17 Suponha que contas com saldos superiores a $10.000 recebam 6% enquanto todas as outras recebam 5%. saldo saldo 1,06 saldo10.000 depósito saldo saldo 1,05 saldo10.000 depósito Note que a ordem na qual aplicamos as operações de atualização é muito importante. Se mudarmos a ordem no exemplo anterior, uma conta cujo saldo esteja pouco abaixo de $10.000 receberia juros de 11,3%. 3.5 – Visões de Usuário Até agora operamos no nível do modelo conceitual, pois as coleções de relações as quais estamos manipulando são as relações efetivamente armazenadas no banco de dados. Sabemos que não é de interesse de empresas que todos os seus funcionários e/ou usuários vejam todo o modelo conceitual do banco de dados. Considere um caixa que precisa saber o número de empréstimo de um cliente, mas não precise saber a quantia do empréstimo. Esta é uma consideração de segurança que requer que alguns dados sejam “escondidos” de certos usuários. O caixa em questão deve ver somente a relação nome agência, empréstimo, nome cliente empréstimo Operando com visões, podemos criar coleção de relações personalizadas que combinem melhor com a intuição do usuário do que todo o modelo conceitual. Exemplo 18 Suponha que um funcionário do departamento de propaganda gostaria de ver uma relação com os clientes de cada agência. Esta relação lista as pessoas que possuem uma conta ou um empréstimo naquela agência. A relação seria resultado da expressão 57 André Luís Duarte Banco de Dados nomeagência,nomecliente depósito nomeagência,nomecliente empréstimo Qualquer relação que não faça parte do modelo conceitual, mas que é visível ao usuário como uma “relação virtual” é chamada de visão do usuário. Levando em consideração que as relações armazenadas no banco de dados podem ser modificadas, geralmente não é possível (nem recomendável) armazenar uma relação correspondente a uma visão. Logo, uma visão deve ser recomposta para cada vez que uma expressão se refira a ela. Quando uma visão é definida, o banco de dados necessita armazenar a definição propriamente dita da visão. Portanto, esta definição não é uma expressão da álgebra relaciona, ao contrário, uma definição de visão produz o armazenamento de uma expressão que deve substituir referências à visão em consultas que a empregam. 3.5.1 – Definição de Visão Para definir uma visão, precisamos dar a ela um nome e estabelecer a consulta que computa a visão. A forma da instrução é create view u as <expressão de consulta> onde <expressão de consulta> é qualquer expressão de consulta válida da álgebra relacional. O nome da visão é representado por u. Considere a visão consistindo em agências e seus clientes. Assuma que desejamos que esta visão se chame todos-clientes. Definimos esta visão como: create view todos-clientes as nome agência, nome cliente depósito nome agência, nome cliente empréstimo Uma vez que seja definida uma visão, o nome pode ser usado para referenciar a relação virtual que a visão gera. Podemos achar todos os clientes da agência Boa Vista escrevendo nomecliente nome agência"BoaVista" todos clientes . André Luís Duarte 58 [email protected] 3.5.2 – Atualizações com Visões e Valores Vazios Pudemos ver que as visões são muito úteis para auxiliar nas consultas no banco de dados. Porém, um problema significativo ocorre quando utilizamos visões para efetuar inserções, atualizações e remoções no banco de dados. A dificuldade é que para efetuar uma modificação, a estrutura da visão deve ser traduzida para uma modificação da estrutura das relações presentes no modelo conceitual do banco de dados. Exemplo 18 Considere o caixa que precisa ver todos os dados de empréstimo na relação empréstimo, exceto quantia-empréstimo. Digamos que info-empréstimo seja o nome da visão dada ao caixa. Esta será definida como: create view info-empréstimo as nome agência, númeroempréstimo, nomecliente empréstimo Uma vez que definimos que um nome de visão pode aparecer em qualquer lugar onde é permitido o nome de uma relação, o caixa poderá escrever info empréstimo info empréstimo " BoaVista ",3," João" Esta inserção precisa ser representada por uma inserção na relação empréstimo. No entanto, para inserir uma tupla em empréstimo, precisamos ter algum valor para quantia. Existem duas abordagens razoáveis para orientar esta inserção: Rejeitar a inserção e dar uma mensagem de erro ao usuário; Inserir uma tupla {(“BoaVista”,3,”João”,vazio)} na relação empréstimo; O símbolo vazio significa que este é desconhecido ou que ele não existe. Todas as comparações envolvendo vazio são falsas por definição. create viewcidade-agência as nome agência,cidade agênciaempréstimo cliente 59 André Luís Duarte Banco de Dados Esta visão lista as cidades nas quais vivem clientes com um empréstimo. Considere a seguinte inserção por meio dessa visão. cidade agência cidade agência " Avenida" , " StaRita " O único método possível para inserirmos tuplas na relação empréstimo e cliente é inserirmos {(“Avenida”,vazio,vazio,vazio)} na relação empréstimo e na relação cliente inserirmos {(vazio,vazio,”StaRita”)}. Então obtemos as relações nome-agência Centro BPS Boa Vista Centro Morro Chic Varginha Canudos Sul Centro Boa Vista Avenida Avenida número-empréstimo 17 23 15 14 93 11 29 16 18 25 10 nulo nome-cliente quantia Junior 1000 André 2000 Jussara 1500 Ana 1500 Lislei 500 Duarte 900 Davi 1200 Talita 1300 Lucas 2000 Mariana 2500 Tiago 2200 nulo nulo Nome-cliente rua cidade-cliente Junior Rodrigues Itajubá André Seabra Maria da Fé Jussara Rodrigues Itajubá Lislei Seabra Maria da Fé Samuel Cardoso Pouso Alegre Duarte Arlindo Brasópolis Davi Zaroni Paraisópolis Talita Major Brasópolis Lucas Coronel Piranguinho Mariana Nova Sta Rita Tiago Corrêa Cristina Mateus Lamounier Brasópolis Sta Rita nulo nulo Tabela3.22 – Tuplas inseridas em empréstimo e cliente André Luís Duarte 60 [email protected] O resultado é insatisfatório. Se fizermos uma consulta com a expressão nomeagência,cidadecliente cidade agência , o resultado não incluirá a tupla inserida {(“Avenida”,”StaRita”)}, pois todas as comparações envolvendo vazio são definidas como falsas. 61 André Luís Duarte Banco de Dados Capítulo 4 – Linguagem Relacional Comercial 4.1 – Introdução Vimos no capítulo 3 um exemplo de linguagem formal que fornece uma notação concisa para representar consultas, entretanto, sistemas comerciais de banco de dados requerem uma linguagem mais “amigável” ao usuário. As linguagens relacionais comerciais se baseiam em linguagens formais (álgebra relacional, cálculo relacional de tuplas e cálculo relacional de domínios) ou na combinação destas na maneira de implementar a manipulação de banco de dados. Podemos citar como exemplos, a linguagem SQL, QBE e Quel, para manipulação de banco de dados. Embora seja comum referenciá-las como “linguagens de consulta”, elas possuem muitas outras capacidades. Por exemplo, elas incluem recursos para definição da estrutura de dados, modificação dos dados e recursos para especificar restrições de segurança. 4.2 – SQL 4.2.1 – Histórico A linguagem SQL original, foi desenvolvida no laboratório de pesquisas da IBM em San Jose. Originalmente denominada “Sequel”, foi implementada como parte do projeto System R no início dos anos 70. A linguagem evoluiu desde então e passou a ser chamada SQL. Em 1986, o American National Standard Institute (ANSI) publicou um primeiro padrão para a linguagem SQL. Rapidamente a linguagem estabeleceu-se claramente como uma linguagem padrão para banco de dados relacional. A linguagem SQL3 possui diversas partes. Data Definition Language (DDL) – fornece comandos para definição de esquemas de relação, remoção de relação, criação de índices e modificação de esquemas de relação. 3 Dependendo do SGBD utilizado, a SQL poderá possuir diferenças sutis em sua capacidade de manipulação. André Luís Duarte 62 [email protected] Interactive Data Manipulation Language (DML) – inclui uma linguagem de consulta baseada na álgebra relacional e no cálculo relacional de tupla. Compreende também comandos para inserir, remover e modificar tuplas em um banco de dados. Embeded Data Manipulation Language – a forma embutida da SQL é projetada para utilização em linguagens de programação como Pascal, Fortran, C, etc. Views Definitions – a SQL DDL inclui também comandos para definição de visualizações. Authorization – a SQL DDL inclui comandos para especificação de autorização de acesso a relações e visões. Integrity – a linguagem SQL original incluía comandos para especificação de instruções complexas de integridade. As versões da SQL fornecem apenas uma forma limitada de verificação de integridade. Transaction control – a SQL inclui comandos para especificação do início e fim de transações. Diversas implementações permitem o trancamento explicito de dados para controle de concorrência. 4.2.2 – Estrutura básica A estrutura básica de uma expressão SQL consiste em três cláusulas: select, from e where. A cláusula “select” corresponde à operação projeção da álgebra relacional. É usada para listar os atributos desejados no resultado de um a consulta. A cláusula “from” corresponde á operação produto cartesiano da álgebra relacional. Ela lista as relações a serem examinadas na avaliação da expressão. A cláusula “where” corresponde ao predicado de seleção da álgebra relacional. Consiste em um predicado envolvendo atributos de relação que aparecem na cláusula “from”. Uma consulta típica SQL assume a forma: select A1, A2, ..., An from r1, r2, ..., rm where P Listagem 4.1 – Forma geral de uma consulta SQL. 63 André Luís Duarte Banco de Dados Cada “Ai” representa um atributo e cada “ri” é uma relação. “P” é um predicado. Esta expressão é equivalente à expressão da álgebra relacional A1, A2,...,An p r1 r 2 ... rm Figura 4.1 – Expressão equivalente à uma consulta SQL. Caso a cláusula where seja omitida, o predicado “P” é verdadeiro. A lista “A1,A2,...An” pode ser substituída pelo “*” indicando todos os atributos de todas as relações presentes na cláusula from. O resultado de uma consulta SQL é, obviamente, uma relação. Exemplo 1 Dê os nomes de todas as agências na relação depósito. select nome_agência from depósito Listagem 4.2 – Exemplo de seleção simples. 4.2.3 – Operações de conjuntos e tuplas duplicadas Linguagens de consultas formais consideram relações como sendo conjuntos, logo, não há ocorrência de tuplas duplicadas na relação. Na prática, em sistemas comerciais, esta eliminação é dispendiosa e na maioria das vezes desnecessária. Todavia, a SQL permite duplicações em relações. Nos casos em que desejamos forçar a eliminação de duplicações, inserimos a palavra reservada “distinct” depois da cláusula select. Logo a consulta do exemplo anterior seria: select distinct nome_agência from depósito Listagem 4.3 – Eliminação de duplicações em um select. 4.2.4 – Operações com conjuntos A SQL original inclui as operações union, intersect e minus que operam sobre relações. Os exemplos aqui são os contidos no capítulo 3. a) Localize todos os clientes que possuem uma conta na agência “Morro Chic”. select distinct nome_cliente from depósito where nome_agência = “Morro Chic” Listagem 4.4 – Uso da cláusula “where” na relação depósito. b) Podemos encontrar todos os clientes com um empréstimo na agência “Morro Chic”. André Luís Duarte 64 [email protected] select distinct nome_cliente from empréstimo where nome_agência = “Morro Chic” Listagem 4.4 – Uso da cláusula “where” na relação empréstimo. c) Para achar todos os clientes com um empréstimo, uma conta, ou ambos na agência “Morro Chic”. (select distinct nome_cliente from depósito where nome_agência = “Morro Chic”) union4 (select distinct nome_cliente from empréstimo where nome_agência = “Morro Chic”) Listagem 4.5 – Uso da operação union. d) Da mesma forma, para achar todos os clientes que possuem um empréstimo e uma conta na agência “Morro Chic” escrevemos: (select distinct nome_cliente from depósito where nome_agência = “Morro Chic”) intersect (select distinct nome_cliente from empréstimo where nome_agência = “Morro Chic”) Listagem 4.6 – Uso da operação intersect. e) Para encontrar todos os clientes da agência “Morro Chic” que possuem uma conta mas não possuem um empréstimo escrevemos: (select distinct nome_cliente from depósito where nome_agência = “Morro Chic”) minus (select distinct nome_cliente 4 Como padrão, a operação union elimina tuplas duplicadas. Para reter a duplicação precisamos utilizar union all no lugar de union. 65 André Luís Duarte Banco de Dados from empréstimo where nome_agência = “Morro Chic”) Listagem 4.7 – Uso da operação minus. Apesar da operação union fazer parte da SQL padrão ANSI, diversos outros padrões não dão suporte a ela. As operações intersect e minus faziam parte da SQL original (Sequel), mas não foram incluídas no padrão ANSI. 4.2.5 – Predicados e junções A SQL original não possui uma representação da operação junção natural. Porém, é relativamente simples escrever uma expressão em SQL para a junção natural. Logo, se temos a expressão nome _ cliente,cidade_ cliente empréstimo cliente Podemos construir a expressão equivalente SQL: select distinct cliente.nome_cliente, cidade_cliente from empréstimo, cliente where empréstimo.nome_cliente = cliente.nome_cliente Listagem 4.8 – Representação da junção natural em SQL. Exemplo 2 Dê o nome, a cidade de todos os clientes com empréstimos na agência “Boa Vista”. Para efetuarmos essa consulta, precisamos enunciar duas restrições na cláusula where utilizando o conector lógico and. select distinct cliente.nome_cliente, cidade_cliente from empréstimo, cliente where empréstimo.nome_cliente = cliente.nome_cliente and nome_agência = “Boa Vista” Listagem 4.9 – Utilização do conector lógico and. Em SQL, podemos utilizar os conectivos lógicos and, or e not, expressões aritméticas envolvendo os operadores +, -, *, / em constantes ou valores de tuplas. Algumas implementações de SQL incluem funções aritméticas especiais para tipos como data, tempo, dinheiro, cadeia de caractere, etc. André Luís Duarte 66 [email protected] A SQL inclui um operador de comparação “between” para simplificar algumas construções da cláusula where que especificam que um valor esteja entre outros dois. Exemplo 3 Encontre os números de contas cujos saldos sejam maiores do que $900,00 e menores do que $10.000,00 inclusive. Teremos para isto a expressão select número_conta from depósito where saldo between 900 and 10000 Listagem 4.10 – Utilização do operador between. Da mesma forma podemos usar o operador de comparação not between. O SQL possui também um operador de comparação de cadeia de caracteres. Os padrões para comparação são descritos utilizando dois tipos de caracteres juntamente com o operador de comparação “like”: O caractere “%” equivale a qualquer subcadeia; O caractere “_” equivale a qualquer caractere; Os padrões são “case sensitive”. Exemplo 4 Dê os nomes dos clientes cujas ruas incluem a subcadeia “en”. Teremos a expressão: select nome_cliente from cliente where rua like “%en%” Listagem 4.11 – Utilização do operador de comparação like. poderíamos ter as seguintes expressões e suas equivalências: Expressão “Boa%” %en% _en% “_ _ _” “_ _ _%” Equivalência Qualquer cadeia começada por “Boa”. Qualquer cadeia contendo a subcadeia “en” (Centro, Avenida). Qualquer cadeia contendo a subcadeia “en” iniciando na segunda posição. Qualquer cadeia contendo exatamente três caracteres. Qualquer cadeia contendo pelo menos três caracteres. Tabela 4.1 – Expressões contendo operadores de comparação de cadeias de caracteres. 67 André Luís Duarte Banco de Dados Para que os padrões possam ser utilizados como qualquer caractere, devemos especificar um caractere denominado “caractere de escape” através da palavra chave “escape”. Ilustramos definindo o caractere “\” (barra invertida) como sendo o caractere de escape nos seguintes padrões: Expressão like “ab\%cd%” escape “\” like “ab\\%cd%” escape “\” Equivalência Todas as cadeias começada por “ab%cd”. Todas as cadeias começada por “ab\cd”. Tabela 4.2 – Expressões contendo um caractere de escape. A SQL permite a busca por não equivalência utilizando o operador de comparação not like. 4.2.6 – Pertinência a conjuntos O conectivo “in” testa a pertinência a um conjunto onde o conjunto é uma coleção de valores produzidos por uma cláusula select. O conectivo “not in” testa a não pertinência de um conjunto. Considere a consulta d) anterior, podemos reescreve-la da seguinte forma select distinct nome_cliente from empréstimo where nome_agência = “Morro Chic” and nome_cliente in ( select nome_cliente from depósito where nome_agência = “Morro Chic”) Listagem 4.12 – Utilização do conectivo in. Podemos também testar a pertinência a uma relação arbitrária. A SQL usa a notação <v1, v2, ..., vn> para representar uma tupla de n elementos contendo os valores v1, v2, ..., vn. Podemos reescrever a consulta anterior como select distinct nome_cliente from empréstimo where nome_agência = “Morro Chic” and <nome_agência, nome_cliente> in ( select nome_agência, nome_cliente from depósito) Listagem 4.13 – Utilização de uma tupla de n elementos. André Luís Duarte 68 [email protected] Note que podemos escrever a mesma consulta de diversas formas em SQL, poderíamos reescrever a consulta e) da seguinte forma select distinct nome_cliente from depósito where nome_agência = “Morro Chic” and nome_cliente not in ( select nome_cliente from empréstimo where nome_agência = “Morro Chic”) Listagem 4.14 – Utilização do conectivo not in. 4.2.7 – Variáveis tupla Uma variável tupla precisa estar associada a uma relação particular. As variáveis tuplas são definidas na cláusula from. Assim podemos reescrever a consulta do exemplo 2 como select distinct c.nome_cliente, c.cidade_cliente from empréstimo e, cliente c where e.nome_cliente = c.nome_cliente and e.nome_agência = “Boa Vista” Listagem 4.15 – Utilização de variáveis tupla. A variável tupla é definida na cláusula from colocando-a logo após o nome da relação à qual ela está associada separada por um espaço. A variável tupla além de possibilitar uma simplificação em consultas extensas onde apareçam várias vezes o nome da relação, elas são essenciais na comparação de duas tuplas de uma mesma relação5. Exemplo 5 Ache todos os clientes que possuem uma conta em alguma agência na qual “Lucas” tenha uma conta. select distinct t.nome_cliente from depósito s, depósito t where s.nome_cliente= “Lucas” and s.nome_agência = t.nome_agência Listagem 4.15 – Utilização de variáveis tuplas para a mesma relação. 5 Isto era feito utilizando a operação renomear na álgebra relacional. 69 André Luís Duarte Banco de Dados 4.2.8 – Comparação de conjuntos Utilizamos o conectivo in quando desejamos testar a igualdade entre os valores de atributos. Porém, vamos supor que desejássemos os nomes de todas as agências que possuem ativos maiores do que alguma agência localizada em Itajubá. Podemos obter o resultado através da expressão select distinct t.nome-agência from agência t, agência s where t.ativos > some ( select ativos from agência where cidade_agência = “Itajubá”) Listagem 4.16 – Utilização do conectivo some. A consulta mais interna gera todos os valores de ativos para as agências em Itajubá, a comparação >some, na cláusula where do select externo é verdadeira se o valor da tupla ativos for maior do que algum (pelo menos um) elemento do conjunto de todos os ativos. Podemos utilizar também <some, >=some, <=some e <>some. Observe que =some é idêntico a in. Por outro lado, e se nossa consulta fosse encontrar os nomes de todas as agências que possuem ativos maiores do que todas as agências em Itajubá. A construção “> all” corresponde à frase “maior do que todos”. Logo podemos escrever a consulta como select nome_agência from agência where ativos >all ( select ativos from agência where cidade_agência = “Itajubá”) Listagem 4.17 – Utilização da construção >all. Também podemos usar construções <all, >=all, <=all, =all e <>all. As construções in, >some, >all e assim por diante nos permite testar um único valor contra elementos de um conjunto inteiro. Como o select gera um conjunto de tuplas, podemos às vezes, quere comparar conjuntos para determinar se um conjunto contém todos os elementos de um outro conjunto. Para isto usamos as construções contains e not contains. André Luís Duarte 70 [email protected] Exemplo 6 Dê todos os clientes que possuem uma conta em todas as agências localizadas em “Maria da Fé”. Para cada cliente, precisamos ver se o conjunto de todas as agências na qual um cliente possui uma conta contém o conjunto de todas as agências em “Maria da Fé”. select distinct e.nome_cliente 1 from depósito s where ( select t.nome_agência 2 from depósito t where s.nome_cliente = t.nome_cliente) contains ( select nome_agência 3 from agência where cidade_agência = “Maria da Fé”) Listagem 4.18 – Utilização da construção cotains. A subconsulta (3) fornece todas as agências de “Maria da Fé”. A subconsulta (2) fornece todas as agências nas quais s.nome_cliente têm uma conta. Assim a consulta externa (1) pega cada cliente e testa se o conjunto de todas as agências em que cada cliente possui uma conta contém o conjunto de todas as agências em “Maria da Fé”. 4.2.9 – Teste de relações vazias O SQL inclui um recurso para testar se uma consulta possui alguma tupla em seus resultados. A construção “exists” retorna true se o argumento da consulta é não vazia. Podemos reescrever a consulta d) da seguinte forma. select nome_cliente from cliente c where exists( select * from depósito d where d.nome_cliente = c.nome_cliente and nome_agência = “Morro Chic”) and exists( select * from empréstimo e 71 André Luís Duarte Banco de Dados where e.nome_cliente = c.nome_cliente and nome_agência = “Morro Chic” Listagem 4.19 – Utilização da construção exists. A não existência de uma tupla em uma subconsulta pode ser testada usando-se a construção not exists. Suponha que desejamos todos os clientes da agência “Morro Chic” que têm uma conta mas não um empréstimo nesta agência. select nome_cliente from cliente c where exists( select * from depósito d where d.nome_cliente = c.nome_cliente and nome_agência = “Morro Chic”) and not exists( select * from empréstimo e where e.nome_cliente = c.nome_cliente and nome_agência = “Morro Chic”) Listagem 4.20 – Utilização da construção not exists. Finalizando, podemos utilizar a construção minus para reescrever o código do Exemplo 6 como segue. select distinct s.nome_cliente from depósito s where not exists(( select nome_agência from agência where cidade_agência = “Maria da Fé”) minus( select t.nome_agência from depósito t where s.nome_cliente = t.nome_cliente)) Listagem 4.21 – Utilização da construção minus André Luís Duarte 72 [email protected] Exercício de fixação Analise os resultados das expressões para o código da Listagem 4.21 e mostre que retornam realmente o resultado obtido na consulta original. 4.2.10 – Ordenação da exibição de tuplas O SQL fornece algum controle sobre a ordem na qual as tuplas serão exibidas. A cláusula “order by” ocasiona o aparecimento de tuplas no resultado de uma consulta em uma ordem determinada. Para listar em ordem alfabética todos os clientes, por exemplo, escrevemos: select distinct nome_cliente from empréstimo where nome_agência = “Centro” order by nome_cliente Listagem 4.22 – Utilização da cláusula order by. Por padrão o SQL classifica as tuplas em ordem crescente, porém, podemos utilizar desc para especificar a ordem decrescente como classificação de tuplas. select * from empréstimo order by quantia desc, número_empréstimo asc Listagem 4.23 – Utilização da construção desc. 4.2.11 – Funções agregadas A SQL oferece a possibilidade de computar funções em grupos de tuplas usando a cláusula group by. Os atributos utilizados na cláusula group by são usados para formarem grupos de tuplas. O SQL também inclui função para computar a média (avg), mínimo (min) máximo (max), total (sum) e contar (count). Estas operações são chamadas funções de agregação porque operam em um grupo de tuplas e geram um único valor. Exemplos f) Suponha que desejamos encontrar o saldo médio de conta em cada agência. select nome_agência, avg(saldo) from depósito group by nome_agência Listagem 4.24 – Função avg. 73 André Luís Duarte Banco de Dados g) Poderíamos também querer saber o número de depositantes de cada agência. select nome_agência, count(distinct nome_cliente) from depósito group by nome_agência Listagem 4.25 – Função count. h) Um caso interessante seria listar as agências nas quais a média dos saldos é maior do que $1200. Note que a condição aqui é aplicada ao grupo em vez de a tupla simples. Para isto, utilizamos a cláusula “having”. Os predicados na clausula having são aplicados depois da formação dos grupos para que funções de agregação possam ser usadas, assim, teremos o código select nome_agência, avg(saldo) from depósito group by nome_agência having avg(saldo) > 1200 Listagem 4.26 – Utilização da cláusula having. i) Dê as agências com a maior média de saldos. Em SQL as funções de agregação não podem ser compostas. Isto significa que a construção max(avg(...)) não será permitida. A estratégia é encontrar as filias cuja média de saldo é maior ou igual a todas as médias de saldo. select nome_agência from depósito group by nome_agência having avg(saldo) >= all( select avg(saldo) from depósito group by nome_agência) Listagem 4.27 – Exemplo da utilização de função de agregação avg. Às vezes, desejamos tratar toda a relação como um único grupo, pra isto, não incluímos a cláusula group by. A função de agregação count é usada para contar o número de tuplas numa relação. A notação para isto em SQL é count(*). André Luís Duarte 74 [email protected] Se uma cláusula where e uma cláusula having aparecem numa mesma consulta, o predicado na cláusula where é aplicado primeiro. As tuplas que satisfazem o predicado where são então colocadas em grupo por uma cláusula group by e então a cláusula having é utilizadas para cada grupo. Para ilustrar a utilização da cláusula where e having na mesma consulta, considere a necessidade de se obter a média dos saldos de todos os depositantes que vivem em “Maria da Fé” e têm pelo menos três contas. select avg(saldo) from depósito, cliente where depósito.nome_cliente = cliente.nome_cliente and cidade_cliente = “Maria da Fé” group by depósito.nome_cliente having count(distinct número_conta) >= 3 Listagem 4.28 – Utilização da construção where e having. 4.2.12 – A potência de SQL A SQL é tão poderosa em expressividade quanto a álgebra relacional. A SQL inclui as operações da álgebra relacional fundamental. A SQL permite resultados intermediários para ser guardados em relações temporárias.assim, podemos codificar qualquer expressão da álgebra relacional na SQL. Assim a SQL é rigorosamente mais poderosa do que a álgebra relacional. Muitas versões da SQL permitem que consultas em SQL sejam feitas a partir de um programa escrito em uma linguagem de uso genérico como Pascal, Fortran, PL/1, C, etc. A SQL não é tão poderosa quanto uma linguagem de programação, isto é, existem consultas e construções que podem ser expressas em uma linguagem e não podem ser implementadas em SQL. 4.2.13 – Modificação do Banco de Dados Até o momento, nos restringimos em consultar informações do banco de dados. Mostramos agora como adicionar, remover ou alterar as informações utilizando a SQL. 75 André Luís Duarte Banco de Dados 4.2.13.1 – Remoção (delete) Uma requisição de remoção é expressa da mesma forma que uma consulta. Podemos remover apenas tuplas inteiras; não é possível remover valores em apenas alguns atributos. Em SQL uma remoção é expressa como delete r where P Listagem 4.29 – Expressão geral da remoção. Onde r representa uma relação e P representa um predicado. As tuplas t de r para qual P(t) é verdadeiro são removidas da relação r. O comando delete opera em apenas uma relação. Se desejamos remover tuplas em n relações, devemos utilizar um comando delete para cada relação. O predicado da cláusula where pode ser tão complexo quanto uma cláusula where em um select. Podemos também possuir um construção de delete sem a cláusula where. Com isso a requisição delete empréstimo remove todas as tuplas da relação empréstimo6. Outros exemplos de requisições de remoção em SQL. delete depósito where nome_cliente = “Smith” delete empréstimo where número_empréstimo between 1300 and 1500 delete depósito where nome_agência in( select nome_agência from agência where cidade_agência = “Itajubá”) Listagem 4.30 – Exemplos de requisição de remoção de tuplas 6 Sistemas bem projetados requerem uma confirmação do usuário antes de executar comandos que possam remover ou alterar informações armazenadas em qualquer parte do sistema. André Luís Duarte 76 [email protected] Devemos tomar cuidado quando o comando delete possuir uma cláusula select embutida que faça referência à relação na qual as tuplas serão removidas, podemos encontrar prováveis anomalias. delete depósito where saldo < ( select avg(saldo) from depósito) Listagem 4.31 – Possível anomalia em expressões aninhadas. Exercícios de fixação Descreva o que irá ocorrer quando as expressões da Listagem 4.30 forem executadas. Descreva a anomalia que ocorre na execução da expressão contida na Listagem 4.31. A SQL padrão não permite que a anomalia descrita anteriormente ocorra, pois na realidade as tuplas que satisfaçam às condições são, primeiramente, marcadas e depois que o processamento da requisição termina é que as tuplas serão removidas. 4.2.13.2 – Inserção (insert) Para inserirmos um dado na relação, ou especificarmos uma tupla para ser inserida ou escrevermos uma consulta cujo resultado será inserido na relação utilizamos o comando insert. Para isto, os valores dos atributos para tuplas inseridas precisam ser membros do domínio do atributo. Da mesma forma, as tuplas inseridas precisam ser do mesmo tipo. A instrução mais simples é uma requisição para inserir uma tupla. insert into depósito values(“Boa Vista”, 9732, “Leonardo”, 1200) Listagem 4.32 – Expressão mais simples para uma inserção. No exemplo anterior, os valores inseridos estão dispostos na ordem em que os atributos aparecem no esquema relacional. Porém podemos não lembrar a ordem dos atributos, por isso a SQL permite que os atributos sejam especificados como parte da instrução SQL. 77 André Luís Duarte Banco de Dados insert into depósito(número_conta, nome_cliente, saldo, nome_agência) values(9732, “Leonardo”, 1200, “Boa Vista”) Listagem 4.33 – Utilização do nome dos atributos na requisição de inserção. Podemos também desejar inserir tuplas baseadas no resultado de uma consulta. Podemos então ter a expressão insert into depósito select nome_agência, número_empréstimo, nome_cliente, 200 from depósito where nome_agência = “Boa Vista” Listagem 4.34 – Inserção do resultado de uma consulta. A SQL padrão proíbe ao select embutido referenciar as relações nas quais tuplas estão sendo inseridas para que não ocorram inserções do tipo mostrados na listagem 4.35. insert into depósito select * from depósito Listagem 4.35 – Construções proibidas no SQL padrão. Exercício de Fixação Descreva o que irá ocorrer após a execução das requisições contidas nas Listagens 4.34 e 4.35. 4.2.13.2 – Atualização (update) Em muitas situações, desejaremos alterar o valor de alguns atributos de algumas tuplas, sem mudar toda a tupla. Isto só pode ser feito utilizando a instrução update. Como no caso das instruções anteriores, podemos escolher as tuplas que serão atualizadas utilizando uma consulta válida. update depósito set saldo = saldo * 1.06 Listagem 4.36 – Atualização simples André Luís Duarte 78 [email protected] A instrução anterior é aplicada uma vez para cada tupla na relação depósito. update depósito set saldo = saldo * 1.06 where saldo > 10000 update depósito set saldo = saldo * 1.05 where saldo <= 10000 Listagem 4.36 – Utilização do comando update com where. Como é o caso do delete e do delete, qualquer select embutido dentro de um update não deve referenciar a relação que está sendo atualizada. Suponha a atualização a seguir update depósito set saldo = saldo * 1.05 where saldo > select avg(saldo) from depósito Listagem 4.37 – Exemplo de anomalia com update. Exercício de Fixação A instrução da Listagem 4.36 prevê um abono de 6% nos saldos acima de $10.000 e de 5% nos saldos abaixo de $10.000. O que poderá ocorrer se a ordem em que a atualização é executada for invertida? A instrução na Listagem 4.37 deveria pagar 5% de juros sobre contas cujos saldos sejam maiores do que a média de saldos. Porque esta rotina na faz o que é desejado? 4.2.14 – Valores Vazios Nossa discussão até agora sempre considerou que as tuplas estavam “completas”, ou seja, não possuíam valores vazios. Em SQL, podemos atribuir valores a apenas alguns atributos do esquema7, os demais receberão valores nulos, que no SQL padrão, são representados por null. Considere o comando insert into depósito values (“Centro”, null, “Luciana”, 1200) Listagem 4.38 – Exemplo da inserção de um valor nulo. 7 Veremos mais adiante como não permitir que isto ocorra em casos onde desejamos que o atributo seja preenchido. 79 André Luís Duarte Banco de Dados Neste caso sabemos que Luciana possui uma conta na Agência Centro e possui saldo de $1.200,00, mas não sabemos qual é o número desta conta. Logo, considere uma consulta para verificar a tupla cujo número da conta é 1700. Como o número da conta de Luciana não é conhecido, não podemos determinar se ele é igual a 1700. Todas as comparações envolvendo null, por definição resultam em false, inclusive o teste de igualdade (número_conta = null). para saber se um determinado atributo possui o valor null, escrevemos select * from empréstimo where quantia is null Listagem 4.39 – Testando a presença de valores nulos nas relações. O predicado is not null testa a ausência de um valor vazio. Todas as operações de agregação, ignoram tuplas com valores vazios, exceto o count, nos atributos de seus argumentos. Isto gera bastante problemas ao utilizarmos funções de agregação, por isto devemos projetar de forma adequada nosso sistema. Exercício de Fixação Cite um exemplo de problema que você identifica quando ocorre a utilização de funções de agregação e a presença de valores vazios em uma relação. 4.2.15 – Visões Para criarmos uma visão em SQL devemos utilizar o comando create view da seguinte forma create view v as <expressão de consulta> onde v é o nome da visão e <expressão de consulta> é qualquer expressão de consulta válida. Exemplo 7 Crie a visão consistindo em nomes de agências e nomes de clientes. Assuma que desejamos esta visão sendo chamada todos_clientes. create view todos_clientes as (select nome_agência, nome_cliente from depósito) André Luís Duarte 80 [email protected] union (select nome_agência, nome_cliente from empréstimo) Listagem 4.40 – Exemplo de criação de visão. As anomalias da atualização de uma visão discutida no capítulo 3, também ocorrem em SQL. Como o SQL permite que o nome de visão apareça em qualquer lugar onde possa aparecer o nome de relação, utilizar visão em comandos insert, delete e update é conceitualmente possível, mas veremos na prática que é bom evitar este tipo de construção. Como resultado, muitos sistemas baseados em SQL impõem uma restrição para modificações com visões, a saber; “Uma modificação é permitida por uma visão apenas se a visão em questão está definida em termos de uma única relação do banco de dados relacional”. 4.2.16 – Definição de Dados Até o momento, assumimos relações que existiam previamente. Logicamente estas relações (ou seus esquemas relacionais) precisa ser especificada para o sistema por meio de uma linguagem de definição de dados (DDL). A SQL DDL permite a especificação não apenas de um conjunto de relações, mas também de informações sobre cada relação, incluindo: O esquema de cada relação; O domínio dos valores associados a cada atributo; O conjunto de índices a ser mantido para cada relação; Informações sobre segurança e autorização de acesso para cada relação; Restrições de integridade; A estrutura física de armazenamento de cada relação no disco. Vamos neste ponto nos ater somente a definição de esquema e inserir os outros conceitos na medida em que forem desenvolvidos. Uma relação em SQL é definida utilizando o comando create table: create table r (A1 D1, A2 D2, ..., An Dn) 81 André Luís Duarte Banco de Dados onde r é o nome da relação, cada Ai é o nome do atributo no esquema relacional r e Di é o tipo de valores de dados do domínio de Ai. Podemos inserir algumas restrições de integridade com o comando create table que ainda serão abordados. Uma vez criada a relação, esta se encontra vazia. Devemos utilizar o comando insert a fim de popular nossa relação com os dados. A forma mais geral para o comando insert é: insert into r values(v1, v2, ..., v3) onde r é o nome da relação que está sendo populada, vi são os valores para cada campo dentro do esquema de r. Existem algumas variações dependendo do SGBD utilizado, estas sempre que possível serão mencionadas durante as aulas e colocadas no material de apoio (arquivos PPT). Para remover uma relação de um banco de dados SQL usamos o comando drop table no seguinte formato: drop table r onde r é o nome da tabela a ser apagada do banco de dados. Alguns sistema SQL possuem o comando delete r, onde r é o nome da relação que será deletada. Neste ultimo caso, todas as tuplas da relação são apagadas, porém o esquema da relação continua, podendo ser populado novamente. O comando alter table geralmente é utilizado para adicionar atributos em um esquema existente. Todas as tuplas na relação recebem valor null. A forma mais geral para o comando é: alter table r add A D onde r é a relação existente, A e D são, consecutivamente, o nome do atributo e seu domínio. O comando alter table aparece em muitos sistemas SQL, porém não faz parte do SQL padrão. André Luís Duarte 82 [email protected] Capítulo 5 – Restrições de Integridade 5.1 – Introdução As restrições de integridade fornecem meios para assegurar que mudanças feitas no banco de dados por usuários autorizados não resultem na perda da consistência dos dados. Assim, as restrições de integridade resguardam o banco de dados contra danos acidentais. Conhecemos algumas destas restrições em capítulos anteriores. São elas: Declaração de chave: O conjunto de inserções e atualizações válidas é restringido àquelas que não criam duas entidades com o mesmo valor de chave candidata; Forma de um relacionamento: Um relacionamento um para um ou um para muitos restringe o conjunto de relacionamentos válidos entre entidades de uma coleção de conjunto de entidades; Geralmente uma restrição de integridade pode ser um predicado arbitrário que reaplica ao banco de dados. No entanto os predicados arbitrários podem ser custosos para ser testado. Para isto apresentamos formas mais simples e que possuem um custo bem menor para ser testada. 5.2 – Restrições de domínio Vimos nos capítulos anteriores que, para todo atributo de uma relação, precisamos ter um domínio relacionado. Restrições de domínio é a forma mais elementar de restrições de integridade. Elas podem ser testadas facilmente pelo sistema cada vez que um novo item de dado é inserido no banco de dados. 5.2.1 – Tipos de Domínio É possível que diversos atributos tenham o mesmo domínio. Por exemplo, nome_cliente e nome_funcionário podem ter o mesmo domínio. Os domínios de saldo e nome_agência, certamente precisam ser diferentes. É talvez menos claro se nome_agência e nome_cliente devem ter o mesmo domínio. No nível de implementação, tanto nome de agência quanto nome de cliente são cadeias de 83 André Luís Duarte Banco de Dados caracteres. Contudo, não podemos considerar como válida (normal) a consulta “dê todos os clientes que possuem o mesmo nome de sua agência” como sendo uma consulta com sentido. Assim se analisarmos o banco de dados no nível conceitual em vez de no nível físico, nome_cliente e nome_agência certamente devem ter domínios distintos. A própria definição de restrições de domínio permite testar os valores inseridos no banco de dados e também testar consultas para assegurar que as comparações façam sentido. 5.2.2 – Tipos de domínios em SQL A SQL padrão suporta um conjunto restrito de tipos de domínio: Cadeia com comprimento de caracteres fixo, com comprimento especificado pelo usuário; Número em ponto fixo, com precisão especificada pelo usuário; Inteiro (um conjunto finto dos inteiros que é dependente da máquina); Número de ponto flutuante, com precisão especificada pelo usuário; Ponto flutuante e números de ponto flutuante com dupla precisão, com precisão dependente da máquina; Diversas implementações da SQL incluem um tipo data. Este tipo é usado para representar datas e permitir processamento baseados em datas. Por exemplo, se x e y são do tipo data, então x - y retorna o número de dias da data x até a data y. 5.2.3 – Valores vazios Vimos que a inserção de tuplas incompletas pode introduzir valores vazios no banco de dados. Podem ser problemáticos permitir a inserção de valores vazios, principalmente em atributos chave do nosso sistema. Em casos como este desejamos proibir valores vazios, restringindo o domínio de nome_cliente para excluir valores vazios. A SQL padrão permite a declaração de domínio de um atributo inclua a especificação not null, proibindo assim a presença de valores nulos neste atributo. Qualquer alteração no banco de dados que provocar a inserção de valores vazios em um domínio not null gera um diagnóstico de erro. André Luís Duarte 84 [email protected] Existem porém diversos casos que desejaremos permitir a inserção de tuplas com certos atributos vazios, porém, é importante que no atributos que formam a chave de um esquema relacional seja proibido valores nulos. 5.3 – Integridade Referencial Frequentemente desejamos assegurar que um valor que aparece em uma relação para um dado conjunto de atributos apareça também em um certo conjunto de atributos em outra relação. Isto é chamado de integridade referencial. 5.3.1 – Conceitos básicos Considere um par de relações r(R) e s(S), e a junção natural r |x| s. Pode acontecer que exista uma tupla tr em r que não se junta a nenhuma tupla em s. Isto é, não existe ts em s tal que tr R S ts R S . Tais tuplas são chamadas de tuplas soltas. Este tipo de tupla pode ou não ser aceito. Suponha que exista uma tupla em t1 na relação depósito com t1[nome_angencia] = “Colonial”, mas não exista nenhuma tupla na relação agência para a agencia Colonial. Isso seria uma situação indesejável e necessitaríamos de uma restrição de integridade para evitar este tipo de tuplas soltas. Analise o inverso e veja se neste caso gostaríamos de ter restrição de integridade. Podemos fazer as seguintes considerações baseado nos exemplos mostrados anteriormente: nome_agência é chave primária no Esquema_agência; nome_agência aparece em Esquema_depósito; As tuplas de depósito se referem à chave primária de agência; nome_agência em Esquema_depósito é uma chave estrangeira; nome_agência é chave primária de um esquema que não é Esquema_depósito; nome_agência em Esquema_agência não é uma chave estrangeira; nome_agência não é a chave primária de nenhum outro esquema relacional; 85 André Luís Duarte Banco de Dados No exemplo do “Colonial”, a tupla t1 em depósito tem um valor na chave estrangeira nome_agência que não aparece em agência. No exemplo que segue, a tupla t2 em agência tem um valor em nome_agência que não aparece em depósito, mas nome_agência não é uma chave estrangeira. Note que integridade referencial surge de forma freqüente em nossos bancos de dados. Por exemplo, podemos citar duas fontes deste tipo de restrição que são: Toda relação surgindo de conjuntos de relacionamentos, tem restrições de integridade referencial; Conjunto de entidades fraco precisava incluir a chave primária do conjunto de entidades do qual ele dependesse; 5.3.2 – Integridade Referencial em SQL Um recurso de aperfeiçoamento de integridade foi aprovado como uma adição ao padrão. Esse recurso permite a especificação de chaves primárias, candidatas e estrangeiras, como parte da instrução create table. A cláusula primary key da instrução create table inclui uma lista de atributos que compreende a chave primária; A cláusula unique key da instrução create table inclui uma lista de atributos que compreende a chave candidata; A cláusula foreign key da instrução create table inclui uma lista de atributos que compreende a chave estrangeira e o nome da relação referida pela chave estrangeira; Na definição de cliente e agência, usamos a especificação not null para primary key. Isto é um requerimento do próprio SQL. Qualquer atributo que seja membro de uma chave candidata, deve ser declarado not null. Exemplo 1 Vamos neste exemplo reformular as relações a fim de inserirmos a integridade vista até este momento. create table cliente ( nome_cliente char(20) not null, rua char(30), André Luís Duarte 86 [email protected] cidade_cliente char(30), primary key(nome_cliente)) create table agencia ( nome_agencia char(20) not null, ativos inteiro, cidade_agencia char(30), primary key(nome_agencia)) create table deposito ( nome_agencia char(20) not null, numero_conta char(10), nome_cliente char(20) not null, saldo inteiro, primary key(numero_conta, nome_cliente) foreign key(nome_agencia) references agencia, foreign key(nome_cliente) references cliente) 5.4 – Asserções Uma asserção é um predicado expressando uma condição que desejamos que o banco de dados sempre satisfaça (vimos algumas formas especiais de asserções). Existem muitas restrições que não podem ser expressas usando somente estas formas especiais de restrições. Podemos citar: A soma de todas as quantias de empréstimos para cada agência precisa ser menor do que a soma de todos os saldos das contas na agência; Todo cliente de empréstimo deve manter uma conta com o saldo mínimo de $1000,00; Quando uma asserção é feita, o sistema testa sua validade. Se a asserção é válida, então qualquer futura modificação no banco de dados é permitida apenas se não violar esta asserção. O problema é que asserções muito complexas podem sobrecarregar de forma significativa o sistema gerenciador de banco de dados. Esta sobrecarga tem levado os sistemas SQL a omitirem o suporte a asserções. 87 André Luís Duarte Banco de Dados Uma asserção que diz respeito a uma única relação toma a forma: assert <nome_asserção> on <nome_relação> : <predicado> Por exemplo, se desejássemos definir uma restrição de integridade que não permita saldos negativos, escrevemos: assert restricao_saldo on deposito: saldo >= 0 O comando assert nos permite definir uma restrição de integridade que não poderia ser expressa como restrição de domínio. assert restricao_gerente on cliente: nome_cliente <> nome_funcionario Ou seja, nenhum funcionário do banco pode ser seu próprio gerente de conta. As asserções podem ser restritas apenas para modificações no banco de dados, como no caso de desejarmos evitar a criação de uma conta, a menos que o nome do cliente apareça na relação cliente. assert restricao_referencia on insertion to deposito: exists (select * from cliente where cliente.nome_cliente = deposito.nome_cliente) Devido ao custo de processamento, asserções deram lugar a restrições de integridade mais fáceis de serem testadas como restrição de domínio, chave e integridade referencial. 5.5 – Gatilhos (TRIGGERS) Um gatilho é um comando executado automaticamente pelo sistema como um efeito colateral de uma modificação no banco de dados. Para projetarmos um gatilho, precisamos: Especificar as condições sob as quais o gatilho deve ser acionado; Especificar as ações a serem tomadas quando o gatilho é executado; André Luís Duarte 88 [email protected] Exemplo 2 Suponha que ao invés de não permitir saldos negativos, o banco trate o saque a descoberto ajustando o saldo para zero e criando um empréstimo no valor da quantia saldo negativo. A este empréstimo é dado o numero da conta estourada. A condição para o exemplo anterior, é uma atualização na relação depósito que resulte em um valor de saldo negativo. Seja t a tupla com valor negativo em saldo. As ações a serem tomadas são as seguintes: Inserir uma nova tupla na relação empréstimo s[nome_agencia] = t[nome_agencia] s[numero_emprestimo] = t[numero_conta] s[quantia] = -t[saldo]8 s[nome_cliente] = t[nome_cliente] Ajusta t[saldo] para 0 (zero) A SQL padrão não inclui gatilhos, porém, diversos sistemas implementam seus próprios recursos não padrões de gatilhos. O gatilho para solucionar nosso problema anterior poderia ser escrito na versão original do SQL da seguinte forma: define trigger saldo_negativo on update of depósito D ( if new D.saldo < 0 then ( insert into emprestimo values ( D.nome_agencia, D.numero_conta, D.nome_cliente, -new D.saldo) update deposito S set S.saldo = 0 where S.numero_conta = D.numero_conta)) 8 Negamos o t[saldo] para obter a quantia do empréstimo, um número que deve ser positivo. 89 André Luís Duarte Banco de Dados Capítulo 6 – Normalização (ou normatização) 6.1 – Introdução Dado um corpo de dados, como decidimos a estrutura lógica adequada a representar no banco de dados, como decidimos a estrutura lógica adequada para estes dados? De forma mais precisa, como decidimos que relações são necessárias e quais devem ser seus atributos? Trata-se do problema de design do banco de dados (ou de forma mais correta, do problema de design lógico do banco de dados). Vamos considerar o seguinte banco de dados de fornecedores e peças. FCOD S1 S2 S3 S4 S5 FNOME Smith Jones Blake Clark Adams PCOD PNOME P1 Porca P2 Trinco P3 Parafuso P4 Parafuso P5 Arruela P6 Engrenagem Fornecedores FSTATUS FCIDADE 20 Londres 10 Paris 30 Paris 20 Londres 30 Atenas PCOR Vermelho Verde Azul Vermelho Azul Vermelho PPESO 12 17 17 14 12 19 Peças PCIDADE Londres Paris Roma Londres Paris Londres FP FCOD PNUM QTD S1 P1 300 S1 P2 200 S1 P3 400 S1 P4 200 S1 P5 100 S1 P6 100 S2 P1 300 S2 P2 400 S3 P2 200 S4 P2 200 S4 P4 300 S4 P5 400 Tabela 6.1 – Banco de dados fornecedores e peças A estrutura lógica deste banco de dados nos dá a sensação de exatidão do mesmo; é obvio que as três relações são necessárias, que por exemplo, cor deve pertencer a relação peças e não fornecedores, da mesma forma quantidade pertence a relação FP, e assim por diante. Mas o que é que nos diz que isto deve ser desta forma? Podemos ter alguma noção sobre este ponto, se verificarmos o que acontece caso o design seja alterado. Suponhamos que o atributo STATUS saia da relação fornecedor e vá para a relação FP. Teremos a Tabela 6.2 mostrada a seguir. André Luís Duarte 90 [email protected] Fica claro, ao analisarmos a Tabela 6.2, que a relação FP’ envolve inúmeras redundâncias; o fato de que o fornecedor tenha um certo status tantas vezes quantas hajam expedições deste fornecedor. FCOD S1 S1 S1 S1 S1 S1 S2 S2 S3 S4 S4 S4 PNUM P1 P2 P3 P4 P5 P6 P1 P2 P2 P2 P4 P5 QTD 300 200 400 200 100 100 300 400 200 200 300 400 STATUS 20 20 20 20 20 20 10 10 30 20 20 20 Tabela 6.2 – Relação FP’ resultante da inserção do atributo STATUS na relação FP A redundância leva a vários problemas. Por exemplo, após uma atualização, o fornecedor S1 pode ser mostrado como tendo um status de 20 em uma tupla e um status de 30 em outra. A teoria da normalização (normatização) é basicamente uma formalização de idéias simples de forma a ser aplicada no design do banco de dados. O ponto fundamental a ser percebido é que uma relação, mesmo que normalizada, ainda possui algumas propriedades indesejáveis; a teoria da normalização permite-nos reconhecer estes casos, e mostra como as relações podem ser convertidas para uma forma mais desejável. 6.2 – Conceitos A teoria da normalização se constrói em torno do conceito de formas normalizadas. Dizse que uma relação está numa forma normalizada se satisfizer um conjunto específico de limitações. Por exemplo, diz–se que uma relação está na primeira forma normal (abreviatura 1FN) se satisfizer a limitação de que contenha apenas valores atômicos. As vezes, há boas razões para desconsiderar os princípios de normalização (sob muita análise). A única necessidade premente é que as relações sejam, no mínimo, na primeira 91 André Luís Duarte Banco de Dados forma normalizada. O design do banco de dados é uma tarefa extremamente complexa (pelo menos em ambiente de banco de dados grande). A teoria da normalização é útil ao processo, mas não é uma solução universal; “cada caso é um caso”. Durante a fase de desenvolvimento, notamos muitas vezes que as técnicas de normalização têm sido tratadas com pouca atenção (quando muito são utilizadas). Com isto, podemos encontrar anomalias na tabela como tabelas sem chave primária, redundância de informações e outras anomalias na atualização. A normalização esta impregnada em banco de dados relacionais, ignora-la durante a modelagem invalida qualquer garantia de que nossa base de dados é coerente e segura. A normalização tem dois objetivos principais: 1. Garantir a integridade dos dados, evitando que informações inconsistentes sejam inseridas; 2. Organizar e dividir as tabelas da forma mais eficiente possível, diminuindo a redundância e permitindo a evolução do banco de dados com o mínimo de efeitos colaterais; Para conseguir estes objetivos devemos utilizar regras implementadas a fim de analisar cada relação do nosso projeto. Estas regras são conhecidas como formas normais e são seis as mais conhecidas: 1FN (1ª Forma Normal) 2FN (2ª Forma Normal) 3FN (3ª Forma Normal) BCNF (Forma Normal de Boyce e Codd) 4FN (4ª Forma Normal) 5FN (5ª Forma Normal) Uma forma normal engloba todas as anteriores, ou seja, para que uma tabela esteja na 2FN, ela obrigatoriamente deve estar na 1FN e assim por diante. André Luís Duarte 92 [email protected] Universe of relations (normalized and unnormalized) 1NF relations (normalized relations) 2NF relations 3NF relations BCNF relations 4NF relations PJ/NF (5NF) relations Figura 6.1 – Esquema para formas de normalização 6.2.1 Revisão dos conceitos relevantes Variáveis de relação O termo “variáveis de relações”, de maneira simplificada, é análogo às relações trabalhadas nos tópicos anteriores; Chaves Chave candidata é um atributo ou conjunto de atributos únicos para cada registro. Cada relação pode ter uma ou várias chaves deste tipo; Chave primária é (são) o(s) atributo(s) escolhido(s) dentro do conjunto das chaves candidatas. Cada relação deve possuir uma chave deste tipo; Chave alternativa é (são) o(s) atributo(s) pertencente(s) ao conjunto da chave candidata que não foram escolhidos como chave primária; Chave estrangeira é (são) o(s) atributo(s) que faz “a ligação” com uma chave candidata de outra tabela; 6.2.2 Dependência Funcional (DF) Começamos a estudar a teoria da normalização inserindo a definição de dependência funcional (ou dependente funcional). Nós já temos alguma ideia do que venha a ser, pois já trabalhamos de forma intuitiva com estas noções. Iremos agora formalizar estas ideias. 93 André Luís Duarte Banco de Dados Dada uma relação R, o atributo y de R é funcionalmente dependente do atributo x de R, simbolicamente R.x R.y (R.x determina funcionalmente R.y), se, e apenas se, sempre que duas tuplas de R equivalerem a seus valores x, elas devem necessariamente equivaler a seus valores y. Sempre que um atributo x identifica um atributo y, dizemos que entre eles há uma dependência funcional. Temos, portanto, que x é o determinante e que y é o dependente. No banco de dados fornecedor e peças, por exemplo, os atributos nome, status e cidade da relação fornecedor são todos funcionalmente dependentes do atributo FCOD da relação fornecedor, porque, dado um valor particular para fornecedor (F) F.FCOD, existe precisamente um valor correspondente para F.FNOME, F.STATUS e F.CIDADE. Simbolicamente representaríamos da seguinte forma: F.FCOD F.FNOME F.FCOD F.STATUS F.FCOD F.CIDADE ou de forma mais sucinta, F.FCOD F.(NOME, STATUS, CIDADE) Exemplo1 Dada uma determinada cidade (sem considerar cidades homônimas) sabemos o seu estado e com o estado temos o país. Este fato pode ser representado da seguinte forma: cidade estado estado pais Em outras palavras, estado é funcionalmente dependente de cidade e país é funcionalmente dependente de estado. Ou ainda, cidade determina estado e estado determina país. Podemos inserir aqui também o conceito de dependência funcional completa. Isto ocorre quando o atributo y da relação R é completamente funcionalmente dependente do atributo x da relação R se for funcionalmente dependente de x e não funcionalmente André Luís Duarte 94 [email protected] dependente de qualquer subconjunto peculiar de x. Por exemplo, na relação fornecedor, é certamente verdadeiro que o atributo cidade seja funcionalmente dependente do atributo (composto) {F.COD, F.STATUS}, ou seja: F.(COD,STATUS) F.CIDADE Contudo, não é uma dependência funcional total, porque, naturalmente, também temos a DF: F.COD F.CIDADE. Notamos que CIDADE também é funcionalmente dependente de FCOD apenas. Podemos então concluir que: se y é funcionalmente dependente de x, mas não de forma total, então x deve ser composto. 6.2.2.1 Trivialidade A dependência funcional trivial indica que um determinante com mais de um atributo pode determinar seus próprios membros isolados. Por exemplo: banco, agencia banco DF trivial, pois, banco faz parte do determinante; banco, agencia agencia DF trivial, pois banco faz parte do determinante; Quando um determinante identifica outro atributo qualquer, temos uma dependência funcional não trivial (esta é a que nos interessa no processo de normalização): banco, agencia cidade DF não trivial, pois cidade não faz parte do determinante; 6.2.2.2 Transitividade Se um atributo x determina y e se o atributo y determina z, podemos dizer que x determina z de forma transitiva. Outra leitura é: existe uma dependência funcional transitiva de x para z. Exemplo2 cidade estado estado país cidade país (cidade determina país de forma transitiva) 6.2.2.3 Dependência funcional irredutível à esquerda Dizemos que o lado esquerdo de uma dependência funcional é irredutível quando o determinante está em sua forma mínima. Temos a forma mínima quando não é possível reduzir a quantidade de atributos determinantes sem perder a dependência funcional. 95 André Luís Duarte Banco de Dados Exemplo3 cidade, estado país Esta dependência funcional não está na forma irredutível à esquerda, pois podemos ter somente o estado como determinante, ou seja: estado país 9 6.2.2.4 Diagrama de Dependência Funcional (Diagrama FD) É conveniente representar as dependências funcionais de nossas relações através de um diagrama de dependência funcional ou Diagrama de FDs. Um exemplo de como construir estes diagramas é mostrado na figura a seguir: PNOME FNOME FCOD FSTATUS PCOD FCIDADE PCOR PPESO PCIDADE FCOD QTD PCOD Figura 6.2 – Diagrama FD para o banco de dados de fornecedores e peças 6.2.2.4 Anomalias de atualização São os problemas causados por inserções, atualizações ou deleções em uma base de dados não normalizada. Para vermos este tipo de problema, suponha a relação mostrada na Tabela 6.3. Vamos propor algumas considerações sobre a relação em questão. A tabela mistura dados do fornecedor, dados do fornecimento e dados de localização do fornecedor; 9 Nem sempre estar na forma irredutível à esquerda significa possuir um determinante com apenas uma coluna (atributo). André Luís Duarte 96 [email protected] Não existem tabelas auxiliares – todas as informações estão armazenadas nessa tabela; Nenhum campo pode ser nulo; A chave primária é composta pelos campos CodFornecedor e CodPeça; CodFornecedor Nome Status Cidade CodPeça F1 F1 F1 F1 F1 F1 F2 F2 F3 F4 F4 F4 Fornecedor 1 Fornecedor 1 Fornecedor 1 Fornecedor 1 Fornecedor 1 Fornecedor 1 Fornecedor 2 Fornecedor 2 Fornecedor 3 Fornecedor 4 Fornecedor 4 Fornecedor 4 20 20 220 20 20 20 10 10 10 20 20 20 Londres Londres Londres Londres Londres Londres Paris Paris Paris Londres Londres Londres P1 P2 P3 P4 P5 P6 P1 P2 P2 P2 P4 P5 Preço R$ 10 20 15 25 12 5 10 20 20 20 25 12 Qtde 300 200 400 200 100 100 300 400 200 200 300 400 Valor R$ 3000 4000 6000 5000 1200 500 3000 8000 4000 4000 7500 4800 Tabela 6.3 – Relação Fornecedor peça Baseando-se nestas considerações, podemos identificar algumas anomalias para as operações DML executadas sobre esta relação. Anomalias no comando INSERT Não podemos inserir a localização de um fornecedor até que este forneça pelo menos uma peça; De fato, a relação não mostra que o fornecedor F5 está localizado em Atenas (ele existe na vida real, mas não pode ser representado); Sempre que cadastrarmos o fornecimento de uma peça, temos que repetir os dados do fornecedor (Nome, Status e Cidade); Anomalias no comando UPDATE O valor do campo cidade aparece repetido várias vezes na relação; Esta redundância aumenta a probabilidade de erro durante uma atualização, por exemplo, se o fornecedor F1 se mudar de Londres para Amsterdã, teremos que pesquisar todos os registros correspondentes e atualiza-los tomando o cuidado de não deixar os dados inconsistentes; O mesmo problema se aplica aos campos nome, status e preço; O campo valor representa outra anomalia: ele é calculado pela multiplicação de preço e quantidade se alterarmos o preço unitário ou a quantidade, teremos que atualizar também o campo valor; 97 André Luís Duarte Banco de Dados Anomalias no comando DELETE Se removermos todos os registros de um determinado fornecimento, apagaremos não somente a ligação com as peças, mas também a informação da localização do fornecedor (os problemas do INSERT e DELETE são na realidade duas faces da mesma moeda); 6.2.2 Decomposição sem perdas O processo de normalização envolve a quebra ou decomposição de uma tabela em partes menores. Essa decomposição tem que ser reversível de modo que nenhuma informação seja perdida no processo. O fato de uma decomposição ser ou não sem perdas está intimamente ligado ao conceito de dependência funcional visto anteriormente. Tendo como base a Tabela 6.4 e 6.5, analise as seguintes considerações: Funcionário André Luís Sexo M M Salário 5.000,00 4.500,00 Tabela 6.4 – Relação funcionário original a) Funcionário André Luís Sexo M M Funcionário André Luís Salário 5.000,00 4.500,00 b) Funcionário André Luís Sexo M M Sexo M M Salário 5.000,00 4.500,00 Tabela 6.5 – Relações formadas após a decomposição Na decomposição da letra a é possível restaurar a tabela original, pois com o nome do funcionário obtemos no sexo e o salário correspondentes (decomposição sem perdas). Na letra b não é possível obter a tabela original, pois para o funcionário “André”, do sexo “M”, encontramos dois salários na segunda tabela. André Luís Duarte 98 [email protected] 6.2.3 Junção (Join) Junção é o processo inverso da decomposição sem perdas. Na Tabela 6.5 letra a, temos um atributo comum (Funcionário), podemos obter a tabela original fazendo a junção das duas tabelas decompostas. 6.2.4 Projeções Significa considerar apenas alguns campos de uma tabela. Nos capítulos anteriores este assunto foi amplamente abordado. 6.3 Importância da Normalização Os benefícios mais importantes obtidos com a normalização de uma base de dados são: Tabela flexíveis de fácil manutenção: uma base sem as anomalias de atualização e com um estrutura de armazenamento eficaz é mais simples de atualizar e evoluir (embora em alguns casos o processo de consulta se torna mais complexo, pois a normalização geralmente aumenta o número de tabelas do banco). Eliminação de redundância: sem redundância, as tabelas ficam menores, mais consistentes e menos sujeitas a discrepâncias. Sempre que possível, evite o que o mercado chama de “redundância controlada”, como o nome já diz, há de se criar um controle (rotinas), o que aumenta a complexidade do sistema. 6.4 Normalização estudo de caso Para efeito didático, vamos trabalhar com o seguinte exemplo: em uma empresa, os produtos recebidos de um fornecedor são registrados em um formulário próprio, que pode ser visualizado na Figura 6.3. Vamos informatizar esse processo criando uma base de dados para armazenar as informações deste formulário. A primeira versão para a base de dados poderia ser definida utilizando a Tabela 6.5 mostrada a seguir. Note que esta estrutura ainda não pode ser carregada em um banco de dados relacional, pois possui atributos (CódItem, CódProd, Qtde, Preço e TotalItem) compostos e não se apresenta no formato de uma tabela bidimensional10. 10 A palavra bidimensional talvez não seja muito bem utilizada aqui, pois, se a analisarmos esta propriedade como sendo largura e altura, nossa tabela possui estas características. O fato aqui é que uma linha e uma coluna seja bem definida e possua somente uma dimensão (possua somente um valor), o que 99 André Luís Duarte Banco de Dados Figura 6.3 – Formulário de fornecimento de mercadoria não ocorre no exemplo já que uma linha começa com um valor para a primeira coluna e ao chegar na 7ª coluna a linha se divide em três outras linhas passando a possuir três valores independentes. André Luís Duarte 100 [email protected] N°Nota Data CForn Nome Fone End 1 15/6/2003 22 Empresa Excalibur 33355255 Itamaracá, 15 2 20/7/2003 17 Cia Silva 33344787 Cardoso, 145 3 22/8/2003 22 Empresa Excalibur 33355255 Itamaracá, 15 Citem 1 2 3 1 2 3 1 2 CProd CA BB TC TC CM RM CA BB Prod Chapa de aço Bobina Tab corridas Tab corridas Compensado Ripas de mad Chapa de aço Bobina Qtde 35 20 50 50 30 300 50 20 Preço 15 15 20 20 15 2 15 15 TItem 525 300 1000 1000 450 600 750 300 Tabela 6.5 – Relação retirada a partir dos formulários 6.4.1 1ª Forma normal (1FN) O primeiro passo para normalizar a tabela anterior é aplicar as regras da primeira forma normal. Podemos dizer que uma entidade está na primeira forma normal quando cada atributo contém somente um valor, em somente um lugar. Essa exigência também é conhecida como atomicidade de dados. As regras gerais para obtenção da 1FN são: Não podemos ter atributos multivalorados. Neste caso, colocamos cada valor do atributo em uma linha diferente e repetimos os dados de todas as outras colunas; Não podemos ter atributos repetidos, como telefone1, telefone2, etc. A solução é semelhante ao item anterior; Todos os registros têm que ser diferentes; A entidade não pode ter mais de duas dimensões; Cada atributo deve ter somente um tipo de dado. Uma violação comum desta regra, por exemplo, é a criação de um campo para armazenar o CPF e o CNPJ, alternadamente. Esse cenário deve ser evitado, pois cria complicações para a evolução da regra de negócio; N°Nota Data CForn Nome Empresa Excalibur Empresa Excalibur Empresa Excalibur 1 15/6/2003 22 1 15/6/2003 22 1 15/6/2003 22 2 20/7/2003 17 Cia Silva 33344787 2 20/7/2003 17 Cia Silva 33344787 2 20/7/2003 17 Cia Silva 33344787 3 22/8/2003 22 3 22/8/2003 22 Empresa Excalibur Empresa Excalibur Fone 33355255 33355255 33355255 33355255 33355255 End Itamaracá, 15 Itamaracá, 15 Itamaracá, 15 Cardoso, 145 Cardoso, 145 Cardoso, 145 Itamaracá, 15 Itamaracá, 15 CItem CProd Prod Chapa de aço Qtde Preço TItem 1 CA 35 15 525 2 BB Bobina 20 15 300 3 TC Tab corrida 50 20 1000 1 TC Tab corrida 50 20 1000 2 CM Compensado 30 15 450 3 RM 300 2 600 1 CA 50 15 750 2 BB 20 15 300 Ripas de mad Chapa de aço Bobina Tabela 6.6 – Relação após a aplicação da 1FN 101 André Luís Duarte Banco de Dados Para trabalhar com a segunda forma normal, precisamos definir uma chave primária. Na tabela recém criada, a chave escolhida é formada pelos campos número da nota e código do item (destacados na Tabela 6.6), pois através deles, podemos determinar todos os outros campos. Por exemplo: Com o número da nota determinamos os atributos Data, CodForn, Nome, Telefone e Endereço. NroNota {Data, CodForn, Nome, Telefone, Endereço}; Com o número da nota e o código do item determinamos os demais atributos: {NroNota, CodItem} {CodProd, Produto, Quantidade, Preço, TotalItem}; Note que no exemplo inicial do banco de dados de fornecedores e peça, as relações já estão em 1FN. 6.4.1.1 Normalização e atributos compostos O objetivo principal da 1FN é transformar estruturas não padronizadas em tabelas, para que possam ser armazenadas em um banco de dados relacional. De fato, podemos dizer que toda tabela já esta na 1 FN senão não seria uma tabela. O caso mais comum de violação da 1FN são estruturas que possuem atributos multivalorados, repetidos ou aninhados. Na 1FN, esses atributos devem ser “planificados”, fazendo com que cada célula armazene somente um valor. Existem duas formas de enquadrar os atributos multivalorados na 1FN: 1. Expandir o atributo multivalorado em vários registros, repetindo o valor dos demais campos (solução que mais se aproxima a definição de Codd, o pai da normalização); 2. Criar uma tabela auxiliar para conter o atributo multivalorado (solução adotada por alguns desenvolvedores pela praticidade). No entanto, em alguns casos, essa abordagem pode induzir ao erro; Por exemplo, observe o aninhamento de três entidades na relação representada na Tabela 6.7 (vários gostos dentro de dependentes e vários dependentes dentro de pai). Utilizando a primeira abordagem, chegaremos facilmente à estrutura mostrada na Tabela 6.8. Agora imagine a dificuldade em criar direto tabelas auxiliares. Teremos que verificar quem é a chave, se a tabela auxiliar terá outra chave, se precisará de uma tabela André Luís Duarte 102 [email protected] auxiliar para auxiliá-la, etc. Em suma, será necessário utilizar os conceitos de chave primária, dependência funcional, dependência funcional irredutível à esquerda e decomposição sem perdas, que são regras utilizadas na 2FN. Certamente neste caso, os projetistas estão sujeitos a inserir erros com mais facilidade no projeto. Pai Código Nome Telefone Nome Samuel Lucas 1 André 3455456 Jussara Davi 2 Duarte 4344554 Mariana Dependente Gosto Futebol Futebol Luta Flores Colorir Dança Games Xadrez Brincos Colares Chocolate Brinquedos Idade 10 Idade 8 31 6 9 37 7 Tabela 6.7 – Informações aninhadas Código 1 1 1 1 1 1 2 2 2 2 2 2 Nome André André André André André André Duarte Duarte Duarte Duarte Duarte Duarte Telefone 3455456 3455456 3455456 3455456 3455456 3455456 4344554 4344554 4344554 4344554 4344554 4344554 Nome Samuel Lucas Lucas Jussara Jussara Jussara Davi Davi Mariana Mariana Mariana Mariana Gosto Futebol Futebol Luta Flores Colorir Dança Games Xadrez Brincos Colares Chocolate Brinquedos Idade 10 8 8 6 6 6 9 9 7 7 7 7 Idade 31 31 31 31 31 31 37 37 37 37 37 37 Tabela 6.8 – Utilizando a primeira abordagem para aplicar a 1FN 6.4.2 2ª Forma Normal (2FN) Essa forma normal visa à diminuição da redundância e o desagrupamento de informações. Com a 2FN, uma tabela passa a representar uma quantidade menor de entidades (o ideal é que cada entidade seja armazenada em apenas uma tabela), observe que a nossa tabela agrupa as entidades nota fiscal, item de nota, fornecedor e produto. 103 André Luís Duarte Banco de Dados A definição da segunda forma normal é que uma tabela está em 2FN se estiver em 1FN e todo atributo não-chave for determinado por todos os campos da chave primária. Em outras palavras, é necessário eliminar as dependências funcionais parciais. A tabela do nosso exemplo, viola a 2FN, pois os campos Data, Codforn, Nome, Telefone e Endereço não são determinados pela chave primária completa (o campo CodItem não é necessário para identificar essas informações): NroNota {Data, CodForn, Nome, Telefone, endereço} Como regra geral, a 2FN deve ser aplicada através dos passos: 1. Eleger a chave primária da tabela; 2. Verificar as dependências funcionais parciais; 3. Mover os campos não enquadrados na 2FN para uma nova tabela, fazendo a decomposição sem perdas; 4. Na tabela criada, repetir os passos anteriores até eliminar a DF parcial; Aplicando a 2FN em nossa relação, teremos o resultado apresentado na Tabela 6.7 e Tabela 6.8. NroNota 1 2 3 Data CodForn 15/6/2003 22 20/7/2003 17 22/8/2003 22 Nome Empresa Excalibur Cia Silva Empresa Excalibur Telefone 33355255 33344787 33355255 Endereço Itamaracá, 15 Cardoso, 145 Itamaracá, 15 Tabela 6.9 – 1ª relação obtida com a aplicação das regras da 2FN NroNota 1 1 1 2 2 2 3 3 CodItem 1 2 3 1 2 3 1 2 CodProd CA BB TC TC CM RM CA BB Produto Chapa de aço Bobina Tábuas corrida Tábuas corrida Compensado Ripas de madeira Chapa de aço Bobina Qtde 35 20 50 50 30 300 50 20 Preço 15 15 20 20 15 2 15 15 TotalItem 525 300 1000 1000 450 600 750 300 Tabela 6.10 – 2ª relação obtida com a 2FN Observe que todos os campos nas duas tabelas são agora determinados por suas chaves primárias completas, garantindo assim a 2FN11. Note também que o resultado da aplicação desta forma normal são duas tabelas mais simples, que representam as entidades com mais proximidade. 11 Se a chave primária possui apenas um campo ou é composta por todos os campos, a tabela já está automaticamente na 2FN. André Luís Duarte 104 [email protected] 6.4.3 3ª Forma Normal (3FN) A 3FN dá continuidade ao objetivo da 2FN que é o de reduzir as redundâncias, desagrupando as tabelas de forma que cada uma represente apenas uma entidade. A Tabela 6.7 agrupa informações sobre as entidades Nota e Fornecedor e a Tabela 6.8 agrupa informações sobre as entidades Item, Nota e Produto. As técnicas utilizadas pela 3FN é a identificação e eliminação da transitividade. Dizemos que uma tabela está na 3FN se também está na 2FN e todo atributo não chave for determinado de forma não transitiva pela chave primária. Em outras palavras, dizemos que todo atributo não chave deve ser mutuamente independente e determinado somente pela chave primária. Dois ou mais atributos são mutuamente independentes se nenhum dos atributos em questão for funcionalmente dependente de um dos outros. Observe que tal atributo pode ser atualizado de forma independente de todos os outros. Um atributo não chave é qualquer atributo que não participe da chave primária nem das chaves candidatas da relação em questão. Vamos analisar a tabela criada na 2FN. Observe que os campos Nome, Telefone e Endereço podem ser determinados tanto pela chave primária quanto pelo campo CodForn: NroNota {Data, Nome, CodForn, Telefone, Endereço} CodForn {Nome, Telefone, Endereço} Assim, esses campos possuem dependência funcional transitiva com a chave primária: {NroNota} CodForn {Nome, Telefone, Endereço} Na segunda tabela também temos transitividade: {NroNota, CodItem} CodProd {Produto, Preço} Outro tipo de violação da 3FN são os campos calculados, que também possuem transitividade. Na 3FN, todos os campos calculados são removidos da base de dados. Veja a representação: 105 André Luís Duarte Banco de Dados {NroNota, CodItem} Preço, Qtde {TotalItem} Para adequar as relações à 3FN, seguimos um roteiro semelhante ao usado na 2FN: 1. Mover os campos com transitividade para uma nova relação; 2. Criar uma chave primária na tabela nova com o(s) campo(s) da tabela original que determinava(m) diretamente os campos movidos; 3. Na nova tabela, repetir os passos anteriores até eliminar a transitividade; Observe nas tabelas a seguir o formato final da nossa base normalizada após a aplicação da 3FN. CodForn 22 17 Nome Empresa Excalibur Cia Silva Telefone 33355255 33344787 Endereço Itamaracá, 15 Cardoso, 145 Tabela 6.11 – Relação Fornecedor CodProd CA BB TC CM RM Produto Chapa de Aço Bobina Tábuas Corridas Compensado Ripas de Madeira Preço 15,00 15,00 20,00 15,00 2,00 Tabela 6.12 – Relação Produto NroNota 1 2 CodForn 22 17 Tabela 6.13 – Relação Nota NroNota 1 1 1 2 2 2 CodItem 1 2 3 1 2 3 CodProd CA BB TC TC CM RM Qtde 35 20 50 50 30 300 Tabela 6.14 – Relação Item Nota Neste ponto temos a organização ideal para esta base de dados pelos seguintes motivos: 1. A decomposição foi feita sem perdas, através de junções podemos recuperar a Tabela 6.6; 2. As quatro entidades (Nota, Item nota, Fornecedor e Produto) possuem tabelas exclusivas, eliminado assim, o agrupamento de informações e redundância; André Luís Duarte 106 [email protected] 3. As tabelas foram separadas de tal forma que as anomalias de atualização não ocorrerão; 4. As tabelas são fáceis de evoluir e manter. Por exemplo, se quisermos incluir dados de um produto que ainda não tenha sido fornecido, podemos inserir sua descrição na tabela Produtos. Observe que isso não era possível até a aplicação da 3FN; 5. Do ponto de vista relacional, os dados estão armazenados e distribuídos de forma eficiente; No exemplo fornecedores e peças no inicio do capítulo, podemos notar ver que os atributos PNOME, PCOLOR, PPESO E PCIDADE são independentes entre si, pois é possível alterar qualquer um deles sem ter que alterar os demais ao mesmo tempo. Também, cada um destes atributos são totalmente dependentes de PCOD, a chave primária (as dependências devem ser totais pois PCOD não é composto). Observações sobre as anomalias Vamos supor, no exemplo de fornecedores e peças, que a informação relativa aos fornecedores em vez de estar fragmentada em duas relações, fornecedores e peças, seja reunida em uma relação: TESTE (FCOD, STATUS, CIDADE, PCOD, QTD) Podemos observar que a relação resultante seria uma versão ampliada para a relação “FP”. Os atributos tem seus significados usuais, a não ser que, neste exemplo, introduzamos uma limitação adicional, a saber que STATUS é funcionalmente dependente de CIDADE. O significado desta limitação é que um status de fornecedor é determinado pela localização deste fornecedor (por exemplo, todos os fornecedores de Londres devem ter status 20). Para simplificar, vamos ignorar o atributo NOME. A chave primária da relação TESTE é formada pela combinação dos atributos FCOD e PCOD. O diagrama FD é mostrado na Figura 6.4. STATUS FCOD QTD PCOD CIDADE Figura 6.4 – Diagrama FD para a relação TESTE 107 André Luís Duarte Banco de Dados Observe que o diagrama FD da relação TESTE é mais complexo do que o diagrama FD para a relação na Figura 6.2. Informalmente, um diagrama 3FN tem setas apenas a partir da chave primária (Figura 6.2). Em relações que não sejam 3FN, existirão setas adicionais, e são estas setas adicionais que causam as anomalias citadas anteriormente. De fato, a relação TESTE viola as regras da 3FN, ou seja, os atributos não chave não são mutuamente independentes, porque STATUS depende funcionalmente de CIDADE (uma seta adicional) e ambos não dependem totalmente da chave primária, ambas dependem apenas de FCOD (mais duas setas adicionais). 5.4.3.4 Forma Normal de Boyce/Codd (BCNF) < Trabalho em grupo > 6.5 Normalização e integridade As formas normais visam à consistência da base de dados sob o aspecto da eliminação de redundâncias, mas não garantem que as informações certas serão inseridas no lugar certo (um ponto crucial para que o banco se mantenha íntegro ao longo do tempo). Para que as tabelas obtidas, com a aplicação das formas normais, façam sentido, é preciso utilizar as regras de integridades abordadas nos capítulos anteriores. Analisando nosso exemplo, podemos listar: Não podemos inserir um produto na tabela Item nota que não tenha sido cadastrado na tabela Produto; Não podemos apagar um registro na tabela Nota sem apagar o conjunto de registros correspondentes da tabela Item nota; Não podemos alterar o código de um fornecedor sem alterar todos os registros da tabela Nota que o referenciam; 6.6 Desnormalização A normalização não se preocupa com a performance de obtenção dos dados e sim com a melhor forma de organizá-los. Como a normalização geralmente aumenta o número de tabelas, há uma tendência de queda de performance nas consultas (logicamente pela necessidade de mais joins). André Luís Duarte 108 [email protected] A desnormalização é o processo inverso, onde o administrador de banco de dados abre mão de algumas regras das formas normais com o objetivo de otimizar consultas. É importante notar que isso não é o mesmo que uma base de dados não normalizada: a desnormalização acontece sempre depois da aplicação das formas normais. A desnormalização inadvertida é na maioria dos casos desaconselhável. Esta só deve ser aplicada quando o administrador tiver certeza (estudos, testes, provas físicas, etc) de que esta trará benefícios reais no sistema em questão. Alguns profissionais fazem suposições sobre a perda de performance e já projetam o sistema desnormalizando, sem fazer nenhum benchmark. Os custos com o ganho de performance podem não aparecer ou não pagam os custos das anomalias de atualização geradas e que necessitaram serem tratadas. Vale notar que nem sempre joins degradam performance em SGBD, normalmente este são dotados de recursos que visam otimizar as consultas. Como exemplo, imagine que nossa aplicação acesse massivamente um relatório contendo o campo calculado TotalItem (eliminado na 3FN). Para evitar o cálculo do total a todo o momento, podemos abrir mão da 3FN e criar o campo fisicamente na tabela de itens de nota, arcando com a responsabilidade de mantê-lo devidamente atualizado12. Algumas dúvidas comuns podem surgir a respeito da normalização. Podemos citar duas delas: a) O que dizer da normalização para fins de manutenção de dados históricos? No exemplo trabalhado, se o preço do produto for alterado, todos os dados de fornecimento são alterados. Repetir o campo preço na tabela Item nota, para manter o histórico do preço é uma boa prática? R. Este caso não se trata de desnormalização. O que temos são dois atributos com sutil diferença: Preço atual e Preço histórico. b) Devemos sempre normalizar até o fim? Por exemplo, geralmente os campos Cidade, Bairro, Uf e CEP apresentam repetição, é correto criarmos tabelas auxiliares para cada um? 12 O Delphi possui componentes elaborados para suprir várias necessidades e solucionar muitos problemas de desenvolvedores de aplicações que acessam banco de dados pequenos ou corporativos. 109 André Luís Duarte Banco de Dados R. Depende, se a aplicação realizar pesquisas nestes campos, sim – imagine se quiséssemos saber a quantidade de pessoas em um bairro e este estiver cadastrado de forma diferente em mais de um registro (por exemplo, Sto. Antônio em um registro e Santo Antônio em outro). Hoje em dia vemos vários sistema como o dos correios, que a partir do CEP trazem todas as demais informações do endereço, deixando claro que várias tabelas foram utilizadas. Podemos notar que a normalização é uma etapa (ferramenta) importante no processo de desenvolvimento de um sistema de banco de dados. A normalização individualmente não soluciona todos os problemas encontrados no desenvolvimento, já que nem todas as anomalias de atualização e as redundâncias podem ser eliminadas através de formas normais. A normalização nunca deve substituir uma boa análise do negócio da aplicação e a utilização de todas as técnicas de desenvolvimento de sistemas. André Luís Duarte 110 [email protected] Bibliografia ELMASRI, Ramez; NAVATHE, Shamkant B. Sistemas de banco de dados. 4a ed. São Paulo: Pearson, 2006. 724 p. ISBN 85-88639-17-3. SUEHRING, Steve. MySQL a bíblia. Rio de Janeiro: Elsevier, 2002. 674 p. ISBN 85-352-1084-9.63 SILBERSCHATZ, Abraham; KORTH, Henry F.; SUDARSHAN, S.. Sistema de banco de dados. 3. ed. São Paulo: Pearson, 2008. 778 p. ISBN 978-85-346-1073-5. HEUSER, C. Projeto de Banco de Dados. Porto Alegre: Sagra Luzzato, 1998, Série de Livros Didáticos, número 4. KORTH, H. F.; Sudarshan, S; Silberschatz, A. Sistema de Banco de Dados. 5a ed. Editora Campus, 2006. KORTH, H.F.; Silberschatz, A. Sistema de Banco de Dados. 3a ed. São Paulo: Makron Books, 1999. MACHADO, F.N.R.; Abreu, M. Projeto de Banco de Dados: uma Visão Prática. São Paulo: editora Érica, 1995. SILVA, I, J, Banco de Dados: do Modelo Conceitual à Implementação Física, Ed: Alta Books, 2005. 111 André Luís Duarte