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

Problema do MySQL e do FK


A(s) coluna(s) de chave estrangeira deve(m) referenciar a(s) coluna(s) que compreendem um prefixo mais à esquerda da chave primária ou uma chave exclusiva na tabela pai.

Em outras palavras, os exemplos a seguir funcionam no InnoDB:
CREATE TABLE Foo ( a INT, b INT, c INT, PRIMARY KEY (a,b,c) );
CREATE TABLE Bar ( x INT, y INT );

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(b,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,b); -- RIGHT

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(b); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(a); -- RIGHT

Você recebeu um erro porque está tentando fazer o equivalente a (x) referências Foo(b).
Sua coluna codmenuitem é a segunda de três colunas na chave primária do pai.

Funcionaria se smenuitememp.codemenuitem deveriam referenciar smenuitem.codmodulo , porque essa coluna é a coluna mais à esquerda na chave primária da tabela pai.

Re sua pergunta de acompanhamento:

Lembre-se de como as chaves estrangeiras funcionam. Toda vez que você insere ou atualiza uma linha na tabela filha, ela precisa procurar uma linha na tabela pai para verificar se o valor existe na coluna referenciada. Se a coluna não estiver indexada, ela terá que fazer uma varredura de tabela para obter essa pesquisa, e isso seria muito caro, supondo que sua tabela pai cresça.

Se você tentar pesquisar uma linha com base na coluna do meio de um índice de várias colunas, o índice não o ajudará. Por analogia, é como procurar em uma lista telefônica todas as pessoas com um determinado nome do meio.

O SQL ANSI padrão requer que a coluna referenciada seja parte de uma CHAVE PRIMÁRIA ou CHAVE ÚNICA, e requer que as colunas de chave estrangeira correspondam a todas as colunas de uma restrição primária ou exclusiva no pai.

Mas o InnoDB é mais permissivo. Ele ainda requer que a coluna referenciada na tabela pai seja indexada para que a pesquisa possa ser eficiente, e que as colunas referenciadas sejam as mais à esquerda no índice. Mas um índice não exclusivo é bom; é permitido que uma chave estrangeira faça referência a ela.

Isso pode levar a casos estranhos, como uma linha filho que faz referência a mais de uma linha no pai, mas espera-se que você lide com essas anomalias.

Sinto a necessidade de enfatizar o último ponto. Você vai obter dados anômalos se você definir chaves estrangeiras para colunas não indexadas exclusivamente no pai. Isso provavelmente fará com que suas consultas relatem linhas várias vezes quando você fizer junções. Você não deve usar este comportamento do InnoDB; você deve definir chaves estrangeiras apenas para colunas pai que são exclusivas.