Explicando 2NF vs 3NF com um exemplo


13

Estou com um problema com o segundo formulário normal (2NF) e não consegui resolvê-lo usando o Google. Isso está me deixando louco porque sou professora e não quero ensinar coisas erradas aos meus alunos.

Vamos ter uma mesa com 5 campos.

Classificação = {StudentName, SubjectCode, SubjectName, #Exam, Grade}

As dependências são assim:

StudentName, SubjectCode, #Exam -> Grade

SubjectCode -> SubjectName

SubjectName -> SubjectCode

Portanto, a chave candidata 1 é {StudentName, SubjectCode, #Exam} e a chave candidata 2 é {StudentName, SubjectName, #Exam} .

Os atributos principais são {StudentName, SubjectCode, SubjectName, #Exam} e os atributos não principais são Grade

De acordo com a definição da segunda forma normal, um atributo não primário não pode depender de uma parte de uma chave candidata. O único atributo não primário (Grade) não depende de uma parte de uma chave candidata, portanto, esta tabela aparece em 2NF.

O problema é que acho que algo está errado (e posso estar errado). Eu acho que os assuntos deveriam ter sua própria mesa.

Classificação = {StudentName, Código da disciplina, # Exame, Nota}

Assuntos = {Código do Assunto, Nome do Assunto}

Mas o 2NF não produz isso. O 3NF trata de dependências entre atributos não primos, portanto também não produz isso. Mas parece-me que este é o resultado certo, porque não tem redundância.

Eu acho que se o atributo não primário fosse definido como "atributo que não é uma chave candidata", o 2NF produziria o resultado desejado. Mas verifiquei isso de novo e de novo e o atributo não primário é definido como "atributo que NÃO PERTENCE a uma chave candidata".

O que estou fazendo de errado?

Respostas:


9

Sua relação está em 3NF (e não apenas em 2NF), pois, como você diz, o único atributo que não é primo é Grade , que só aparece no lado direito dos seus DFs.

A relação não está no BCNF, porque o lado esquerdo dos dois FDs pequenos não é uma superchave.

No entanto, você pode decompor sem perdas a relação com ( SubjectCode , SubjectName ) e ( StudentName, SubjectCode, #Exam, Grade ) ou ( StudentName, SubjectName, #Exam, Grade )

Essa decomposição fornece duas relações BCNF e preserva todas as dependências funcionais. Isso nem sempre é possível (você sempre pode decompor uma relação com 3NF, mas não necessariamente com BCNF).

2NF

Se você deseja um exemplo de 2NF (e não de 3NF), sua relação precisa conter dependências transitivas.

Por exemplo, digamos que você tenha uma coluna Pontuação. Pontuação intuitiva-> nota, pois todos os exames com a mesma pontuação devem obter a mesma nota (seria injusto), mas observe que não podemos dizer Grade-> Pontuação, pois várias pontuações podem ter a mesma nota (11% e 12% provavelmente seria "Fail", por exemplo).

Agora sua relação é:

Classificações ( StudentName, SubjectCode, SubjectName, #Exam, Score, Grade )

e você tem uma nova forma de redundância, pois toda vez que inserir um resultado com a mesma pontuação que outro registro de avaliações, você também precisará repetir a nota correspondente. Para chegar ao 3NF, você poderia decompor-se em

ScoreGrades ( Pontuação, Nota )

com Pontuação como a chave e

Pontuações ( StudentName, SubjectCode, SubjectName, #Exam, Score )


4

Você está certo em tudo o que diz. O Código do Assunto, SubjectName precisa entrar em sua própria tabela para impor as dependências desejadas. Este é um bom exemplo de por que 2NF e 3NF não são suficientes para produzir bons designs de banco de dados - você precisa do formulário normal Boyce Codd (BCNF).

2NF e 3NF são substituídos pelo BCNF, o que praticamente torna obsoletas as NFs menores *. O BCNF é o mais importante e sem dúvida mais simples de explicar e aplicar. Como professor, sugiro que você gaste mais tempo no BCNF e menos no 2NF e 3NF. Se uma tabela atender aos requisitos do BCNF, também atenderá aos 2NF e 3NF.


* 3NF não é a Forma Normal de preservação de dependência mais alta. A chave normal da chave elementar (EKNF) é. Estritamente falando, é o EKNF, não o BCNF, que torna o 3NF obsoleto, mas o EKNF é injustamente negligenciado e a maioria dos livros e cursos nem o menciona. O que equivale à mesma coisa é projetar para o BCNF e, em seguida, verificar se todas as dependências desejadas e quaisquer outras regras de integridade podem ser aplicadas corretamente - se não, modifique o design. Nenhuma das NFs é uma solução completa para a integridade dos dados, mas o BCNF geralmente se aproxima e é o mais fácil de explicar e usar.


Você tem boas referências para o EKNF, especialmente para iniciantes? Estou tentando ler e encontrar uma boa documentação, pois se mostrou difícil. Fora do resumo de uma linha do Wiki, uma explicação funcional de funcionamento das sutilezas de EKNF vs BCNF / 3NF que ainda não encontrei.
Saijin_Naib

2

Não vou dizer quanto tempo se passou desde que aprendi tudo isso. Mas lembro que tinha um professor que, depois de nos ensinar obedientemente o significado adequado de "dependência funcional" e "atributo não primordial" e todas as outras chavões, nos deu uma série de perguntas simples para perguntar se uma determinada normalidade formulário foi atingido. Vamos ver se consigo me lembrar disso há muito tempo ...

Identificamos a (s) chave (s) candidata (s) e, portanto, fazemos essa pergunta dos demais atributos não principais. Nesse caso, existe apenas um: nota.

Qual é a informação mínima absoluta necessária para identificar exclusivamente a nota? Precisamos conhecer o aluno, o assunto e o exame que está sendo realizado. Tudo bem, essa é uma das chaves candidatas.

EDIT: VVV

Mas a resposta poderia muito bem ter sido o nome do aluno, o assunto e o exame. Isso corresponderia à segunda chave candidata.

Supondo que SubjectCode e SubjectName são chaves candidatas para a entidade Subject, não há razão para ter esses dois campos aqui. Uma referência exclusiva a uma linha na tabela Assuntos é suficiente. Portanto, podemos nos livrar com segurança do campo SubjectName sem sacrificar nenhuma integridade do modelo.

No entanto, em minha resposta original, em meu desejo de mostrar outro nível de normalização, ignorei que SubjectName havia sido usado em uma chave candidata e o considerei apenas outro atributo não primário. Eu acho que era tão óbvio para mim que este era um campo inútil que pensei que seria tão óbvio para todos e, como de qualquer maneira nos livramos do campo, o que importava?

Mas, em vez de remover essa parte da resposta, vou mantê-la em comparação.

END EDIT: ^ ^ ^

Qual é a informação mínima absoluta necessária para identificar exclusivamente o nome do sujeito?

SubjectName depende apenas do SubjectCode - um subconjunto da chave candidata. Portanto, esta tupla não está em 2nf. SubjectCode deve ser a chave primária de uma tabela de assuntos, para que seja o local apropriado para colocar SubjectName. Remova-o desta tupla e agora está em 2nf.

Se fizermos a pergunta de um atributo e a resposta não for toda ou parte da chave candidata, a tupla não estará em 3nf. Mas essa tupla também é trivial em 3nf e além, pois ficamos sem campos para fazer perguntas. ;)

Nota: quando dizemos "normalizar", estamos nos referindo a um processo que é aplicado a uma entidade lógica. Como a tupla fornecida parece ser a definição de uma entidade chamada "nota", podemos normalizá-la. No entanto, em um ponto, eu disse "essa tupla não está em 2nf", o que deveria ser mais apropriadamente ", essa entidade não está em 2nf". Peço desculpas se isso causou confusão.


2

O único atributo não primário (Grade) não depende de uma parte de uma chave candidata, portanto, esta tabela aparece em 2NF.

É em 2NF.

O problema é que acho que algo está errado (e posso estar errado). Eu acho que os assuntos deveriam ter sua própria mesa.

Não há razão para esperar que os participantes tenham sua própria tabela para decompor a tabela original em 2NF . Você está confundindo alguma noção vaga de "deveria" com o que qualquer forma normal específica realmente lhe dá.

O 3NF trata de dependências entre atributos não primos, portanto também não produz isso.

"3NF é sobre dependências entre atributos não primos" não é uma definição adequada de 3NF, portanto "assim também não produz isso" não é uma conclusão sólida. Embora a aplicação de uma definição real mostre que a tabela está no 3NF, não é necessária nenhuma tabela do aluno. Mas, novamente, não há razão para esperar que exista.

Mas parece-me que este é o resultado certo, porque não tem redundância.

Mais uma vez, a "redundância" é inútil, de modo que a expectativa do "porque" e da tabela do aluno não é satisfatória. Diferentes formas normais estão livres e sujeitas a tipos específicos de anomalias e "redundância" associada. Mas outras "redundâncias" não abordadas pela normalização podem permanecer.

Esta tabela não está no BCNF, pois possui FDs que não estão fora das CKs. Decompô-lo pelo BCNF leva a ter a mesa do aluno. O BCNF é a forma normal mais alta para lidar com JDs (dependências de junção) que acompanham os FDs. No entanto, outros JDs podem ser problemáticos (ou seja, não "implícitos pelas CKs") e devem ser removidos por normalização para 5NF.

PS A tabela original também atende ao FD {StudentName, SubjectName, #Exam} -> Grade.

As dependências são assim:

O que isso significa? Não está claro.

Você quer dizer: "Esses são todos os DFs não triviais que são válidos"? Não, porque eles implicam o quarto. "Aqui estão alguns DFs que valem"? Não, isso significa que os FDs no fechamento transitivo se mantêm, mas não diz que outros não se mantêm, mas você conseguiu determinar as CKs. "Os DFs que detêm são exatamente os que estão no fechamento transitivo destes"? Se você quisesse dizer isso, só saberia se tivesse mostrado , ou seja, teria que encontrar o fechamento (normalmente, através de uma cobertura mínima / canônica) e depois mostrar que não há outros DFs; você fez? Independentemente disso, o que você escreveu simplesmente não significa isso. Portanto, espero que você não esteja discutindo profundamente sobre a situação de FD & CK.


0

Você está correto, os assuntos exigem sua própria tabela. Se você pegar uma das suas chaves candidatos, seja subject_codeou subject_namese torne uma chave candidata não primário. Você remove o campo de assuntos não primários da tabela de notas.

Você tem uma dependência funcional do assunto para a qual possui dois identificadores exclusivos. Isso é demonstrado pela dependência transitiva entre subject_codee subject_name. Isso indica um requisito para criar uma tabela contendo esses dois campos e remover um desses campos de todas as outras tabelas. Essa tabela pode ter colunas dependentes adicionais, embora eu não veja nenhuma neste exemplo. Na terceira forma normal que você selecionou.

A nota depende dos outros três campos (chave do candidato) na nova tabela de classificações. Como observado acima, você precisa escolher um dos campos candidatos para a tabela de assuntos. Normalmente, esse seria um valor de código, se disponível, pois eles tendem a ser mais estáveis. O modelo resultante está em 3nf, pois todos os campos não chave são totalmente dependentes dos campos na chave primária.

Uma análise mais aprofundada do problema (requisitos) provavelmente produzirá uma tabela de sessões na qual as marcas são aplicadas. É improvável que o modelo atual cubra um aluno que repete um curso. Isso seria abordado em uma lição posterior.

Os alunos também provavelmente se tornarão uma tabela separada, pois é possível ter vários alunos com o mesmo nome. Isso provavelmente seria resolvido com a adição de uma chave primária sintética (número do aluno?).

subjects --->  sessions ---+--> grades
students  -----------------+

3
"Se você escolher uma das chaves candidatas , subject_code ou subject_name se tornará uma chave candidata não primária ." Isto está claramente errado. O restante da análise tem alguns pontos valiosos, mas quando se começa a partir de um ponto falso, não podemos confiar nas conclusões.
precisa saber é o seguinte

-7

Estou me preparando para excluir isso, pois é considerado incorreto

O Nome do Assunto também é um atributo não primário e depende de parte do Código de Assunto da chave primária (quebra de regra - não deve haver dependência parcial de nenhuma coluna na chave primária).

Isso é proibido na 2ª forma normal e, portanto, deve ser colocado em sua própria mesa, como você suspeitou.

Eu acho que o ponto de desconexão está na identificação de dois conjuntos de chaves candidatas; quando você cria a tabela, deve escolher um conjunto de chaves candidatas para criar a chave primária. As colunas restantes se tornam atributos não primos, ou seja, se você escolheu sua segunda chave candidata, o Código do Assunto se torna um atributo não primo dependente de parte da chave primária (Nome do Assunto) e deve ser colocado em sua própria tabela.

É importante ensinar a 1ª, 2ª e 3ª formas normais para que elas se desenvolvam. O BCNF também é essencialmente uma extensão da 3ª forma normal, portanto é essencial uma forte compreensão dos níveis mais baixos.

Mais longe; um desenvolvedor experiente não considerará os níveis independentes de normalização porque muitas regras se tornam intuitivas.

Eles também saberão quando quebrar as regras de normalização para resolver certos problemas de design e otimização. A normalização deve ser tratada como um guia para um bom design, não uma regra rigorosa, acredito que também seria um bom ponto de ensino.


1
O OP diz corretamente que "a chave candidata 2 é {StudentName, SubjectName, #Exam}". Portanto, StudentNameé um atributo primordial.
usar o seguinte comando

1
"Ao criar a tabela, você deve escolher um conjunto de chaves candidatas para criar a chave primária. As colunas restantes se tornam atributos não primos. " Isso está claramente errado.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.