Respostas às suas perguntas individuais
Se eu quiser adicionar uma coluna Club
que descreva o proprietário, que também será membro, qual é a melhor abordagem sem ter o mesmo membro listado duas vezes?
Se, como indicado em suas especificações a Person can be a Member of only one Club
, e você estiver interessado em armazenar esse dado simplesmente como verdadeiro ou falso , uma opção é adicionar uma coluna BIT(1)
ou uma BOOLEAN
( TINYINT
) à Person
tabela e você pode chamá-la IsClubOwner
. Dessa forma, você pode registrar o fato de que uma determinada pessoa é dona de um clube exclusivamente uma vez. Além disso, esse método também permite manter várias pessoas como donos da mesma ocorrência de clube . Você pode ver uma representação em nível lógico dessa abordagem na Figura 1 .
No entanto, você está procurando a melhor abordagem e, de acordo com minha experiência, essa abordagem implica o desenvolvimento de uma estrutura muito mais expansível e versátil. A esse respeito, siga a progressão de um exercício de modelagem para esses e outros pontos abaixo, nas seções intituladas “Cobrindo suas especificações restantes”, “Pessoa como membro de vários clubes” e “Membro e proprietário como tipos de entidade separados”.
Devo colocar todas as minhas tabelas no incremento automático de uma id
ou isso seria uma má idéia? (benefícios / desvantagens?)
Se você enfrentar um requisito explícito que indica a definição de uma tabela com uma coluna com essas características, e essa coluna tiver um significado contextual válido ou servir a um propósito específico, como ser um substituto para uma ampla PRIMARY KEY (PK) natural, então sim, você deve proceder dessa maneira.
Caso contrário, se você não tiver dito esse requisito, considero desnecessário, pois é necessário armazenar e gerenciar uma coluna extra sem sentido e (talvez?) Também um índice adicional em seu banco de dados.
Como sempre, você deve analisar cada caso, juntamente com suas repercussões gerais, a fim de decidir como prosseguir.
Se eu adicionar chaves estrangeiras na guia Chaves estrangeiras, elas corresponderão automaticamente à tabela correta ou também devo adicioná-las às colunas?
Nesse sentido, meu conselho para você é criar sua estrutura de banco de dados manualmente, codificar suas próprias DDL
declarações até obter uma compreensão firme do assunto. Se você fizer isso, será mais fácil entender os processos que as ferramentas gráficas estão executando "sob o capô".
Para mim, por exemplo, criando uma declaração como a seguinte:
CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)
É muito mais instrutivo do que usar ferramentas da GUI para executar esse tipo de tarefas, especialmente agora que você está criando seus primeiros projetos.
E minha pergunta provavelmente a mais nobre de todas ... Coloco as chaves estrangeiras de phone_number
e email
na respectiva tabela vinculadas a uma person_id
ou devo colocar phone_number
e email
ids
na tabela de pessoas?
Pessoalmente, acho que essa e todas as suas outras perguntas são completamente válidas e bem contextualizadas .
Voltando aos aspectos técnicos que nos interessam, essa investigação precisa oferece uma boa oportunidade para revisar as duas afirmações a seguir:
A Person can be reached through zero-one-or-many PhoneNumbers
A PhoneNumber can be used to reach one-to-many People
Portanto, pode-se concluir que há um relacionamento muitos-para-muitos entre Person
e PhoneNumber
, portanto, sugiro a criação de uma tabela associativa nomeada PersonPhoneNumber
para representar o referido relacionamento em seu banco de dados. A PK desta tabela deve ser composta por duas colunas diferentes: PersonId
(uma CHAVE ESTRANGEIRA [FK] apontando para Person.PersonId
) e PhoneNumber
(uma FK que faz referência a PhoneNumber.Number
). Para uma descrição do nível lógico de todas as opções acima, consulte a Figura 1 .
Por outro lado, vamos examinar as duas proposições a seguir:
A Person can be contacted via zero-one-or-many EmailAddresses
An EmailAddress can be used to contact exactly one Person
Então, sim, você deve definir uma referência de FK a Person
partir da EmailAddress
tabela, e essa tabela também deve ter uma PK composta, que seria composta pelas colunas PersonId
e Address
. Dessa maneira, você pode garantir que a mesma combinação EmailAddress.PersonId
e EmailAddress.Address
possa ser inserida apenas uma vez.
Se você também deseja garantir que um dado EmailAddres.Address
possa ser armazenado em uma única linha, basta estabelecer uma Restrição Única para esta coluna.
Modelos de dados lógicos propostos
Para expor minhas sugestões com mais clareza, incluí quatro modelos lógicos distintos do IDEF1X [1] que são mostrados na Figura 1 , Figura 2 , Figura 3 e Figura 4 . Fornecerei uma explicação dos recursos mais relevantes exibidos em cada um deles nas seções correspondentes. Você também pode baixar do Dropbox um PDF que integra em um único modelo a maioria dos elementos em discussão.
Cobrindo suas especificações restantes
Relacionando pessoas e endereços
Vamos examinar as duas seguintes afirmações (ligeiramente reformuladas) que são relevantes para pessoas e endereços :
A Person can only have one Address
An Address can belong to different People (couples or siblings)
Portanto, para lidar com essas restrições, você pode optar por implementar um modelo de dados semelhante ao que você pode ver na Figura 1 .
Levando em conta o modelo referido, você deve seguir os próximos passos:
Crie uma tabela chamada PersonAddress
corrigindo um relacionamento entre Person
e Address
. Defina as colunas PersonId
e AddressId
como o PK composto desta tabela.
Configure um CONSTRAINT UNIQUE para a PersonAddress.PersonId
coluna para garantir que um valor específico possa ser inserido em no máximo uma linha da referida tabela. No nível lógico, essa circunstância implica que PersonAddress.PersonId
se tornou uma CHAVE ALTERNATIVA [2] .
Se o valor de AddressId
uma determinada PersonAddress
tentativa de inserção ainda não estiver armazenado, deixe a inserção continuar; caso contrário, quando esse valor já existir em uma linha, você deverá verificar se (a) PersonId
quem registrou AddressId
também está registrado como o Marriage.WifeId
se o PersonId
é um homem (dado derivado do Person.GenreCode
) ou (b) que PersonId
é o Marriage.HusbandId
quando o PersonId
é uma mulher (derivada também em virtude de Person.GenreCode
). Se uma dessas condições for atendida na situação apropriada, você deverá deixar o INSERT continuar.
Se as condições acima não foram cumpridas, ainda há uma chance de uma PersonAddress
tentativa de inserção ser bem-sucedida. Você deve verificar se o PersonId
valor envolvido na inserção inserida compartilha pelo menos um Progeny.ParentId
com o PersonId
que já registrou o PersonAddress.AddressId
. Se essa condição for atendida, significa que eles são armazenados como Siblings
no banco de dados, portanto, este INSERT deve ser bem-sucedido.
Como em qualquer implementação de banco de dados relacional, considere seriamente executar suas DML
operações nas transações do ACID, para proteger a integridade e a consistência dos dados com os quais você está trabalhando.
Atender aos requisitos que você adicionou nos comentários: Endereços e números de telefone que atendem igualmente a clubes e pessoas
Desde que você deseje que os endereços e números de telefone sirvam pessoas e clubes , você pode usar um relacionamento de supertipo-subtipo . Aqui está uma resposta na qual dou um tratamento mais detalhado a esse tipo de estrutura, caso você esteja interessado.
No cenário atual, você pode definir Person
e Club
como subtipos de uma nova entidade denominada Party
, um termo comumente usado em círculos jurídicos para representar (a) uma pessoa ou (b) um grupo de pessoas (conforme observado no sentido 6 ). Com esse método, os relacionamentos entre Addresses
(ou PhoneNumbers
) e People
e Clubs
seriam definidos por meio Party
do supertipo. Veja a Figura 2 para uma representação desta sugestão.
Parte e endereço
Então, podemos ler neste novo modelo que:
A Party keeps zero-one-or-many Addresses
An Address is kept by one-to-many Parties
Assim, há um relacionamento muitos-para-muitos envolvendo Party
e Address
que é expresso por meio da PartyAddress
entidade.
Party and PhoneNumber
Além disso, podemos interpretar que:
A Party is reached through zero-one-or-many PhoneNumbers
A PhoneNumber is used by one-to-many Parties
Por isso, adicionei a PartyPhoneNumber
entidade que descreve a associação muitos-para-muitos que entra em vigor entre os tipos de entidade Party
e PhoneNumber
.
Parte e clube ou pessoa
Então, também pode ser lido que:
A Party is either a Club or a Person
Por conseguinte, Party
fornece uma ligação de um ou outro Clubs
ou People
para Addresses
(ou PhoneNumbers
).
Pessoa como membro de vários clubes
Como @aldwinaldwin menciona em sua resposta, se você deseja fornecer a funcionalidade para uma pessoa ser membro de vários clubes , pode incluir uma tabela chamada ClubMember
que estaria agindo como outro relacionamento de muitos para muitos, desta vez naturalmente , interconectando Person
e Club
.
Acrescentarei ao exposto que esta tabela também pode ser útil no objetivo de armazenar qualquer pessoa concreta como proprietária de vários clubes , por meio da inclusão da IsClubOwner
coluna booleana já mencionada . De fato, pode-se dizer que esta nova tabela é a representação de um tipo de entidade integral por direito próprio.
Como demonstrado na Figura 3 , essa tabela requer uma PK composta composta pelas colunas ClubId
e MemberId
(um nome de função [3] dado a PersonId
), e essas colunas devem ser definidas também como FKs apontando, correspondentemente, para Club
e Person
.
Uma estrutura mais adaptável
Empregando essa configuração, você também pode cumprir a regra inicial que declara isso a Person can be a member of only one Club
, mas você só precisa adicionar uma restrição exclusiva à MemberId
coluna, para que um determinado valor possa ser inserido em mais de uma ocasião. Portanto, como você pode observar, essa estrutura é muito mais adaptável que a mostrada na Figura 1 , uma vez que, ao descartar o UNIQUE CONSTRAINT (ou INDEX), você abriria a funcionalidade mencionada acima, de permitir que uma pessoa se torne membro de diferentes clubes do clube. mesmo tempo.
Membro e Proprietário como tipos de entidade separados
Como você sabe, o armazenamento de vários fatos sobre o papel desempenhado por uma pessoa como proprietário de um clube - além de sua mera existência em um atributo verdadeiro ou falso - pode ser muito vantajoso. Por exemplo, convém manter a data efetiva em que uma pessoa definida se tornou proprietária de um clube ; portanto, você pode gerenciar essa situação introduzindo um tipo de entidade separado chamado ClubOwner
, conforme apresentado na Figura 4 .
Depois de criar uma tabela com base nesse novo tipo de entidade, você pode adicionar as colunas de ajuste que representam as características que entram em jogo exclusivamente quando a Person
é a Owner
de a Club
. Conforme representado, esta tabela conteria uma PK composta pelas colunas FK referenciadas Person.PersonId
e Club.ClubId
, dessa forma, qualquer combinação de ClubOwner.OwnerId
(ou ClubOwner.PersonId
, se preferir) e ClubOwner.ClubId
pode ser inserida em apenas uma oportunidade.
Obviamente, com essa configuração, você ainda pode derivar em forma booleana se a Person
é Owner
uma particularidade Club
com o auxílio de uma consulta que retorna um valor escalar que pode ser avaliado como verdadeiro ou falso .
Notas
1. A Definição de Integração para Modelagem de Informações ( IDEF1X ) é uma técnica de modelagem de dados altamente recomendável que foi definida como padrão em dezembro de 1993 pelo Instituto Nacional de Padrões e Tecnologia dos Estados Unidos ( NIST ). É solidamente baseada em (a) alguns dos trabalhos teóricos de autoria do criador do modelo relacional , isto é, Dr. EF Codd ; na (b) teoria da Entidade-Relacionamento , desenvolvida pelo Dr. PP Chen ; e também (c) a Logical Database Design Technique , criada por Robert G. Brown . Vale ressaltar que o IDEF1X foiformalizado por meio de lógica de primeira ordem .
2. Uma CHAVE ALTERNATIVA é um atributo (ou uma combinação de atributos) que contém valores que identificam exclusivamente uma ocorrência de entidade, mas não foram escolhidos como a PK do tipo de entidade pertinente; cada tipo de entidade pode ter zero, uma ou mais CHAVES ALTERNATIVAS. Num modelo IDEF1X, eles são são indicados como “AK” para além do seu respectivo número, por exemplo, AK1, AK2, etc. Eles são geralmente implementadas em um SQL DDL estrutura através de uma restrição exclusiva (ou um UNIQUE INDEX ).
3. Os nomes das funções são denotações (ou aliases) atribuídos aos atributos do FK, a fim de expressar o significado que eles possuem no escopo de sua respectiva entidade. Seu uso é recomendado desde 1970 pelo Dr. Codd em seu artigo seminal intitulado "Um modelo relacional de dados para grandes bancos de dados compartilhados" . Por sua vez, o IDEF1X - mantendo a fidelidade em relação às práticas relacionais - também defende a nomeação de funções.
clubId
também o número de telefone e deixo o clube ou a pessoa definida como nula?