Eu tive o mesmo problema com
ALTER TABLE ADD FOREIGN KEY
. Após uma hora, descobri que essas condições devem ser atendidas para não obter o erro 150:
-
A tabela Pai deve existir antes de você definir uma chave estrangeira para referenciá-la. Você deve definir as tabelas na ordem correta:primeiro a tabela pai, depois a tabela filho. Se ambas as tabelas fizerem referência uma à outra, você deve criar uma tabela sem restrições FK, criar a segunda tabela e adicionar a restrição FK à primeira tabela comALTER TABLE
.
-
As duas tabelas devem suportar restrições de chave estrangeira, ou seja,ENGINE=InnoDB
. Outros mecanismos de armazenamento ignoram silenciosamente as definições de chave estrangeira, portanto, não retornam nenhum erro ou aviso, mas a restrição FK não é salva.
-
As colunas referenciadas na tabela Pai devem ser as colunas mais à esquerda de uma chave. Melhor se a chave no Pai forPRIMARY KEY
ouUNIQUE KEY
.
-
A definição FK deve fazer referência à(s) coluna(s) PK na mesma ordem que a definição PK. Por exemplo, se o FKREFERENCES Parent(a,b,c)
então o PK do pai não deve ser definido nas colunas na ordem(a,c,b)
.
-
As colunas PK na tabela Pai devem ser do mesmo tipo de dados que as colunas FK na tabela Filho. Por exemplo, se uma coluna PK na tabela Pai forUNSIGNED
, certifique-se de definirUNSIGNED
para a coluna correspondente no campo Tabela filho.
Exceção:o comprimento das strings pode ser diferente. Por exemplo,VARCHAR(10)
pode referenciarVARCHAR(20)
ou vice-versa.
-
Qualquer coluna FK do tipo string deve ter o mesmo conjunto de caracteres e agrupamento que a(s) coluna(s) PK correspondente(s).
-
Se já houver dados na tabela filho, cada valor na(s) coluna(s) FK deve corresponder a um valor na(s) coluna(s) PK da tabela pai. Verifique isso com uma consulta como:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK WHERE Parent.PK IS NULL;
Isso deve retornar zero (0) valores não correspondentes. Obviamente, esta consulta é um exemplo genérico; você deve substituir seus nomes de tabela e nomes de coluna.
-
Nem a tabela Pai nem a tabela Filho podem serTEMPORARY
tabela.
-
Nem a tabela Pai nem a tabela Filho podem serPARTITIONED
tabela.
-
Se você declarar um FK com oON DELETE SET NULL
opção, as colunas FK devem ser anuláveis.
-
Se você declarar um nome de restrição para uma chave estrangeira, o nome da restrição deverá ser exclusivo em todo o esquema, não apenas na tabela na qual a restrição está definida. Duas tabelas não podem ter sua própria restrição com o mesmo nome.
-
Se houver outros FKs em outras tabelas apontando para o mesmo campo para o qual você está tentando criar o novo FK e eles estiverem malformados (ou seja, agrupamento diferente), eles precisarão ser consistentes primeiro. Isso pode ser resultado de alterações anteriores em queSET FOREIGN_KEY_CHECKS = 0;
foi utilizado com uma relação inconsistente definida por engano. Veja a resposta de @andrewdotn abaixo para obter instruções sobre como identificar esses FKs problemáticos.
Espero que isto ajude.