Tudo bem ter uma chave estrangeira como chave primária?

102

Eu tenho duas mesas:

  • Usuário (nome de usuário, senha)
  • Perfil (profileId, gênero, data de nascimento, ...)

Atualmente estou usando esta abordagem: cada registro de Perfil tem um campo denominado "userId" como chave estrangeira que se vincula à tabela User. Quando um usuário se registra, seu registro de Perfil é criado automaticamente.

Estou confuso com a minha sugestão de amigo: ter o campo "userId" como a chave primária e estrangeira e excluir o campo "profileId". Qual abordagem é melhor?

Duc Tran
fonte
3
O Entity Framework gera isso (com o código primeiro) para relações zeroOrOne (e um) -para-um. Então ... é possível. É a melhor maneira ... Essa é outra pergunta. Mas é válido. Nunca fiz isso ao criar meus próprios bancos de dados (mas nunca pensei nisso).
Raphaël Althaus

Respostas:

132

As chaves estrangeiras são quase sempre "Permitir duplicatas", o que as tornaria inadequadas como chaves primárias.

Em vez disso, encontre um campo que identifique exclusivamente cada registro na tabela ou adicione um novo campo (um inteiro de incremento automático ou um GUID) para atuar como a chave primária.

A única exceção a isso são as tabelas com um relacionamento um para um , em que a chave estrangeira e a chave primária da tabela vinculada são uma e a mesma.

Robert Harvey
fonte
73
Uma chave primária composta que consiste em duas chaves estrangeiras também é perfeitamente adequada para implementar relacionamentos muitos para muitos.
rightfold
1
@rezadru: Longe de mim discordar do rightfold, mas uma chave substituta é quase sempre uma escolha melhor.
Robert Harvey
4
Nada sobre uma chave estrangeira determina que ela seja de 1 para muitos (ou "permitir duplicatas" conforme escritas). Restrições de chave e exclusividade são dois conceitos separados em um banco de dados e podem ser facilmente misturados com a mesma facilidade com a adição de um índice (o que seria um terceiro conceito separado).
cego de
40

As chaves primárias sempre precisam ser exclusivas, as chaves estrangeiras precisam permitir valores não exclusivos se a tabela for uma relação um-para-muitos. É perfeitamente normal usar uma chave estrangeira como chave primária se a tabela estiver conectada por um relacionamento um para um, não um relacionamento um para muitos. Se você deseja que o mesmo registro de usuário tenha a possibilidade de ter mais de 1 registro de perfil relacionado, vá com uma chave primária separada, caso contrário, mantenha o que você tem.

kotekzot
fonte
11

Sim, é legal ter uma chave primária sendo uma chave estrangeira. Esta é uma construção rara, mas se aplica a:

  • uma relação 1: 1. As duas tabelas não podem ser mescladas em uma por causa de permissões e privilégios diferentes que se aplicam apenas no nível da tabela (em 2017, esse banco de dados seria estranho).

  • uma relação 1: 0..1. O perfil pode ou não existir, dependendo do tipo de usuário.

  • o desempenho é um problema, e o design atua como uma partição: a tabela de perfis raramente é acessada, hospedada em um disco separado ou tem uma política de fragmentação diferente em comparação com a tabela de usuários. Não faria sentido se o armazenamento sublinhado fosse colunar.


fonte
Haveria um desempenho negativo se as tabelas fossem unidas com frequência, o que leva à recomendação normal de que 1 tabela é melhor. Em alguns casos, os dados são sempre acessados ​​separadamente, não unidos, e pode haver uma vantagem organizacional em ter duas tabelas com um relacionamento 1: 1.
cego de
4

É geralmente considerado uma má prática ter um relacionamento pessoal. Isso ocorre porque você poderia apenas ter os dados representados em uma tabela e obter o mesmo resultado.

No entanto, há casos em que você pode não conseguir fazer essas alterações na tabela que está se referindo. Neste caso, não há problema em usar a chave estrangeira como chave primária. Pode ser útil ter uma chave composta consistindo em uma chave primária exclusiva de incremento automático e uma chave estrangeira.

Atualmente, estou trabalhando em um sistema em que os usuários podem fazer login e gerar um código de registro para usar com um aplicativo. Por motivos que não irei abordar, não consigo simplesmente adicionar as colunas necessárias à tabela de usuários. Portanto, estou percorrendo uma rota de um para um com a tabela de códigos.

Tshsmith
fonte
2
Eu concordo com você principalmente que há muitas vantagens em ter todos os dados na mesma tabela como colunas adicionais. Embora tenha escrito isso .. "você pode apenas ter os dados representados em uma tabela e obter o mesmo resultado" ..: ter uma tabela separada pode ser útil, por exemplo, aqui se a entrada da tabela de perfil for opcional. Por exemplo, todo cliente de banco pode não ter um registro de internet banking. Nesse caso, a tabela de registro IB pode ser usada para restringir outras tabelas de ter mais registros filho. Novamente, aqui isso poderia ser feito com um novo PK para a tabela de registro IB também.
Teddy
1
@Teddy Da mesma forma, concordo principalmente com o que você disse. No entanto, na pergunta original eles afirmam "... seu registro de Perfil é criado automaticamente ...", implicando que a tabela de Perfil não é opcional. Em uma situação onde a tabela de perfis era opcional, sim, tê-la como uma tabela separada é possível. Mas, novamente, eles poderiam apenas usar colunas anuláveis ​​na mesma tabela.
Tshsmith
1
Usando uma segunda tabela separada, podemos evitar a entrada em uma terceira tabela, que só é permitida para pessoas que têm uma entrada na segunda tabela.
Teddy de
Com certeza, mas se fundirmos as tabelas de 1 para 1, podemos evitar que pessoas com valores nulos acessem a terceira tabela (tecnicamente a segunda agora). Mas a pergunta que OP fez contém a linha "... ao se inscrever .. ... o registro do seu perfil é criado automaticamente ...", tornando isso redundante.
Tshsmith de
Meu principal motivo para considerar isso é que, no armazenamento de dados, é uma boa prática separar tabelas de fatos e dimensões. As tabelas separadas de fatos e dimensões são dicas úteis ao trabalhar com softwares como PowerPivot, PowerBI e Tableau.
Marco Rosas de
4

Sim, uma chave estrangeira pode ser uma chave primária no caso de um relacionamento um para um entre essas tabelas

Riaj Ferdous
fonte
2
isso também é útil para projetos de supertipos e subtipos. A chave primária das tabelas de subtipo deve ser uma referência de chave estrangeira para a tabela de supertipo.
axelioo
2

Eu não faria isso. Eu manteria a profileIDcomo chave primária da tabelaProfile

Uma chave estrangeira é apenas uma restrição referencial entre duas tabelas

Alguém poderia argumentar que uma chave primária é necessária como alvo de quaisquer chaves estrangeiras que se refiram a ela em outras tabelas. Uma chave estrangeira é um conjunto de uma ou mais colunas em qualquer tabela (não necessariamente uma chave candidata, muito menos a chave primária dessa tabela) que pode conter os valores encontrados na (s) coluna (s) de chave primária de alguns outra mesa. Portanto, devemos ter uma chave primária para corresponder à chave estrangeira. Ou devemos? O único propósito da chave primária no par de chave primária / chave estrangeira é fornecer uma junção inequívoca - para manter a integridade referencial com respeito à tabela "estrangeira" que contém a chave primária referenciada. Isso garante que o valor ao qual a chave estrangeira se refere será sempre válido (ou nulo, se permitido).

http://www.aisintl.com/case/primary_and_foreign_key.html

Massimiliano Peluso
fonte
1
Talvez - se você tiver a restrição FK entre User.UserID e Profile.UserID, então seria altamente recomendável ter um índice em Profile.UserID. Por que não torná-lo o índice clusterizado primário na tabela Profile, economizando um segundo índice e um monte de trabalho desnecessário para o mecanismo de banco de dados?
Engenheiro
1

Depende do negócio e do sistema.

Se o seu userId for exclusivo e será exclusivo o tempo todo, você pode usar o userId como sua chave primária. Mas se você quiser expandir seu sistema, isso tornará as coisas difíceis. Aconselho você a adicionar uma chave estrangeira no usuário da tabela para fazer um relacionamento com o perfil da tabela em vez de adicionar uma chave estrangeira no perfil da tabela.

Vincent Cai
fonte
0

Resposta curta: DEPENDE ... Nesse caso em particular, pode ser bom. No entanto, os especialistas não recomendam isso quase todas as vezes; incluindo o seu caso.

Por quê?

As chaves raramente são exclusivas em tabelas quando são estrangeiras (originadas em outra tabela) da tabela em questão. Por exemplo, um ID de item pode ser único em uma tabela de ITENS, mas não em uma tabela de PEDIDOS, uma vez que o mesmo tipo de item provavelmente existirá em outro pedido. Da mesma forma, os IDs de pedido podem ser únicos (podem) na tabela PEDIDOS, mas não em alguma outra tabela como ORDER_DETAILS, onde um pedido com vários itens de linha pode existir e para consultar um item específico em um pedido específico, você precisa da concatenação de dois FK (order_id e item_id) como o PK para esta tabela.

Não sou um especialista em DB, mas se você puder justificar logicamente para ter um valor gerado automaticamente como seu PK, eu faria isso. Se isso não for prático, uma concatenação de dois (ou talvez mais) FK pode servir como seu PK. MAS, não consigo pensar em nenhum caso em que um único valor FK possa ser justificado como o PK.

Hfontanez
fonte