Foreign keys error in migrations (Laravel 6.0) - php

I'm trying to figure out how migrations in Laravel work. Here you can see I'm creating 2 tables. And in the second table (RealNationalLeague), I'm having foreign keys to two columns (real_nation_id, level) in the first table (RealNationalLeagueLevel).
public function up()
{
...
Schema::create(Model\RealNationalLeagueLevel::TABLE, function (Blueprint $table) {
$table->unsignedInteger("real_nation_id");
$table->unsignedTinyInteger("level");
$table->foreign("real_nation_id")->references("id")->on(Model\RealNation::TABLE);
$table->primary(["real_nation_id", "level"]);
});
Schema::create(Model\RealNationalLeague::TABLE, function (Blueprint $table) {
$table->increments("id");
$table->unsignedInteger("real_nation_id");
$table->unsignedTinyInteger("level");
$table->string("name", 32);
$table->foreign("real_nation_id")->references("real_nation_id")->on(Model\RealNationalLeagueLevel::TABLE); // this works
$table->foreign("level")->references("level")->on(Model\RealNationalLeagueLevel::TABLE); // this does not
});
}
Running the migration does not work. It throws QueryException:
SQLSTATE[HY000]: General error: 1005 Can't create table `testdb`.`#sql-17a00_448a37` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table `real_national_league` add constraint `real_national_league_level_foreign` foreign key (`level`) references `real_national_league_level` (`level`))
Any idea why it's not working? Thanks for any help.

The table that you want to reference, you have to create it first, then in another migration, create a column from this table to that reference table.

Related

SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint laravel 9

Trying to assign foreign key but when you run migrate, I get this this error, I do not understand what the problem is.
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table categories add constraint categories_parent_key_foreign foreign key (parent_key) references categories (key) on delete cascade)
$table->bigIncrements('id');
$table->string('key', 64)->unique();
$table->string('parent_key', 64)->nullable()->index();
$table->string('title', 256)->index()->unique();
$table->foreign('parent_key')->references('key')
->on((new Category())->getConnection()->getDatabaseName() . '.' . Category::TABLE)
->onDelete('cascade');
I had the same problem.
The problem arises when a model has a relationship with itself (self-relation).
To solve this problem, first, the migration file must be created and then the foreign key must be assigned in another migration file.
You must remove the foreign key assignment from the migration file and create the new migration file after that, then add relations statements to assign a foreign key. (the order of the migration files is important).
create_category_table
public function up(): void
{
$table->bigIncrements('id');
$table->string('key', 64)->unique();
$table->string('parent_key', 64)->nullable()->index();
$table->string('title', 256)->index()->unique();
}
create_category_relation_table
public function up(): void
{
$table->foreign('parent_key')->references('key')
->on((new Category())->getConnection()->getDatabaseName() . '.' . Category::TABLE)
->onDelete('cascade');
}
And then php artisan migration
In my case the problem was in the different datatypes of the referenced table key and the key reference. For instance, integer(unsigned) vs bigInteger(unsigned).

Laravel - Dropping foreign key and adding in one migration

I am trying to drop the foreign key and add the foreign key in one migration but can't get it to work:
I have created the table contents with the foreign key cms_id:
public function up()
{
Schema::create('contents', function (Blueprint $table) {
$table->increments('id');
$table->integer('ct_id')->unsigned();
$table->foreign('ct_id')->references('id')->on('content_types');
$table->integer('cms_id')->unsigned();
$table->foreign('cms_id')->references('id')->on('inventories');
$table->string('title');
$table->string('slug');
$table->text('excerpt');
$table->mediumText('body');
$table->string('password');
$table->integer('parent_id');
$table->timestamps();
});
}
This is how the inventories table looks like:
Schema::create('inventories', function (Blueprint $table) {
$table->increments('id');
$table->integer('remote_id');
$table->integer('local_id')->unsigned();
$table->string('local_type');
$table->timestamps();
});
And after failing to drop it and to create a new foreign key, I have deleted all the tables in the DB, and have tried to run all the migrations again with the new one as well, which holds this:
public function up()
{
Schema::table('inventories', function (Blueprint $table) {
$table->integer('remote_id')->unsigned()->change();
});
Schema::table('contents', function (Blueprint $table) {
$table->dropForeign('contents_cms_id_foreign');
$table->foreign('cms_id')->references('remote_id')->on('inventories');
});
Schema::table('files', function (Blueprint $table) {
$table->dropForeign('files_cms_id_foreign');
$table->foreign('cms_id')->references('remote_id')->on('inventories');
});
}
But,I get:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
(SQL : alter table contents add constraint
contents_cms_id_foreign foreign k ey (cms_id) references
inventories (remote_id))
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
If, I first run all the migrations where I create all the tables, and then after that run the new migration where I change the foreign keys, I get this error:
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP
'content s_cms_id_foreign'; check that column/key exists (SQL:
alter table contents drop foreign key
contents_cms_id_foreign)
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP
'content s_cms_id_foreign'; check that column/key exists
I have even tried to just delete all the tables in the DB, and only edit the files that I already have by just changing, without new migrations:
$table->integer('ct_id')->unsigned();
$table->foreign('ct_id')->references('remote_id')->on('content_types');
$table->integer('cms_id')->unsigned();
$table->foreign('cms_id')->references('remote_id')->on('inventories');
And, also in the inventories table:
$table->integer('remote_id')->unsigned();
But, even then it won't work, and I get:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
(SQL : alter table contents add constraint
contents_cms_id_foreign foreign k ey (cms_id) references
inventories (remote_id))
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
So, I have checked all of the usual suspects that I have come across on the internet, I have even added $table->engine = 'InnoDB'; to to the tables inventories, contents and files, I have made sure to first create tables and then add foreign keys, as well as checked if the columns have the same data type, not sure what to do else?

Laravel 5.1 foreign key migration error

I get this weird error when executing my constraints migration
When I execute this migration I get
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'flowtime_dev.#sql-85bb_52' (errno: 121) (SQL: alter table `questions` add constraint questions_inventory_i
d_foreign foreign key (`inventory_id`) references `inventories` (`id`) on delete cascade)
[PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'flowtime_dev.#sql-85bb_52' (errno: 121)
I've read that the data types in different tables should match ( like int(10) to int(10)) and they do, this is also the last migration that I have ( all the tables exist and have been created by other migrations before).
I seriously have no idea what to do anymore :(. Could someone help?
I have seen similar posts, but they have not fixed the problem so far for me.
The migration is as follows:
public function up()
{
Schema::table('questions', function ($table) {
$table->integer('inventory_id')->unsigned()->change();
$table->foreign('inventory_id')
->references('id')->on('inventories')
->onDelete('cascade');
});
Schema::table('question_response', function ($table) {
$table->integer('question_id')->unsigned()->change();
$table->foreign('question_id')
->references('id')->on('questions')
->onDelete('cascade');
});
Schema::table('question_response', function ($table) {
$table->integer('sample_result_set_id')->unsigned()->change();
$table->foreign('sample_result_set_id')
->references('id')->on('sample_response_set')
->onDelete('cascade');
});
Schema::table('inventory_response', function ($table) {
$table->integer('inventory_id')->unsigned()->change();
$table->foreign('inventory_id')
->references('id')->on('inventories')
->onDelete('cascade');
});
Schema::table('inventory_response', function ($table) {
$table->integer('sample_result_set_id')->unsigned()->change();
$table->foreign('sample_result_set_id')
->references('id')->on('sample_response_set')
->onDelete('cascade');
});
}
In the beginning of your migration turn off foreign key constraints.
SET FOREIGN_KEY_CHECKS=0;
Then, when the data is migrated, turn them back on.
SET FOREIGN_KEY_CHECKS=1;
If that doesn't work, then try adding the following line.
$table->engine = 'InnoDB'
Further, you can rename the constraint since the name may already be used...
$table->foreign('inventory_id', 'fk_questions_inventory_id')->...
Try to use two separate migrations.
Create first migration, which will create tables and all columns (put everything except $table->foreign clauses here). Run migrate command. Do not execute second one, temporarily remove it from migrations directory, if you've already have this migration.
Then create second migration, which will add foreign keys to already created columns (use only $table->foreign clauses here). Run migrate command again.
This helped me, when I was in the same situation. I hope it will work for you too.

Laravel 5.1 - General error: 1005 Can't create table (mysql)

I'm using laravel to migrate some data, but i'm having this message below:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'heinz.#sql-1e83_8' (errno: 150) (SQL: alter table `funcionarios` add constraint funcionarios_supervisor_id_foreign foreign key (`supervis
or_id`) references `funcionarios` (`id`))
I tried a lot of thing, but didn't work.
Here is the code of the migration file. (the relevant part).
Schema::create('funcionarios', function (Blueprint $table) {
// $table->engine = 'InnoDB';
$table->increments('id');
$table->string('nome', 60);
$table->integer('matricula')->unsigned()->unique();
$table->bigInteger('pis_pasep')->unsigned()->nullable();
$table->date('data_admissao')->nullable();
$table->date('data_demissao')->nullable()->default(null);
$table->date('data_nascimento')->nullable();
$table->string('apelido', 20)->nullable();
$table->integer('supervisor_id')->nullable();
$table->integer('coordenador_id')->nullable();
$table->integer('gerente_id')->nullable();
$table->integer('diretor_id')->nullable();
$table->integer('sexo_id')->nullable();
$table->integer('setor_id')->nullable();
$table->integer('cargo_id');
$table->integer('turno_id')->nullable();
$table->timestamps();
});
Schema::table('funcionarios', function($table){
$table->foreign('supervisor_id')->references('id')->on('funcionarios');
$table->foreign('coordenador_id')->references('id')->on('funcionarios');
$table->foreign('gerente_id')->references('id')->on('funcionarios');
$table->foreign('diretor_id')->references('id')->on('funcionarios');
$table->foreign('sexo_id')->references('id')->on('sexos');
$table->foreign('setor_id')->references('id')->on('setores');
$table->foreign('cargo_id')->references('id')->on('cargos');
$table->foreign('turno_id')->references('id')->on('turnos');
});
All of your foreign keys must be unsigned
$table->integer('supervisor_id')->unsigned()->nullable();
$table->integer('coordenador_id')->unsigned()->nullable();
$table->integer('gerente_id')->unsigned()->nullable();
$table->integer('diretor_id')->unsigned()->nullable();
$table->integer('sexo_id')->unsigned()->nullable();
$table->integer('setor_id')->unsigned()->nullable();
$table->integer('cargo_id')->unsigned();
$table->integer('turno_id')->unsigned()->nullable();
(source: http://laravel.com/docs/4.2/schema#foreign-keys)
Without seeing your table structure, from your below query it could be that
both column id and supervisor_id doesn't match datatype and size. Make sure both datatype and size are same for both this column
Also, check if any other constraint with name funcionarios_supervisor_id_foreign already exists. If so, try providing a different name for the constraint.
alter table `funcionarios` add constraint funcionarios_supervisor_id_foreign
foreign key (`supervisor_id`) references `funcionarios` (`id`)
You get error code 1005 when there is a wrong primary key reference in your code. Here is what you can do to debug your code:
Make sure that your FK you are referring actually exists.
Make sure that you don't have typo. The case must be same too.
FK-linked fields must match definitions exactly.
The execution order of the migration files needs to be checked first. the referenced table migration should be done before refer it in integrity constains.

Laravel Migrations self-referencing foreign key General error: 1005 Can't create table

Why do I have a problem creating a table using Laravel Migrations Schema Builder?
The problem occurs with a table with a self-referencing foreign key.
Schema::create('cb_category', function($table)
{
$table->integer('id')->primary()->unique()->unsigned();
$table->integer('domain_id')->unsigned();
$table->foreign('domain_id')->references('id')->on('cb_domain');
$table->integer('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
$table->string('name');
$table->integer('level');
});
SQLSTATE[HY000]: General error: 1005 Can't create table 'eklik2.#sql-7d4_e' (errno: 150) (SQL: alter table `cb_category` add constraint cb_category_parent_id_foreign foreign key (`parent_id`) references `cb_category` (`id`) on delete cascade on update cascade) (Bindings: array ())
[PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table 'eklik2.#sql-7d4_e' (errno: 150)
You have to break this into two Schema blocks, one creating the columns, the other adding the FKs. mysql can't do both at the same time.
Two querys work :
Schema::create('cb_category', function($table)
{
$table->integer('id')->primary()->unique()->unsigned();
$table->integer('parent_id')->nullable();
});
Schema::table('cb_category', function (Blueprint $table)
{
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
});
I may be too late for the party, but the official docs claim that the foreign key, in case of integer, must be ->unsigned();
http://laravel.com/docs/4.2/schema#foreign-keys
Note: When creating a foreign key that references an incrementing
integer, remember to always make the foreign key column unsigned.
Also, Artisan does not fail if you (as I have) misspell unsigned() and I have spent quite a few hours trying to figure out why the key was not created.
So two things:
1. Always make the foreign key column unsigned in case of incrementing integers
2. Check the spelling of unsigned()
Also a late response but probably a more idiomatic way for Laravel 8:
use App\Models\CbCategory;
...
Schema::create("cb_category", function(Blueprint $table)
{
$table->id();
$table->foreignIdFor(CbCategory::class, "parent_id")
->constrained()
->cascadeOnUpdate()
->cascadeOnDelete()
->nullable();
});
Please Note: I guessed the class name of CbCategory here. Using the class reference firsthand (instead of the former table name string) enables your static code checkers to pick up on future class name changes.
Also the _id-suffix at the parent_id column name is important.
May the following resources quench your thirst for knowledge:
id(): https://laravel.com/docs/8.x/migrations#column-method-id
foreignIdFor(): https://laravel.com/api/8.x/Illuminate/Database/Schema/Blueprint.html
cascadeOnDelete() & cascadeOnUpdate(): https://laravel.com/api/8.x/Illuminate/Database/Schema/ForeignKeyDefinition.html
Schema::create('cb_category', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('domain_id')->unsigned();
$table->foreign('domain_id')->references('id')->on('cb_domain');
$table->integer('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
$table->string('name');
$table->integer('level');
});
Try this
I think you have another table that references the current table that you want to create.
I had this problem and remove that table and my problem was solved
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->integer('parent_id')->unsigned();
$table->foreign('parent_id')->on('categories')->references('id');
});
i got same error when i used this code, after change "$table->integer('parent_id')->unsigned()" to "$table->bigInteger('parent_id');"
my problem solved.
The point here is to make sure that the type of foreign key is the same as the primary key.
Since Laravel 8+ you don't have to break into two Schema blocks. You can use
foreignIdFor(CbCategory::class, 'cb_category_id') and it will create a column named cb_category_id
Ex.
Schema::create("cb_category", function(Blueprint $table)
{
$table->id();
$table->foreignIdFor(CbCategory::class, 'cb_category_id')->nullable()->constrained()->cascadeOnUpdate()->cascadeOnDelete();
});
Any additional column modifiers (Ex. nulleable) must be called before the constrained method.
You can use a second parameter in foreignIdFor for the referencing column name (in case it isn't 'id') NOT for the name you want it to have, in your case the name will automatically be 'cb_category_id'

Categories