Às vezes, ao executar uma migração do Laravel, você obtém o erro: errno 150 "errno 150 "Foreign key constraint is incorrectly formed"
que siginifica: “A restrição de chave estrangeira está formada incorretamente”. Este erro é causado principalmente porque sua coluna de chave estrangeira é declarada usando um tipo de dados diferente da coluna de chave relacionada na tabela de origem.
Principal causa para o erro errno 150: Foreign key constraint is incorrectly formed
A causa mais comum do erro é que a coluna de chave estrangeira é criada com o tipo errado, relacionado à coluna primária referenciada.
Já que increments()
cria uma coluna do tipo integer sem sinal (unsigned), você precisa definir a coluna de chave estrangeira como inteiro unsigned
também.
As migrações padrão no Laravel 6+ usam bigIncrements()
, então você precisa usar o método unsignedBigInteger()
:
$table->unsignedBigInteger('order_id');
Para migrações padrão em versões mais antigas do Laravel, use o método unsignedInteger()
:
$table->unsignedInteger('order_id');
Ou:
$table->integer('order_id')->unsigned();
Veja um exemplo de migração com erro:
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->timestamps();
$table->softDeletes();
});
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->integer('book_id');
$table->timestamps();
$table->softDeletes();
$table->foreign('book_id')->references('id')->on('books');
});
}
Então, para resolver um erro como:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table orders.#sql-b5b_b2a (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table orders add constraint orders_book_id_foreign foreign key (book_id) references books (id))
[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table books.#sql-b5b_b2a (errno: 150 "Foreign key constraint is incorrectly formed")
Você deve alterar a linha que cria a coluna book_id
:
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->timestamps();
$table->softDeletes();
});
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('book_id'); // altere esta linha
$table->timestamps();
$table->softDeletes();
$table->foreign('book_id')->references('id')->on('books');
});
}
Outras causas para o erro Foreign key constraint is incorrectly formed
Nome da tabela referenciada errado
Um dos pecados mais comuns de desenvolvedores, errar o nome de variáveis, tabelas, campos, etc. Então sim, um simples e inocente erro destes pode trazer a mensagem de erro: “errno 150 Foreign key constraint is incorrectly formed on Laravel Migration”. Basta corrigir a tabela na instrução de criação da chave estrangeira:
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
...
});
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('book_id');
$table->foreign('book_id')->references('id')->on('book'); // corrija o nome para books
});
}
Ordem dos arquivos Migration
Às vezes, o motivo desse erro é devido à ordem em que os arquivos de migração são listados ou erro devido à conversão de tipo.
Certifique-se sempre de que a migração do arquivo ao qual as restrições de chaves estrangeiras serão criadas ocorra após a migration principal. E também certifique-se de que é um unsignedBigInteger
, embora a versão anterior do laravel (<5.4) possa ignorar esse erro de conversão de tipo.
Portanto, os arquivos de migração devem ser criados de forma que a migração pai venha primeiro e o arquivo de migração com a chave estrangeira em seguida.
Além disso, a chave estrangeira e o id primário na outra tabela devem ter propriedades exatamente semelhantes. Se o id primário for incrementado, faça a chave estrangeira integer('xxx_id')->unsigned()
;
MySQL MyISAM
Verifique o motor (engine) da sua tabela MySQL. Em alguns casos, você pode estar referenciando uma tabela MyISAM em uma tabela de origem InnoDB. Depois de alterar o mecanismo da tabela de referência para InnoDB, ele deve funcionar!
Isso pode ser causado quando as tabelas criadas antes da migração onde MyISAM de um sistema legado e as migradas são innoDB por padrão, então a mistura de tipos de tabela será um problema no meu caso.
Conclusões
Preste atenção ao criar chaves estrangeiras no Laravel Migration para criar as colunas estrangeiras com o mesmo tipo de dados das colunas originais, criando também os arquivos de migração na ordem correta.
Comentários