Devo usar chaves primárias de várias colunas ou adicionar uma nova coluna?

15

Meu design atual de banco de dados utiliza uma chave primária de várias colunas para usar os dados existentes (que seriam únicos de qualquer maneira) em vez de criar uma coluna adicional atribuindo a cada entrada uma chave arbitrária. Eu sei que isso é permitido, mas estava me perguntando se essa é uma prática que eu gostaria de usar com cautela e possivelmente evitar (muito parecido com ir para C).

Então, quais são algumas das desvantagens que eu vejo nessa abordagem ou os motivos pelos quais desejo uma única chave de coluna?

Covar
fonte
2
Não sei, acho que isso teria sido melhor no SO.
FrustratedWithFormsDesigner
2
@FrustratedWithFormsDesigner Poderia ir para SO, mas acho que funciona aqui também, já que o foco da pergunta parece estar no "quais são os prós e os contras dessa abordagem" em vez de "como eu faço o X?".
Adam Lear
@ Anna Lear ♦: É um "prós e contras" sobre as decisões de design que terão um impacto direto e definitivo na codificação, então acho que o SO seria um lugar melhor.
FrustratedWithFormsDesigner

Respostas:

8

Normalmente, quando você tem uma tabela com uma chave primária de várias colunas, é o resultado de uma tabela de junção (muitos para muitos) que se elevou para ser sua própria entidade (e, portanto, merece sua própria chave primária). Há muitos que argumentam que qualquer tabela de junção DEVE ser uma entidade por padrão, mas essa é uma discussão para outro dia.

Vejamos um relacionamento hipotético de muitos para muitos:

Aluno * --- * Classe

(um aluno pode estar em várias turmas, uma turma pode ter vários alunos).

Entre essas duas tabelas, haverá uma tabela de junção chamada StudentClass (ou ClassStudent, dependendo de como você a escreve). Às vezes, você deseja acompanhar coisas como quando o aluno estava na sala de aula. Então você o adicionará à tabela StudentClass. Neste ponto, StudentClass se tornou uma entidade única ... e deve receber um nome para reconhecê-lo como tal, por exemplo, Inscrição.

Aluno 1 --- * Inscrição * --- 1 Classe

(um aluno pode ter muitas matrículas, cada matrícula é para uma turma (ou seguindo o caminho oposto que uma turma pode ter muitas matrículas, cada matrícula é para um aluno).

Agora você pode consultar questões como, quantos alunos estavam matriculados na aula de Química 101 no ano passado? Ou em quais aulas o aluno que John Doe se matriculou enquanto cursava a Universidade Acme? Isso foi possível sem a chave primária separada, mas depois que você tiver uma chave primária para inscrição, uma consulta mais fácil será sobre essas inscrições (por ID), quantos alunos receberam uma nota de aprovação?

A determinação de se uma entidade merece uma PK se resume a quantas consultas (ou manipulação) você fará por essa entidade. Digamos, por exemplo, que você deseja anexar as tarefas concluídas para um aluno em uma classe. O local lógico para anexar esta entidade (atribuição) seria na entidade de inscrição. Dar à inscrição sua própria chave primária tornaria as consultas de atribuição mais simples.

Michael Brown
fonte
1
Então você o adicionará à tabela StudentClass. Neste ponto, StudentClass se tornou uma entidade única ... e deve receber um nome para reconhecê-lo como tal, por exemplo, Inscrição. É uma coisa tão simples, mas há muito valor em fazer isso!
Botis
8

Faz sentido ter uma coluna de identificação separada. Quando você deseja obter algo da sua tabela de banco de dados, é mais fácil:

SELECT whatever FROM table WHERE id=13

que SELECT qualquer tabela FROM WHERE col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3'

Por exemplo, em um aplicativo Web, ele se traduz em um URL parecido com este:

www.somewebsite.com/somepage.php?id=13

ou assim:

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3
infravermelho
fonte
4
E é muito mais fácil adicionar uma tabela relacionada quando você pode ligar em uma Id, em vez de várias colunas
CaffGeek
3
Desculpe, neste momento eu tenho que -1, pois A) não é preto e branco. A adição de uma coluna de ID vem com negativos, como onde e quando você gera esse novo ID. Além disso, isso pode resultar em junções ou SELECTconsultas extras . E, B) , não tenho idéia de como isso realmente causa qualquer tipo de requisito de URL (a menos que você esteja trabalhando com uma estrutura incorreta). Meus URLs não possuem nenhuma sequência de consulta ?id=13, muito menos ?col1=val1&col2=val2&col3=val3.
7777 Nicole
2
@renesis: este site tem perguntas e usuários únicos, que estão nos URLs. Embora esse seja um caso especial, pois esses dados específicos não são alterados.
Michael K
1
@ Renesis, a maioria dos bancos de dados modernos (talvez todos) modernos possui tipos de colunas inteiras auto_increment que podem gerar os IDs de maneira automática e segura, e relatá-los via consulta sql ou chamada de função de biblioteca. Ou em um ambiente distribuído, você usa um grande hash aleatório. Alguns bancos de dados até criarão uma coluna de identificação oculta para você, se você ainda não tiver uma na tabela.
GrandmasterB
@ Michael - eu não disse que os IDs nunca estão nos URLs. Claro que eles são. Se você possui URLs que representam uma linha de dados, é provável que esses dados tenham um ID exclusivo. A menos que alguma outra parte da URL já forneça as outras partes da chave múltipla. @GrandmasterB Nenhuma das duas últimas empresas em que trabalhei (mais de 6 anos), que usam o MySQL (uma também suportou Oracle e SQL Server) foram capazes de usar o incremento automático, nem um grande hash aleatório.
7777 Nicole
8

Basicamente, você está perguntando se deve usar chaves substitutas ou naturais (no seu caso, parece chaves naturais compostas ). Aqui está um ótimo artigo: http://www.agiledata.org/essays/keys.html

Prefiro chaves substitutas porque simplificam a administração ao longo da vida do DB (você nunca precisa se preocupar com a implicação da mudança de significado das chaves, o que nunca deve acontecer, mas ocorre em qualquer sistema real em que os humanos estejam envolvidos). Contudo , se houver muitas tabelas de "pesquisa" no banco de dados (ou seja, tabelas que são basicamente pares chave: valor), as chaves substitutas poderão ficar complicadas porque você precisará associar essas tabelas à consulta para obter resultados significativos.

Por exemplo, digamos que você tenha duas entidades: Endereço e País.

  • O relacionamento é: Endereço * ----- 1 País
  • A entidade País é basicamente uma chave: par de valores (por exemplo, EUA: Estados Unidos, CA: Canadá, MX: México, etc ...)
  • Para consultar esta estrutura para todos os endereços nos EUA:

select * from Address where CountryCode = 'US'

  • Para executar a mesma consulta com chaves substitutas:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

Fico confortável em exigir chaves naturais para tabelas de consulta e chaves substitutas para todo o resto, se tiver certeza de que as chaves naturais não serão alteradas com muita frequência, se é que alguma vez.

Curtis Batt
fonte
5

Depende de como você acessa os dados. Se você fizer muitas pesquisas de chave parcial (onde você seleciona registros com base em, digamos, apenas duas das três chaves), manterá as chaves com várias partes. OTOH, se você tem muitos relacionamentos 1: 1 com outras tabelas, provavelmente faz mais sentido ter uma chave substituta.

TMN
fonte
1

Eu gosto de ter sempre uma chave primária substituta para cada tabela. Mas não há muitas razões "difíceis" para reforçar isso que ouvi.

A única vez em que eu tive uma chave natural de várias colunas foi na ORM. Ocasionalmente, eu teria problemas com uma chave primária de várias colunas usando o Linq To Entities.

Mike M.
fonte
1

Nunca diga nunca, mas juntar-se a 4 colunas é uma dor. Quanto mais colunas você tiver com dados inteligentes, maior a chance desses valores mudarem. Os bancos de dados podem ser configurados para manter a integridade referencial com atualizações em cascata.

Você sempre pode criar outro índice para manipular os valores exclusivos.

O desempenho é provavelmente insignificante na maioria dos casos, mas você pode testar suas consultas com e sem a chave de substituição.

JeffO
fonte
0

Acho difícil encontrar uma boa razão para exigir uma chave separada, mas, como você disse, muitas pessoas a colocam.

Não acho isso útil (especialmente com armazenamento) ao lidar com tabelas de fatos / detalhes. Exemplo canônico: uma tabela de fatos de vendas com uma (chave do cliente, chave da loja, chave do produto) com quantidade não faz muito sentido ter uma chave em nível de registro.

Jé Queue
fonte
0

Ter o PK como um incremento automático int reduz o aborrecimento se você achar que sua chave composta pode, na realidade, ter duplicatas.

Paul Nathan
fonte
0

Há uma boa discussão desde 2002 em Ask Tom . É específico da Oracle, mas a discussão mais ampla é relevante, independentemente do banco de dados que você estiver usando.

Rhys Gibson
fonte