Como criar corretamente chaves primárias compostas - MYSQL


182

Aqui está uma simplificação grosseira de uma configuração intensa com a qual estou trabalhando. table_1e table_2ambos têm incremento automático de chaves primárias substitutas como o ID. infoé uma tabela que contém informações sobre ambos table_1e table_2.

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

Estou tentando decidir se devo criar a chave primária de infoum composto dos IDs de table_1e table_2. Se eu fizesse isso, qual deles faz mais sentido?
(neste exemplo, estou combinando o ID 11209 com o ID 437)

INT(9)11209437 (eu posso imaginar por que isso é ruim)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

Ou alguma outra coisa?

Seria bom usar isso como a chave primária em um banco de dados MYSQL MYISAM?


Respostas:


343

Eu usaria uma chave composta (multi-coluna).

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

Dessa forma, você pode ter t1ID e t2ID como chaves estrangeiras apontando para suas respectivas tabelas.


2
Oh uau, é assim que você faz uma chave composta! parece que eu tenho entendido totalmente o conceito. Obrigado!! Então, algo assim é inteiramente para fins de indexação e correto? Como eu não seria capaz de fazer referência a um registro usando esse composto, ainda precisaria fazer um UPDATE info ... WHERE t1ID=11209 AND t2ID=437?
filip

2
corrigir. Embora as duas colunas devam ser exclusivas, provavelmente t1ID = 11209 seria suficiente.
precisa saber é o seguinte

39
@AlexCuse a combinação de ambas as colunas é única, mas para t1ID = 11209 pode haver qualquer número de t2IDs.
e18r

21

Eu não tornaria a chave primária da tabela "info" uma composição dos dois valores de outras tabelas.

Outros podem articular melhor os motivos, mas parece errado ter uma coluna que é realmente composta de duas informações. E se você quiser classificar o ID da segunda tabela por algum motivo? E se você quiser contar o número de vezes que um valor de qualquer tabela está presente?

Eu sempre os manteria como duas colunas distintas. Você pode usar uma chave primária de duas colunas no mysql ... PRIMARY KEY (id_a, id_b) ... mas eu prefiro usar um índice exclusivo de duas colunas e ter um campo de chave primária de incremento automático.


1
Você está absolutamente certo em manter colunas distintas. Eu não sabia que você poderia ter um índice exclusivo de duas colunas e acho que pode ser realmente uma boa opção para mim. Posso perguntar por que você ainda prefere manter a Chave Primária como incremento automático?
Filip 29/04

3
Não tenho razões realmente convincentes e admito que esse é um ponto de discórdia entre mim e alguns de meus colegas, porque é mais econômico ter menos colunas. Acho mais fácil escrever junções em uma única chave estrangeira. Às vezes, o significado dessas tabelas "Mapeamentos entre duas tabelas" se torna tão importante quanto as tabelas originais e sua chave primária se torna uma coluna de chave estrangeira em outras tabelas.
wmorse

obrigado. Eu acho que o que você diz faz muito sentido e vou tentar como um índice exclusivo de duas colunas + chave primária de incremento automático
filip

1
Acho que um dos motivos da minha cabeça é que você deseja criar uma tabela de relacionamento. você tem três tabelas, por exemplo, mercado, moeda e provedor, um provedor SOMENTE pode existir em um mercado UMA VEZ; portanto, sua tabela de relacionamento pode fornecer apenas uma moeda; essa conexão uma vez, tentando adicionar novamente o mesmo mercado e provedor falhará, o que significa que eles são únicos; então você teria uma segunda coluna, digamos id_currency, o que significa que a moeda é singular em toda a tabela, isso faz sentido?
Christopher Thomas

1
Para quem vê esse segmento posteriormente, observe que o motivo é uma prática inadequada porque viola um princípio muito básico do design do banco de dados. O 1º Formulário Normal exige que cada informação tenha sua própria coluna. Não há praticamente nenhuma razão para violar isso e vários benefícios para normalizar sua estrutura de banco de dados.
smcjones

15

a sintaxe é CONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)por exemplo:

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

o exemplo acima funcionará se você estiver gravando enquanto estiver criando a tabela, por exemplo:

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

Para adicionar essa restrição a uma tabela existente, é necessário seguir a seguinte sintaxe

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)

8

Suponha que você já tenha criado uma tabela agora, você pode usar esta consulta para criar chave primária composta

alter table employee add primary key(emp_id,emp_name);

5

Além das preferências pessoais de design, há casos em que se deseja fazer uso de chaves primárias compostas. As tabelas podem ter dois ou mais campos que fornecem uma combinação exclusiva e não necessariamente por meio de chaves estrangeiras.

Como exemplo, cada estado dos EUA tem um conjunto de distritos congressionais exclusivos. Embora muitos estados possam ter um CD-5 individualmente, nunca haverá mais de um CD-5 em nenhum dos 50 estados e vice-versa. Portanto, a criação de um campo de numeração automática para o Massachusetts CD-5 seria redundante.

Se o banco de dados gerar uma página da web dinâmica, escrever código para consulta em uma combinação de dois campos pode ser muito mais simples do que extrair / reenviar uma chave com número automático.

Portanto, embora não responda à pergunta original, certamente aprecio a resposta direta de Adam.


4

Chaves primárias compostas são o que você deseja, onde deseja criar um relacionamento muitos para muitos com uma tabela de fatos. Por exemplo, você pode ter um pacote de aluguel de férias que inclui várias propriedades nele. Por outro lado, a propriedade também pode estar disponível como parte de vários pacotes de aluguel, por conta própria ou com outras propriedades. Nesse cenário, você estabelece o relacionamento entre a propriedade e o pacote de aluguel com uma tabela de fatos de propriedade / pacote. A associação entre uma propriedade e um pacote será única; você somente ingressará no usando property_id com a tabela de propriedades e / ou package_id com a tabela de pacotes. Cada relacionamento é único e uma chave de incremento automático é redundante, pois não será exibida em nenhuma outra tabela. Portanto, definir a chave composta é a resposta.


1
CREATE  TABLE `mom`.`sec_subsection` (

  `idsec_sub` INT(11) NOT NULL ,

  `idSubSections` INT(11) NOT NULL ,

  PRIMARY KEY (`idsec_sub`, `idSubSections`) 

);

1

@AlexCuse Eu queria adicionar isso como comentário à sua resposta, mas desisti depois de fazer várias tentativas fracassadas de adicionar novas linhas nos comentários.

Dito isso, t1ID é único na tabela_1, mas isso não o torna exclusivo também na tabela INFO.

Por exemplo:

A tabela_1 possui:
Campo ID
1 A
2 B

A Tabela_2 possui:
Campo ID
1 X
2 Y

INFO pode ter:
t1ID campo t2ID
1 1 alguns
1 2 dados
2 1 em cada
2 2 linhas

Portanto, na tabela INFO para identificar exclusivamente uma linha, você precisa de t1ID e t2ID


a sua chamada chave composta
Pavel P

1
@PavelP, minha resposta está escrita no comentário de Alex "Embora, já que as duas colunas devam ser únicas, onde t1ID = 11209 provavelmente seja suficiente." ... Concordo que o uso da chave composta está correto, mas para identificar a correspondência exata, você precisará de t1ID e t2ID ... Espero que esteja claro agora.
sactiw
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.