Nós já vimos em aulas anteriores, diversas características dos Bancos de Dados, principalmente como fazemos para captar os dados na Realidade, separando uma “fatia” dessa realidade para análise e organização. Nós falamos também de diversas características dos Bancos de Dados e citamos que existem vários modelos de estruturação física, porém trabalhamos exclusivamente com exemplos baseados em Bancos de Dados Relacionais.
A primeira razão, como já vimos anteriormente, é que o modelo relacional de Banco de Dados responde hoje por mais de 70% dos Bancos de Dados que dão suporte aos Sistema em todo mundo. Mas, por que será que existe esse domínio de modelagem até hoje? Essa é a pergunta que vamos trazer nesta lição para que, aprofundando um pouco mais o nosso conhecimento no modelo Relacional, consigamos responder sobre as principais características que fortalecem o domínio do Modelo relacional sobre os demais modelos de Bancos de Dados. Vamos lá?
Antes de voltar a falar de Banco de Dados, vamos refletir um pouco: como nós organizamos as informações no nosso dia a dia?
Para deixar esse problema mais real, vamos usar um livro. No caso vamos usar como exemplo o livro mais vendido do mundo, a Bíblia, pois, mesmo que você ainda não tenha lido, já deve ter ouvido falar desse livro, não é mesmo?
A Bíblia é um livro extremamente organizado, que pode ser acessado por diversas formas. Pode ser acessado de forma sequencial ou cronológica, ou seja, lendo página a página. Pode ser acessado também por autor (ou grupo de autores) que escreveu cada “unidade” – (vamos chamar de unidade, apenas para uma questão didática, para não confundirmos o conceito do livro Bíblia com todos os livros que a compõem).
Podemos acessar por tema ou assunto, por exemplo, Salmos, Gênesis, Êxodo, etc. Em cada “unidade” há a divisão por capítulos e versículos, que são trechos do texto numerados sequencialmente. Na verdade, a Bíblia foi sendo composta por vários livros e quando vemos alguns personagens da nossa história citando passagens da Bíblia, em seu tempo, observe que é muito comum eles usarem a expressão “está escrito” e não a indicação que utilizamos hoje, com capítulo e versículo, pois, essa organização foi realizada apenas no século XVI. Caso eu queira indicar uma leitura específica do 2º Livro de Pedro, Capítulo 1, Versículos de 20 a 22 eu posso usar a notação 2 Pedro 1:20-22.
Quando analisamos tecnicamente esse formato, ele não é um formato relacional, mas sim um formato hierárquico, pois organiza assuntos dentro de assuntos para classificar e localizar. Isso só é possível, pois a Bíblia tem um formato padronizado, ou seja, são livros que foram escritos desde +/- 1500 a.C. até +/- 100 d.C. e foram reunidos em um único livro, que posteriormente foi indexado.
Agora, imagine como nós podemos fazer a organização padronizada de informações que têm formatos diferentes? Ou ainda, como podemos organizar em um único local as informações de pessoas, com informações contábeis, com informações sobre produção, entre outras informações que existem na nossa realidade?
Com esse problema em mãos surgiu a Teoria Relacional, que, trouxe muitas considerações da matemática, principalmente da teoria dos conjuntos e, com base nestas teorias, foi desenvolvido todo um conceito de relacionamento entre dados, por volta dos anos 70, que utilizamos até os dias de hoje, mesmo com toda a evolução tecnológica que vivemos.
Em resumo, temos hoje vários modelos de organização de dados, principalmente quando temos problemas pontuais a serem atendidos, porém, quando precisamos atender à organização de dados de forma mais genérica e abrangente, o modelo relacional ainda é o que melhor atende e garante performance, resultados e segurança.
Agora, falando ainda em buscas por informações, vamos avançar para os nossos dias atuais. Você já percebeu que quase tudo o que fazemos ou procuramos tem uma “chave” de acesso?
Vamos iniciar pensando no Google: Como você faz uma pesquisa?
Se você já sabe o que quer, você digita no campo de busca apenas o dado que está buscando e as rotinas de buscas do Google entendem o que você quer, de forma rápida, e trazem a informação. Por exemplo, se você digitar apenas a palavra “dólar”, ele já entende que você quer saber sobre a moeda dos Estados Unidos e mostra automaticamente a cotação da moeda. Isso ocorre, pois a maior incidência de buscas para a palavra dólar é em relação a sua cotação. Em seguida o Google mostra algumas notícias sobre “dólar” e ainda vários sites relacionados.
Agora, se você fizer uma busca mais específica e usar outra “chave” como “história do dólar”, a resposta que ele vai trazer vai ser bem diferente, ou seja, conforme você varia sua chave de acesso, as informações relacionadas a essa chave também variam.
Quando nós falamos de um banco de dados relacional, o raciocínio é bem parecido, porém nós não teremos a liberdade para mudar a chave, pois o Banco de Dados faz buscas sempre estruturadas, diferente do Google, que faz buscas pelo contexto.
Vamos pensar o seguinte: quando você vai fazer um cadastro em uma loja, ou em um emprego. Qual é o dado que sempre pedem após você se identificar pelo seu nome completo? Se você respondeu CPF, acertou, pois o CPF é um identificador único em todo o Brasil, ou seja, não existem duas pessoas com o mesmo número de CPF.
Já o RG, até o momento, é gerenciado pelos Estados, então, cada Estado emite o seu. Isso pode trazer duplicidade de numeração, o que violaria a integridade do Banco de Dados. Pensando dessa forma, quando uma pessoa pede o número do CPF, ela não quer saber o seu CPF, na verdade ela precisa identificar você dentro do Banco de Dados e, cada vez que precisar saber alguma informação relacionada a você, como endereço, telefone, data de nascimento, irá usar o CPF como chave para abrir o seu cadastro.
O mesmo ocorre com um Livro Físico de Receitas, onde o Título da Receita é a chave que usamos para saber em qual página está. Caso contrário, se não temos a chave, não podemos fazer uma busca relacional, temos que fazer uma busca sequencial, ou seja, temos que ler todas as páginas até chegar na receita.
Imagine agora que você precisa armazenar os dados de um carro. Qual seria uma chave natural que você pode usar? Minha sugestão é a Placa, caso seja um veículo já em uso. Pela placa você consegue recuperar todas as informações do veículo.
E quando você vai a um site comprar, por exemplo, sabão em pó? Com certeza você não sabe o código do produto que está cadastrado no Banco de Dados do fornecedor, mas você pode fazer uma busca por chave secundária, como o nome, que assim o sistema vai trazer o resultado da pesquisa para você escolher e efetuar a sua compra. O sistema trouxe a chave primária relacionada a cada item que apresentou para você em tela e, no momento que você escolher, ele vai passar esse código ao Banco de Dados para recuperar exatamente o produto que você quer comprar.
Em resumo, praticamente tudo o que fazemos no nosso dia a dia é baseado em relacionamento de dados. Por meio de uma chave de acesso, conseguimos acessar rapidamente as informações que precisamos e, assim, efetuamos as transações necessárias.
Agora que nós já entendemos como geramos o nosso modelo lógico podemos aprofundar um pouco mais em como obter mais segurança e integridade no Banco de Dados, ou seja, garantir ao nosso usuário que os dados que estão dentro do Banco de Dados estejam íntegros, sem repetição, e possam ser recuperados de forma ágil.
Como já vimos, vamos sempre precisar trabalhar com Chaves para conseguir acessar as informações dentro da relvar (está lembrado(a) desse conceito da aula anterior?). Vimos também o conceito básico de Dependências Funcionais, que vamos retomar com mais detalhes nesta lição.
Tudo o que vimos nos levou a montar as nossas relvars (ou tabelas) de forma empírica, ou seja com base no nosso conhecimento e experiência, porém, como já falamos anteriormente, a Teoria dos Relacionamentos tem fundamentação matemática, mais especificamente na teoria das funções.
Considerando que a Matemática é uma ciência exata, podemos então determinar algumas regras que vão nos ajudar a fazer a decomposição da relvar, sem perder informação, ou seja, vamos utilizar algumas regras da teoria das funções que vão garantir a integridade no Banco de Dados. Posteriormente, aplicá-las ao que vamos chamar de processo de normalização, onde iremos aplicar algumas regras, que são denominadas formas normais.
Na lição passada já introduzimos o assunto de dependências funcionais para explicar os conceitos de relvar e relação, porém agora vamos trabalhar especificamente nos conceitos das dependências funcionais.
Para isso, vamos rever alguns conceitos básicos da teoria de funções da matemática, mas, fique tranquilo(a), que só vamos precisar de alguns conceitos básicos mesmo, não precisamos nos aprofundar muito. Considere os seguintes conjuntos:
Figura 1 - Conjuntos X e Y relacionados
Fonte: o autor.
#PraCegoVer: imagem de dois círculos representando funções. O primeiro círculo da esquerda, está identificado com a letra X e tem em seu conteúdo os números 1, 2, 3 e 4. A esquerda temos outro círculo, identificado pela letra Y que tem os números 11, 12, 13 e 14. Temos ainda uma seta interligando o número 1 ao número 11, uma seta interligando o número 2 ao número 12, uma seta interligando o número 3 ao número 13 e uma seta interligando o número 4 ao número 14.
Na figura 1, observamos dois conjuntos, X e Y, onde cada elemento de X está diretamente relacionado a um elemento de Y. Matematicamente, nós podemos dizer então que f(x) = x + 10 ou y = x + 10, ou seja, sempre que você sabe “x”, você pode aplicar a “fórmula” e chegar ao valor de “y”.
Agora, vamos observar os conjuntos, a seguir:
Figura 2 - Conjuntos CPF e NOME Relacionados
Fonte: o autor.
#PraCegoVer: imagem de dois círculos representando funções. O primeiro círculo da esquerda, está identificado por cpf e tem em seu conteúdo os números 1, 2, 3 e 4. À esquerda temos outro círculo, identificado por nome que tem os nomes Maria, Pedro, João e Joana. Temos ainda uma seta interligando o número 1 a Maria, uma seta interligando o número 2 ao Pedro, uma seta interligando o número 3 ao João e uma seta interligando o número 4 a Joana.
Observe agora que apenas fizemos uma alteração no segundo conjunto, substituindo o que era Y por NOME, então, podemos dizer que f(cpf) = nome ou, ainda, podemos afirmar que sempre que eu sei o CPF, logo, saberei qual é o NOME, pois o CPF leva ao dado NOME. Dentro da teoria relacional, podemos representar da seguinte forma:
CPF → NOME
Ou seja, podemos afirmar que o NOME depende funcionalmente do CPF.
Para facilitar o entendimento, dentro das dependências funcionais existem 4 fundamentos que nos auxiliam em compreender como os relacionamentos entre as chaves e os dados ocorrem nos Bancos de Dados.
1ª Regra Separação: Podemos dizer que se um elemento determina um conjunto de elementos, ele também os determina de forma separada, ou seja:
Se X→YZ então X→Y e X→Z
Ou seja:
Se CPF→ NOME, DT_NASCIMENTO
então
CPF→ NOME e CPF→ DT_NASCIMENTO
Podemos dizer que se com o CPF eu encontro o NOME e a DT_NASCIMENTO de uma pessoa, caso necessário eu posso, com o CPF, encontrar apenas o NOME ou, com o CPF eu posso encontrar apenas a DT_NASCIMENTO, quando necessário.
2ª Regra Acumulação: Na acumulação vamos analisar a chave composta por dois ou mais elementos e vamos afirmar que, se apenas um dos elementos isolados da chave determinar a um atributo, o mesmo elemento continua a determinar este atributo caso ele faça mais parte da composição de uma chave.
Se X→Z então XW→ Z
Ou seja:
Se CPF→ DT_NASCIMENTO
então
CPF, ID_PRODUTO→ DT_NASCIMENTO
Podemos dizer que se com o CPF eu encontro o DT_NASCIMENTO, caso eu tenha uma outra relação em que CPF esteja compondo a chave com ID_PRODUTO, CPF continua encontrando DT_NASCIMENTO, independente de ID_PRODUTO.
3ª Regra Transitividade: Essa característica é muito importante para que os relacionamentos sejam realizados dentro do Banco de Dados por meio de dependências funcionais indiretas, ou seja:
Se X→Z e Z→W então X→ W
Ou seja:
Se CPF→ CEP e CEP→ CIDADE
então
CPF → CIDADE
Podemos dizer que CPF determina o CEP e que o CEP determina qual é a cidade, logo, podemos afirmar, por transitividade que CPF determina a CIDADE, ou seja, por meio do CEP eu consigo saber qual é a CIDADE.
4 ª Regra Pseudo-Transitividade: Essa regra é bem semelhante a transitividade, mas, ao invés de fazer a transitividade nos atributos, ela ocorre diretamente na chave. Ou melhor, caso eu tenha algum dos elementos da chave que é determinado por outra chave, esta pode substituí-lo, sem perda de capacidade de relacionamento, ou seja:
Se X→Z e ZW→Y então XW→ Y
Ou seja:
Se CPF → PLACA_CARRO
e PLACA_CARRO,DATA → VALOR_MULTA
então
CPF,DATA → VALOR_MULTA
Podemos afirmar que se eu sei o CPF, eu consigo saber qual é a PLACA_CARRO da pessoa e se eu sei a PLACA_CARRO e da DATA eu consigo determinar qual é o valor da multa, logo, se eu tenho o CPF e a DATA eu também consigo saber qual é o VALOR_MULTA.
Como você deve ter observado, as regras são lógicas e autoexplicativas e compreendê-las é muito importante para que possamos saber qual é a origem das formas normais, que vão garantir ao Banco de Dados integridade, segurança e lógica relacional simplificada.
Isto é, elas vão possibilitar que o Banco de Dados tenha os dados modelados de forma que a informação possa ser composta sempre de forma confiável e atualizada, pois o dado está armazenado fisicamente em apenas um local no Banco de Dados e acessível por meio dos relacionamentos proporcionados pelas chaves.
As Formas Normais, utilizadas em banco de dados, são um conjunto de regras que visam, principalmente, a organização do projeto de banco de dados com a finalidade de evitar ou reduzir a redundância de dados, aumentar a integridade e o desempenho nos relacionamentos. As Formans Normais, ou FN, foram definidas originalmente por Edgar Frank Codd, em um trabalho publicado em 1970, e vem sendo aprimoradas dor CJ Date (2004, 2015), explicadas em diversos de seus livros.
As FN têm como base algumas normas definidas a partir das dependências funcionais e que visam garantir que dados armazenados não possuam anomalias.
Pensando em anomalias, que são situações não esperadas, ou não normais, dentro do processamento de dados, podemos citar que as Formas Normais, ou simplesmente FN são regras definidas que buscam “purificar” os dados em relação a eventuais anomalias de atualização (inclusão, alteração e exclusão), que podem destruir gradativamente as informações armazenadas.
Entre os principais problemas que são evitados, estão:
grupos repetitivos (atributos multivalorados) de dados;
variação temporal de certos atributos, dependências funcionais totais ou parciais em relação a uma chave concatenada;
redundâncias de dados desnecessárias;
perdas acidentais de informação;
dificuldade na representação de fatos da realidade observada;
dependências transitivas entre atributos.
Em resumo, a Normalização é uma técnica que permite a depuração de um projeto de Banco de Dados, por meio da identificação de inconsistências. Sendo depuração o processo de limpeza ou purificação.
1ª Forma Normal (1FN): A 1ª Forma Normal é conhecida como a Forma Normal da atomicidade, o que significa que ela determina que cada atributo dentro de uma relvar (ou tabela) deve ser indivisível, ou seja, deve ter apenas um significado dentro de si. Um exemplo fácil para entender essa FN é o atributo nome: Pessoa (CPF, nome_da_pessoa).
É muito comum observarmos em um Banco de Dados o atributo nome_da_pessoa. Analisando o nome de uma pessoa, ele não é atômico, pois pode ser dividido em nome e sobrenome, ou seja, naturalmente viola a 1FN.
Como já citamos anteriormente, as FN não são regras rígidas, elas não visam retirar todas as inconsistências do Banco de Dados, mas sim identificá-las para que o projetista tenha condições de analisar a necessidade ou não em segui-la.
Assim, caso o sistema tenha a necessidade de identificar membros de uma mesma família pelo sobrenome, devemos separar o atributo: pessoa (CPF, nome, sobrenome)
Um outro exemplo são atributos multivalorados, que podem receber mais de um valor, como, por exemplo: historico (matricula_aluno → materias, notas)
Como nós já sabemos que um aluno pode ter várias matérias e cada matéria pode ter várias provas e, cada prova pode ter uma única nota, temos que dividir estes atributos, tornando-os monovalorados, recebendo apenas um valor possível por vez: historico (matricula_aluno, materia, numero_prova, nota)
Observe que na 1FN ainda não estamos trabalhando diretamente com as dependências funcionais, apenas estamos observando os atributos e validando se eles são atômicos e monovalorados.
2ª Forma Normal (2FN): Na segunda forma normal vamos trabalhar com as dependências funcionais, mais precisamente, vamos trabalhar diretamente na chave primária com a pseudo-transitividade. Para atender a 2FN, a relvar tem que:
atender a 1FN;
todos os atributos primos (que fazem parte de uma relação) devem depender funcionalmente de toda chave primária.
Para compreender melhor, essa FN é aplicada somente em relvar que tem a chave primária composta por 2 ou mais elementos.
Quando temos uma relação que atende a 1FN, com uma chave primária composta por apenas 1 elemento, já temos certeza que este é atômico e que os demais elementos na relação não podem ter dependência funcional de parte de uma chave de um único atributo.
Para exemplificar, vamos resgatar o exemplo da lição anterior, que tínhamos inicialmente a relvar E, que representava o Estoque, com a seguinte composição, após elegermos a chave primária:
E( id_forn, id_peça, nome_f, status, cidade, nome_p, cor, peso, qtde, vlr_unit, vlr_total)
Inicialmente identificamos que:
id_forn, id_peça → nome_f, status, cidade, nome_p, cor, peso, qtde, vlr_unit, vlr_total
Mas, observando atentamente, sabemos que não precisamos de id_peca para obter o nome_f, status e cidade, assim como não precisamos de id_forn para obter o nome_p, cor, peso, vlr_unit e vlr_total, logo, podemos dizer que essas duas relações identificadas dependem parcialmente da chave primária (id_forn e id_peca).
Os demais atributos somente têm significado se forem obtidos pela chave primária completa. Desta forma, retiramos na relvar os atributos que são dependentes funcionalmente de parte da chave primária e colocamos em uma nova relvar.
id_forn, id_peça → qtde, vlr_unit, vlr_total
id_forn → nome_f, status, cidade
id_peça → nome_p, cor, peso
3ª Forma Normal (3FN): Na terceira forma normal vamos trazer o conceito de transitividade das dependências funcionais e aplicar a todos os atributos que não fazem parte da chave dentro da relvar, ou seja, enquanto na 2FN nós nos preocupamos em observar os atributos em relação a chave primária, na 3FN nós vamos observar todos os atributos com dependência funcional entre si, que podem ser obtidos por transitividade.
Para estar na 3FN então, podemos dizer que a relvar deve:
Atender a 2FN;
Ter todos os atributos primos dependentes funcionalmente apenas da chave, não havendo dependência funcional entre si.
Para exemplificar, vamos dar continuidade no resultado que obtivemos na 2FN, no exemplo anterior, e analisar caso a caso.
Iniciando por id_peça → nome_p, cor, peso, podemos afirmar que nome_p, cor e peso dependem funcionalmente apenas de id_peça, portanto atende a 2FN e a 3FN naturalmente.
Já em id_forn→ nome_f, status, cidade, podemos afirmar que cidade → status, ou seja, há uma violação de transitividade nessa situação, pois não precisamos manter na mesma relação os dois dados, logo, podemos levar essa relação para uma nova relvar, que ficaria então:
id_forn→ nome_f, cidade
cidade → status
Por último, analisando a relação id_forn, id_peça → qtde, vlr_unit, vlr_total, podemos dizer que vlr_total é um campo calculado, pois é obtido pela multiplicação de vlr_unit com qtde.
Desta forma, podemos retirar esse atributo da relação sem sofrer perda de informação, pois conseguimos recompô-lo a qualquer momento fazendo a multiplicação citada. Desta forma, aplicando a 3FN teríamos as seguintes relações finais:
id_forn, id_peça → qtde, vlr_unit
id_forn→ nome_f, cidade
cidade → status
id_peça → nome_p, cor, peso
Com isso, chegamos a nossa base de dados mínima, que não pode mais ser dividida sem que haja perda de informação. O que vai garantir que no banco de dados não tenhamos redundância de informação e que todos os dados sempre estejam atualizados para que o sistema possa trabalhar gerando informações confiáveis aos usuários.
Vamos agora exercitar as formas normais, aplicando-as na tabela que coletamos de um cliente que está precisando criar um banco de dados para organizar suas informações:
Tabela 1 - Dados de Notas Fiscais de Clientes
Fonte: o autor.
#PraCegoVer: tabela com 4 linhas e 8 colunas. Na primeira linha estão identificados os nomes das colunas, em negrito, sendo, na primeira coluna está escrito cpf, na segunda nome, na terceira cidade, na quarta dt_nasc, na quinta coluna idade, na sexta telefone, na sétima notas_fiscais e na oitava coluna vlr_nfs. Na segunda linha temos os valores, sendo na primeira coluna 123, na segunda Maria Silva, na terceira Londrina, na quarta 01/10/2000, na quinta 21, na sexta (43) 2340-4567, na sétima coluna temos 3 valores, sendo 123, 456, 789 e na oitava coluna também temos 3 valores, sendo 1200, 1500 e 1800. Na terceira linha temos na primeira coluna 456, na segunda José Souza, na terceira Maringá, na quarta 30/11/2003, na quinta 18, na sexta (44) 5439-8765, na sétima coluna 128 e na oitava coluna 564. Na quarta linha temos na primeira coluna 745, na segunda Salvador Dali, na terceira Curitiba, na quarta 12/01/1999, na quinta 23, na sexta (41) 8765-5433, na sétima coluna temos 5 valores, sendo 124, 458,490, 856 e 932 e na oitava coluna também temos 5 valores, sendo 765, 3456, 2000, 500 e 650.
Extraindo os atributos da nossa tabela, vamos criar uma relvar, chamando de NFC (Notas Fiscais de Clientes), com os seguintes atributos: cpf, nome, cidade, dt_nasc, idade, telefone, notas_fiscais, vlr_nfs
Aplicando a 1FN, podemos separar o nome em nome, sobrenome, telefone e ddd e fone e notas fiscais em nr_nf e vlr_nfs e manter junto. Teremos então a seguinte situação: cpf, nome, sobrenome, cidade, dt_nasc, idade, ddd, fone, nr_nf, vlr_nf
Na tabela original, seria espelhado, da seguinte forma:
Tabela 2 - Dados de Notas Fiscais de Clientes normalizada na 1FN
Fonte: o autor.
#PraCegoVer: tabela com 10 linhas e 10 colunas. Na primeira linha estão identificados os nomes das colunas, em negrito, sendo, na primeira coluna está escrito cpf, na segunda nome, na terceira sobrenome, na quarta cidade, na quinta dt_nasc, na sexta coluna idade, na sétima ddd, na oitava fone, na nona nr_nf e na décima coluna vlr_nf. Na segunda linha temos os valores, sendo na primeira coluna 123, na segunda Maria, na terceira coluna Silva, na quarta Londrina, na quinta 01/10/2000, na sexta 21, na sétima 43, na oitava 2340-4567, na nona coluna 123 e na décima coluna 1200. Na terceira linha temos na primeira coluna 123, na segunda Maria, na terceira coluna Silva, na quarta Londrina, na quinta 01/10/2000, na sexta 21, na sétima 43, na oitava 2340-4567, na nona coluna 456 e na décima coluna 1500. Na quarta linha temos na primeira coluna 123, na segunda Maria, na terceira coluna Silva, na quarta Londrina, na quinta 01/10/2000, na sexta 21, na sétima 43, na oitava 2340-4567, na nona coluna 789 e na décima coluna 1800. Na quinta linha temos na primeira coluna 456, na segunda José, na terceira coluna Souza, na quarta Maringá, na quinta 30/12/2003, na sexta 18, na sétima 44, na oitava 5439-8765, na nona coluna 128 e na décima coluna 564. Na sexta linha temos na primeira coluna 745, na segunda Salvador, na terceira coluna Dali, na quarta Curitiba, na quinta 12/01/1999, na sexta 23, na sétima 41, na oitava 8765-5433, na nona coluna 124 e na décima coluna 765. Na sétima linha temos na primeira coluna 745, na segunda Salvador, na terceira coluna Dali, na quarta Curitiba, na quinta 12/01/1999, na sexta 23, na sétima 41, na oitava 8765-5433, na nona coluna 458 e na décima coluna 3456. Na oitava linha temos na primeira coluna 745, na segunda Salvador, na terceira coluna Dali, na quarta Curitiba, na quinta 12/01/1999, na sexta 23, na sétima 41, na oitava 8765-5433, na nona coluna 490 e na décima coluna 2000. Na nona linha temos na primeira coluna 745, na segunda Salvador, na terceira coluna Dali, na quarta Curitiba, na quinta 12/01/1999, na sexta 23, na sétima 41, na oitava 8765-5433, na nona coluna 856 e na décima coluna 500 e na décima linha temos na primeira coluna 745, na segunda Salvador, na terceira coluna Dali, na quarta Curitiba, na quinta 12/01/1999, na sexta 23, na sétima 41, na oitava 8765-5433, na nona coluna 932 e na décima coluna 650.
Identificando a chave primária, agora vamos eleger que cpf e nr_nf compõe juntas a chave, pois são, a princípio, a melhor forma de chegarmos a todas as dependências funcionais que estão apresentadas. Teremos então: cpf, nr_nf → nome, sobrenome, cidade, dt_nasc, idade, ddd, fone, vlr_nf
Aplicando a 2FN, observamos que nome, sobrenome, cidade, dt_nasc, idade, ddd, fone dependem funcionalmente apenas de cpf e vlr_nf depende funcionalmente apenas de nr_nf, desta forma tiramos os atributos dependentes e levamos para uma nova relação, onde temos:
cpf→ nome, sobrenome, cidade, dt_nasc, idade, ddd, fone
nr_nf → vlr_nf
Observamos que a relação original ficou sem atributos, mantendo apenas a chave primária, pois, quando a determinamos, poderíamos ter escolhido outra chave, mas, isso foi deixado como um erro proposital para demonstrar como o uso das FN nos alertam, inclusive, para deficiências de análise.
Considerando que ficamos apenas com cpf, nr_nf → (vazio) vamos analisar apenas os dois atributos. Contextualmente podemos afirmar que nr_nf → cpf, então, podemos também afirmar que nr_nf → cpf, vlr_nf (já tínhamos obtido o nr_nf → vlr_nf anteriormente).
Agora vamos aplicar a 3FN, para finalizar. Observamos que temos duas violações que podem ser consideradas. A primeira está em cidade → ddd e a segunda é que se deixarmos a idade como um valor fixo, em que todo aniversário do cliente vai provocar uma falha de integridade na nossa base, pois é um campo calculado, que pode ser obtido pela subtração da dt_nasc do dia de hoje.
Desta forma vamos levar a dependência funcional transitiva para outra relação e apenas remover o campo calculado. Teremos então a seguinte situação final:
cpf→ nome, sobrenome, cidade, dt_nasc, fone
cidade → ddd
nr_nf → cpf, vlr_nf
Com isso chegamos a nossa base de dados mínima, sem perder qualquer informação e garantindo que vamos ter integridade na base de dados.
Como já estamos entendendo bem da parte de integridade e de criação de Banco de Dados seguro, vamos avançar, na nossa próxima lição, e aprender sobre formas que podemos utilizar para otimizar a busca pelas informações. Até a próxima aula!
DATE, CJ. Introdução aos Sistemas de Banco de Dados , 8ª Edição. São Paulo: GEN LTC, 2004.
DATE, CJ. Projeto de Banco de Dados e Teoria Relacional – Formas Normais e tudo mais. 1ª Edição. São Paulo: Novatec, 2015.