Desambiguação de colunas/restrições de chave estrangeira
Supondo que você esteja se referindo às restrições de chave estrangeira , a resposta curta seria você simplesmente não os usa .
E aí vem o longo:
Estamos acostumados a nos referir a colunas como chaves estrangeiras para outras tabelas. Especialmente durante o processo de normalização, frases como "
user_purchase.i_id
é uma chave estrangeira para os items
tabela" seria muito comum. Embora essa seja uma maneira perfeitamente válida de descrever o relacionamento, ela pode ficar um pouco confusa quando chegarmos à fase de implementação. Suponha que você tenha criado suas tabelas sem a
FOREIGN KEY
cláusulas:CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Observe que, em termos de relação, a chave estrangeira colunas estão ainda implementados . Há uma coluna que faz referência ao
user
tabela (id
) e outro que faz referência aos items
tabela (i_id
) -- vamos colocar o name
coluna de lado por um momento. Considere os seguintes dados: user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
A relação está aí. Ele é implementado por meio do
user_purchase
tabela, que contém informações sobre quem comprou o quê . Se fôssemos consultar o banco de dados para um relatório relevante, faríamos:select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
E é assim que usamos a relação e a chave estrangeira colunas envolvidos.
Agora, e se fizermos:
insert into user_purchase (id,i_id) values (23,99)
Aparentemente, esta é uma entrada inválida. Embora haja um usuário com
id=23
, não há item com i_id=99
. O RDBMS permitiria que isso acontecesse, porque não conhece nada melhor . Ainda. É aí que a chave estrangeira restrições entre no jogo. Especificando
FOREIGN KEY (i_id) REFERENCES items(i_id)
em user_purchase
definição de tabela, essencialmente damos ao RDBMS uma regra a seguir:entradas com i_id
valores que não estão contidos no items.i_id
coluna não são aceitáveis . Em outras palavras, enquanto uma chave estrangeira coluna implementa a referência , uma restrição de chave estrangeira impõe a integridade referencial . Observe, no entanto, que o
select
acima não mudaria, apenas porque você definiu uma restrição FK. Assim, você não use restrições FK, o RDBMS faz, para proteger seus dados. Redundâncias
Pergunte a si mesmo:Por que você quer isso? Se as duas chaves estrangeiras servirem ao mesmo propósito, a redundância acabará por causar problemas. Considere os seguintes dados:
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
O que está errado com esta imagem? O usuário
55
comprar duas barras de chocolate ou uma barra de chocolate e uma pasta de dentes? Esse tipo de ambiguidade pode levar a muito esforço para manter os dados sincronizados, o que seria desnecessário se apenas mantivéssemos uma das chaves estrangeiras. Na verdade, por que não descartar o name
coluna completamente, uma vez que está implícito pela relação. Claro, podemos resolver isso implementando uma chave estrangeira composta, definindo
PRIMARY KEY(i_id,name)
para os items
table (ou definindo um extra UNIQUE(i_id,name)
index, isso realmente não importa) e, em seguida, definindo um FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. Desta forma, somente casais (i_id,name) que existem nos items
tabela seria válida para user_purchases
. Além do fato de que você ainda teria um chave estrangeira , essa abordagem é totalmente desnecessária, desde que o i_id
coluna já é suficiente para identificar um item (não posso dizer o mesmo para o name
coluna...). No entanto, não há regra contra o uso de várias chaves estrangeiras em uma tabela. Na verdade, existem circunstâncias que exigem tal abordagem. Considere uma
person(id,name)
tabela e um parent(person,father,mother)
um, com os seguintes dados: person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Obviamente, todas as três colunas do
parent
table são chaves estrangeiras para person
. Não para a mesma relação , mas para três diferentes :Como os pais de uma pessoa também são pessoas, as duas colunas correspondentes devem fazer referência à mesma tabela person
faz. Observe, no entanto, que os três campos não apenas podem mas também tem que indique uma person
diferente s no mesmo parent
linha, já que ninguém é seu próprio pai e o pai de ninguém é sua mãe também.