Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como usar chaves estrangeiras com PHP

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.