Estou tentando criar uma tabela no MySQL com duas chaves estrangeiras, que fazem referência às chaves primárias em 2 outras tabelas, mas estou recebendo um errno: erro 150 e não criará a tabela.
Aqui está o SQL para todas as 3 tabelas:
CREATE TABLE role_groups (
`role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
`name` varchar(20),
`description` varchar(200),
PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50),
`description` varchar(200),
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;
create table role_map (
`role_map_id` int not null `auto_increment`,
`role_id` int not null,
`role_group_id` int not null,
primary key(`role_map_id`),
foreign key(`role_id`) references roles(`role_id`),
foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Qualquer ajuda seria muito apreciada.
mysql
foreign-keys
mysql-error-150
Bill Karwin
fonte
fonte
auto_increment
? Isso não é válido. Auto_increment é uma palavra-chave, não um identificador.Respostas:
Eu tive o mesmo problema com
ALTER TABLE ADD FOREIGN KEY
.Depois de uma hora, descobri que essas condições devem ser satisfeitas para não ocorrer 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 certa: Tabela pai primeiro, depois a tabela filho. Se as duas tabelas fizerem referência uma à outra, você deverá criar uma tabela sem restrições FK, depois criar a segunda tabela e adicionar a restrição FK à primeira tabela com
ALTER TABLE
.As duas tabelas têm de suportar restrições de chave estrangeira, ie
ENGINE=InnoDB
. Outros mecanismos de armazenamento ignoram silenciosamente as definições de chave estrangeira, portanto, eles 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 Parent for
PRIMARY 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 FK
REFERENCES Parent(a,b,c)
, o PK do pai não deve ser definido nas colunas em ordem(a,c,b)
.A (s) coluna (s) PK na tabela pai devem ter o mesmo tipo de dados que a (s) coluna (s) FK na tabela filho. Por exemplo, se uma coluna PK na tabela pai for
UNSIGNED
, 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 fazer referênciaVARCHAR(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:
Deve retornar zero (0) valores não correspondidos. 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 ser uma
TEMPORARY
tabela.Nem a tabela pai nem a tabela filho podem ser uma
PARTITIONED
tabela.Se você declarar um FK com a
ON DELETE SET NULL
opção, a (s) coluna (s) FK devem ser anuláveis.Se você declarar um nome de restrição para uma chave estrangeira, o nome da restrição deve ser único em todo o esquema, não apenas na tabela em que a restrição é definida. Duas tabelas não podem ter sua própria restrição com o mesmo nome.
Se houver qualquer outro FK em outras tabelas apontando para o mesmo campo para o qual você está tentando criar o novo FK, e eles estiverem malformados (isto é, agrupamento diferente), eles precisarão ser consistentes primeiro. Isso pode ser resultado de alterações anteriores em que
SET FOREIGN_KEY_CHECKS = 0;
foi utilizado com um relacionamento inconsistente definido por engano. Consulte a resposta de @andrewdotn abaixo para obter instruções sobre como identificar esses FKs problemáticos.Espero que isto ajude.
fonte
int(11) unsigned NOT NULL
vsint(11) NOT NULL
.ON DELETE
regra CONSTRAINT for,SET NULL
certifique-se de que a chave estrangeira pode ser NULL! Passei 30 minutos lendo essa resposta sem parar, certificando-me de que minhas tabelas atendiam às condições, mas ainda obtinha o Erro 150. Então, percebi que meu FK era um campo NOT NULL, o que significa que a regra era impossível de ser aplicada.A mensagem genérica “errno 150” do MySQL “ significa que uma restrição de chave estrangeira não foi formada corretamente .” Como você provavelmente já sabe se está lendo esta página, a mensagem de erro genérica “errno: 150” é realmente inútil. Contudo:
Você pode obter a mensagem de erro real executando
SHOW ENGINE INNODB STATUS;
e, em seguida, procurandoLATEST FOREIGN KEY ERROR
na saída.Por exemplo, esta tentativa de criar uma restrição de chave estrangeira:
falha com o erro
Can't create table 'test.t2' (errno: 150)
. Isso não diz a ninguém nada útil além de que é um problema de chave estrangeira. Mas corraSHOW ENGINE INNODB STATUS;
e ele dirá:Diz que o problema é que não consegue encontrar um índice.
SHOW INDEX FROM t1
mostra que não há nenhum índice para a tabelat1
. Corrija isso, digamos, definindo uma chave primária emt1
, e a restrição de chave estrangeira será criada com sucesso.fonte
SHOW ENGINE INNODB STATUS
ajudou-me a identificar imediatamente um problema que venho tentando diagnosticar há quase uma hora. Obrigado.SET FOREIGN_KEY_CHECKS = 0;
durante uma importação / alteração malformada em um momento ou outro. Grande ajuda, obrigado.Certifique-se de que as propriedades dos dois campos que você está tentando vincular a uma restrição sejam exatamente as mesmas.
Freqüentemente, a propriedade 'unsigned' em uma coluna de ID irá pegá-lo.
fonte
Qual é o estado atual do seu banco de dados quando você executa este script? Está completamente vazio? Seu SQL funciona bem para mim ao criar um banco de dados do zero, mas errno 150 geralmente tem a ver com descartar e recriar tabelas que são parte de uma chave estrangeira. Estou tendo a sensação de que você não está trabalhando com um banco de dados 100% novo e novo.
Se você está errando ao fazer o "código-fonte" em seu arquivo SQL, você deve ser capaz de executar o comando "SHOW ENGINE INNODB STATUS" no prompt do MySQL imediatamente após o comando "fonte" para ver informações mais detalhadas sobre o erro.
Você pode querer verificar a entrada manual também:
fonte
Para pessoas que estão vendo este tópico com o mesmo problema:
Existem muitos motivos para erros como esse. Para uma lista bastante completa de causas e soluções de erros de chave estrangeira no MySQL (incluindo aqueles discutidos aqui), verifique este link:
Erros de chave estrangeira MySQL e Errno 150
fonte
Para outros que encontrarem esta entrada do SO através do Google: Certifique-se de que você não está tentando fazer uma ação SET NULL em uma coluna de chave estrangeira (a ser) definida como "NOT NULL". Isso causou grande frustração até que me lembrei de fazer um CHECK ENGINE INNODB STATUS.
fonte
Definitivamente não é o caso, mas achei esse erro muito comum e pouco óbvio. O alvo de um
FOREIGN KEY
não poderia serPRIMARY KEY
. A resposta que se tornou útil para mim é:Uma FOREIGN KEY sempre deve ser apontada para um campo true PRIMARY KEY de outra tabela.
fonte
Como apontado por @andrewdotn, a melhor maneira é ver o erro detalhado (
SHOW ENGINE INNODB STATUS;
) em vez de apenas um código de erro.Um dos motivos pode ser que já exista um índice com o mesmo nome, pode estar em outra tabela. Como prática, recomendo prefixar o nome da tabela antes do nome do índice para evitar tais conflitos. por exemplo, em vez de
idx_userId
usaridx_userActionMapping_userId
.fonte
Por favor, certifique-se primeiro de que
Tive o mesmo problema e resolvi. Eu tinha INT não assinado para um campo e apenas inteiro para outro campo.
fonte
Dica útil, use
SHOW WARNINGS;
após tentar suaCREATE
consulta e você receberá o erro, bem como o aviso mais detalhado:Portanto, neste caso, é hora de recriar minha mesa!
fonte
Isso geralmente acontece quando você tenta originar o arquivo em um banco de dados existente. Elimine todas as tabelas primeiro (ou o próprio banco de dados). E então o arquivo de origem com
SET foreign_key_checks = 0;
no início eSET foreign_key_checks = 1;
no final.fonte
Encontrei outro motivo para a falha ... nomes de tabelas com distinção entre maiúsculas e minúsculas.
Para esta definição de tabela
Esta definição de tabela funciona
enquanto este falha
O fato de que funcionou no Windows e falhou no Unix me levou algumas horas para descobrir. Espero que ajude outra pessoa.
fonte
MySQL Workbench 6.3 para Mac OS.
Problema: errno 150 na tabela X ao tentar fazer Forward Engineering em um diagrama DB, 20 de 21 tiveram sucesso, 1 falhou. Se FKs na tabela X foram excluídos, o erro foi movido para uma tabela diferente que não estava falhando antes.
Todos os mecanismos de tabelas foram alterados para myISAM e funcionou perfeitamente.
fonte
Também vale a pena verificar se você não está operando acidentalmente no banco de dados errado. Este erro ocorrerá se a tabela externa não existir. Por que o MySQL precisa ser tão enigmático?
fonte
Certifique-se de que as chaves estrangeiras não estejam listadas como exclusivas no pai. Eu tive esse mesmo problema e resolvi demarcando-o como não único.
fonte
No meu caso, foi devido ao fato de que o campo que era um campo de chave estrangeira tinha um nome muito longo, ou seja.
foreign key (some_other_table_with_long_name_id)
. Tente mais curto. A mensagem de erro é um pouco enganosa nesse caso.Além disso, como @Jon mencionou anteriormente - as definições de campo devem ser as mesmas (cuidado com o
unsigned
subtipo).fonte
(Notas laterais muito grandes para um comentário)
Não há necessidade de um
AUTO_INCREMENT
id em uma tabela de mapeamento; livre-se disso.Altere o
PRIMARY KEY
para(role_id, role_group_id)
(em qualquer ordem). Isso tornará os acessos mais rápidos.Como você provavelmente deseja mapear as duas direções, adicione também um
INDEX
com essas duas colunas na ordem oposta. (Não há necessidade de fazer issoUNIQUE
.)Mais dicas: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
fonte
Quando a restrição de chave estrangeira é baseado no
varchar
tipo, em seguida, para além da lista fornecida pelamarv-el
a coluna de destino deve ter uma restrição exclusiva.fonte
execute a linha abaixo antes de criar a tabela: SET FOREIGN_KEY_CHECKS = 0;
A opção FOREIGN_KEY_CHECKS especifica se deve ou não verificar as restrições de chave estrangeira para tabelas InnoDB.
- Especifique para verificar as restrições de chave estrangeira (este é o padrão)
- Não verifique as restrições de chave estrangeira
SET FOREIGN_KEY_CHECKS = 0;
Quando usar: Desativar temporariamente as restrições referenciais (defina FOREIGN_KEY_CHECKS como 0) é útil quando você precisa recriar as tabelas e carregar dados em qualquer ordem pai-filho
fonte
Eu encontrei o mesmo problema, mas descobri que não tinha a tabela pai. Então, eu apenas edito a migração pai antes da migração filho. Apenas faça.
fonte