As chaves estrangeiras são parte integrante da criação de um relacionamento em bancos de dados relacionais. Aqui está o porquê e como criá-los.
Portanto, estabelecemos que uma chave primária fornece um identificador exclusivo para a tabela. Mas as chaves primárias não são o único tipo de "chave". Nosso banco de dados também pode conter chaves estrangeiras.
O que é uma chave estrangeira?
Uma chave estrangeira é uma coluna (ou coleção de colunas) em uma tabela que identifica exclusivamente uma linha de outra tabela. Isso define um relacionamento entre as duas tabelas.
Uma chave estrangeira permite que você faça referência cruzada de dados relacionados entre tabelas. Isso é útil quando uma coluna contém dados representados em outra tabela.
Exemplo
Aqui está um diagrama da nossa FruitShop banco de dados mostrando a relação entre o Fruit tabela e as Unidades tabela.
A linha preta que liga as duas tabelas indica uma chave estrangeira. O UnitId campo no campo Frutas table é uma chave estrangeira para o UnitId campo em Unidades tabela. Portanto, o valor que inserimos em Fruit.UnitId deve corresponder a um valor em Units.UnitId . Isso habilita o Fruit.UnitId para referenciar os dados nas outras colunas desse registro (ou seja, o registro que tem o UnitId correspondente ).
Os dados
Portanto, se nossa Fruta table contém um registro como este:
FruitId | FruitName | Inventário | UnitId | DataInserida | Data de atualização |
---|---|---|---|---|---|
1 | Maçã | 10 | 3 | 27/11/2012 12:42:10 | 27/11/2012 12:42:10 |
E nossas Unidades tabela contém os seguintes registros:
UnitId | Nome da Unidade | DataInserida | Data de atualização |
---|---|---|---|
1 | Peça | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
2 | Grupo | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
3 | Quilograma | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
4 | Contêiner | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
5 | Libra | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
6 | Onça | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
Você pode ver que o Fruit.UnitId campo contém um
3
. Agora veja as
Unidades
tabela para o registro que contém um 3
no
UnitId
campo. Você pode ver que este registro representa
Quilograma
. Portanto, agora sabemos que as maçãs são medidas em quilogramas. O bom de configurar o banco de dados dessa maneira é que não precisamos repetir "Quilogramas" para cada registro que usa essa unidade. Reduzir a duplicação é um dos principais benefícios dos sistemas de gerenciamento de banco de dados relacional.
Vendo tantos registros no Fruit table compartilhará o mesmo nome de unidade (por exemplo, "Kilograms", "Container", "Bunch", etc), devemos pensar cuidadosamente antes de adicionar duplicatas ao nosso banco de dados. Sem usar um relacionamento de chave estrangeira, poderíamos simplesmente escrever os nomes das unidades diretamente no Fruit tabela (e talvez chamar a coluna "Unit", "UnitType" ou "UnitName"). Então, teríamos muitos registros compartilhando o mesmo valor para a coluna de nome da unidade. Veríamos "Kilogram" repetido várias vezes contra muitos recordes. Também veríamos "Banco" repetido e qualquer outro tipo de unidade popular.
Embora não seja necessariamente "errado" fazer isso, geralmente é mais eficiente armazenar um registro para cada um desses nomes de unidade em uma tabela separada e fazer referência a essa tabela por meio do UnitId coluna. Fazer isso é mais eficiente do que repetir esses nomes de unidade repetidamente para cada registro criado no arquivo Fruits tabela. Também torna mais fácil se decidirmos atualizar o nome de uma unidade (altere "Quilogramas" para "Quilos", por exemplo). Se atualizarmos o nome de uma unidade, isso não afetará a Fruit tabela porque o UnitId permanecerá o mesmo. Além disso, também ajuda a evitar que dados inconsistentes apareçam em nosso banco de dados.
Restrição de chave estrangeira
Uma restrição de chave estrangeira é um objeto de banco de dados que ajuda a manter seus dados de chave estrangeira consistentes. Você cria uma restrição de chave estrangeira para manter a integridade referencial. Ao criar uma restrição de chave estrangeira, você está dizendo ao MySQL para impor certas regras sobre os dados. Quando os dados são inseridos, excluídos ou atualizados, o MySQL verificará se ele adere à chave estrangeira que você criou entre as tabelas. Caso contrário, impedirá que os dados sejam gravados/sobrescritos/excluídos, mantendo assim a integridade referencial.
Por exemplo, se um usuário tentar inserir um valor UnitId em Fruit.UnitId mas não há registro correspondente em Units.UnitId coluna, o MySQL impedirá que o usuário insira esse valor.
Quando criamos nossas duas tabelas, adicionamos uma restrição de chave estrangeira ao Fruit tabela. Aqui está o código que usamos para criar a restrição:
CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE
Quando você expande os nós à esquerda SCHEMAS guia, você pode ver a chave estrangeira que criamos (assim como as chaves primárias):
Se você tentar inserir dados que não estejam em conformidade com a restrição de chave estrangeira, deverá receber um erro.
Por exemplo, se eu tentar inserir um registro no arquivo Fruit tabela usando um UnitId valor que não existe nas Unidades tabela, recebo o seguinte erro:
Isso ocorre porque estou tentando inserir um valor de
5
no
UnitId
coluna quando não há valor correspondente em
Units.UnitId
campo. Para que isso seja bem-sucedido, preciso garantir que haja um registro nas Unidades tabela com um UnitId de
5
. Chave estrangeira não funciona?
Você pode encontrar a situação ocasional em que uma chave estrangeira parece não funcionar. Por exemplo, você pode inserir dados com êxito em uma tabela, mesmo que haja uma chave estrangeira que deve impedir que esses dados sejam inseridos.
Há algumas coisas que você pode verificar nesta situação.
- Certifique-se de ter anexado
ON DELETE
eON UPDATE
cláusulas em seu código. Por exemplo,ON DELETE RESTRICT ON UPDATE CASCADE
. Veja nosso exemplo de CREATE TABLE para saber quando colocar este código. - Certifique-se de que a tabela seja InnoDB . Você pode fazer isso adicionando
ENGINE=InnoDB
ao final do seuCREATE TABLE
declaração (veja meu exemplo de quando criamos nossas tabelas). Alguns mecanismos (como MyISAM ) não oferecem suporte a restrições de chave estrangeira, mas não fornecem nenhum aviso sobre isso quando você tenta criar sua restrição de chave estrangeira. Se seu mecanismo padrão não for InnoDB então é provável que suas chaves estrangeiras não sejam suportadas. - Certifique-se de que o MySQL esteja realmente verificando as chaves estrangeiras. Você pode fazer isso executando o seguinte código:
SET FOREIGN_KEY_CHECKS=1
.
Desativar verificação de chave estrangeira
Pode haver momentos em que as restrições de chave estrangeira podem se tornar desnecessariamente restritivas - a ponto de prejudicar gravemente seus esforços no carregamento de dados. Por exemplo, quando você acaba de criar um banco de dados e precisa carregar os dados iniciais. Ou se você precisar descartar um monte de tabelas e recarregar os dados.
Se você não carregar os dados na ordem correta, provavelmente continuará recebendo erros de chave estrangeira devido aos dados serem carregados na ordem errada (ou seja, você está tentando carregar as tabelas filhas antes que as tabelas pai tenham seus dados carregados).
Este não é apenas um problema ao carregar os dados. Você também pode encontrar esse problema ao criar o banco de dados em primeiro lugar. Se você não criar as tabelas na ordem correta, poderá encontrar erros devido a restrições de chave estrangeira.
Se você não souber a ordem pai-filho correta, pode levar muito tempo e esforço para estabelecer a ordem correta para criar o banco de dados ou carregar os dados. Em casos como esses, talvez seja melhor dizer ao MySQL temporariamente para não verificar chaves estrangeiras por enquanto.
Você pode desabilitar a verificação de chave estrangeira com o seguinte código:
FOREIGN_KEY_CHECKS=0
Para habilitá-lo novamente, faça o seguinte:
FOREIGN_KEY_CHECKS=1