Adding a foreign key constraint with a Laravel Migration - php

I have started a new Laravel 5.5 project and I am receiving the following error when trying to add a foreign key to my users table:
General error: 1215 Cannot add foreign key constraint (SQL: alter table users add constraint users_organization_id_foreign foreign key (organization_id) references organizations (id) on delete cascade)
Here is the migration code for the organization table:
Schema::create('organizations', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('subdomain')->nullable();
$table->timestamps();
$table->softDeletes();
});
Here is the migration code for the users table:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('organization_id')->unsigned();
$table->foreign('organization_id')->references('id')->on('organizations');
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->timestamps();
$table->softDeletes();
});
I have researched this error online and the common thing to make sure of are that the data types are the same. From what I can see, they are the same. What's even crazier is that if I run this query in the database directly it works:
alter table `users` add constraint `users_organization_id_foreign` foreign key (`organization_id`) references `organizations` (`id`)

By default, in each Laravel fresh installation users table is created first. But since you're adding a constraint in this table, you need to create organizations table first.
So, put organizations table migration before users table migration by changing organizations migration date in the file name:
2014_01_01_000000_create_organizations_table.php

Going along with Alexey's answer. I would also suggest that you enable/disable foreign key constraints before you run your migrations:
Schema::disableForeignKeyConstraints();
// Your migration code.
Schema::enableForeignKeyConstraints();
This way you don't need to rename your migration files.

Related

SQLSTATE[HY000]: General error: 1005 Can't create table Laravel 8

Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('slug')->unique();
$table->integer('price');
$table->text('description');
$table->timestamps();
});
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('slug')->unique();
$table->timestamps();
});
Schema::create('category_menu', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id')->unsigned()->nullable();
$table->foreign('menu_id')->references('id')
->on('menus')->onDelete('cascade');
$table->integer('category_id')->unsigned()->nullable();
$table->foreign('category_id')->references('id')
->on('categories')->onDelete('cascade');
$table->timestamps();
});
When I run php artisan:migrate, I get the following error.
SQLSTATE[HY000]: General error: 1005 Can't create table `mieaceh`.`category_menu` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table `category_menu` add constraint `category_menu_menu_id_foreign` foreign key (`menu_id`) references `menus` (`id`) on delete cascade)
This is due to mismatch of datatype of foreign key column and the referenced column most likely
When you create a primary key with $table->id() the datatype of the auto incrementing id column is unsignedBigInteger so you must have foreign key also with the same datatype
Schema::create('category_menu', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('menu_id');
$table->foreign('menu_id')->references('id')
->on('menus')->onDelete('cascade');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')
->on('categories')->onDelete('cascade');
$table->timestamps();
});
You shouldn't make the columns in a pivot table nullable for the foreign keys to maintain data integrity.
Also be consistent with the datatype for primary key columns as well as definitions - when using $table->id() keep that consistent across all migrations for all tables. That way you will have less chances of mismatch when defining foreign keys as $table->unsignedBigInteger()
laravel migrations files contains a datetime slug that determine which file will be migrated first
notice the order
2021_10_11_101533_create_posts_table.php
2014_10_12_000000_create_users_table.php
when you run
php artisan migrate
posts table will be migrated first and it contains a foriegn key
user_id
which references a primary key on users table
id
but the users table doesn't exists yet, to fix this issues change the files names and make sure users table migrate first like this
notice the order
2014_10_10_000000_create_users_table.php
2021_10_11_101533_create_posts_table.php
short pattern for declaring a foreign key
$table->foreignId('user_id')->constrained()->cascadeOnDelete();

Laravel 7 migration error. Cannot add foreign key constraint

Try to create foreign key in Laravel 7 but when I migrate tables using artisan it gives error
SQLSTATE[HY000]: General error: 3780 Referencing column 'remote_id' and referenced column 'parent_id' in foreign key constraint 'products_remote_id_foreign' are incompatible. (SQL: alter table products add constraint products_remote_id_foreign foreign key (remote_id) references categories (parent_id) on delete cascade)
My categories table
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('parent_id');
$table->tinyInteger('depth');
$table->string('name');
$table->string('slug');
$table->text('description');
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->default(DB::raw('NULL ON UPDATE CURRENT_TIMESTAMP'))->nullable();
});
My products table
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('remote_id');
$table->foreign('remote_id')->references('parent_id')->on('categories')->onDelete('cascade');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->string('name');
$table->text('description');
$table->integer('price');
$table->tinyInteger('status')->default(1);
$table->integer('qty');
$table->string('barcode')->nullable();
$table->string('image');
$table->text('images')->nullable();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->default(DB::raw('NULL ON UPDATE CURRENT_TIMESTAMP'))->nullable();
});
Any ideas as to what I've done wrong?
Thanks for help!!!
As mentioned by aynber, for foreign keys to be compatible, they must be of the same type. Your remote_id in your products table is an unsignedBigInteger while the key you are trying to reference in your categories table, parent_id, is an integer. To fix this either change category_id in your products table to an integer or change parent_id in your categories table to an unsignedBigInteger.
Edit:
I looked a little more into foreign keys and found this useful answer on another post. Foreign keys need to have a unique constraint or be a primary key. Since your remote_id column is referencing parent_id which is neither a primary key nor has a unique constraint, you are getting this error.
The solution given in the other question for adding a unique constraint is running this command(modified for your tables):
alter table categories add constraint uq1 unique (parent_id);

(Laravel) errno: 150 "Foreign key constraint is incorrectly formed

I try to migrate my tables but it display an error which is:
errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter
table users add constraint users_role_id_foreign foreign key
(role_id) references roles (id))
This is my tables:
Schema::create('users', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->string('fullname');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->references('id')->on('roles');
$table->rememberToken();
$table->timestamps();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->string('name')->unique();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
Schema::create('posts', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->string('content');
$table->string('image');
$table->timestamps();
});
The problem is that when you create the users table with a foreign key to the roles table, then the roles table does not exist yet, therefore you cannot add a foreign key referencing it.
I also noted that the roles table also has a foreign key referencing the users table, which makes the situation more tricky.
If you are absolutely sure that the roles table needs a foreign key to the users table, then you need to remove the foreign key creation from the users table definition, and add it separately back as alter table after the roles table is created.
However, I'm not sure that the roles table should have an fk to the users table (unless it represents the user that created the role) because you can have multiple users in a role. If you are modelling a many-to-many relationship, then this is not the way to do it. But this has got nothing to do with the current error, so treat this as a side note only.
Sometimes that error can also occur due to migrations order. If you face errno 150 "Foreign key constraint is incorrectly formed" then go to your migrations folder and check whether the parent table migration was executed first or not. If child table migration is executed first according to the migration order, it will try to find foreign key binding and shows that error.

Table not found when seeding

Below are my migrations
The users table have a relation with the customer table
In user:
$table->integer('customer_id')->unsigned();
$table->foreign('customer_id')->references('id')->on('customers');
When i call php artisan migrate:refresh --seed, artisan given me the following error:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `users` add constraint `users_customer_id_foreign` foreign ke
y (`customer_id`) references `customers` (`id`))
[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
Because the customers table does not exists... (obvious)
Is there a way to solve this problem? I know changing the date of the files will fix this but there should be a beter approach
You have to create the table you're referencing to before adding the foreign key. A solution would be to remove the foreign key constraint from your user table migration and create a new migration which adds the foreign key constraints.
Try to make it separately.
public function up()
{
Schema::create('users', function(Blueprint $table) {
$table->increments('id');
$table->integer('costumer_id')->unsigned();
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::table('users', function($table) {
$table->foreign('costumer_id')->references('id')->on('costumers');
});
}
Another thing you can try(since laravel 5.3):
unsignedInteger('column_name') instead of ('column_name')-unsigned()
If you had set one field as "Unsigned" and other one not. Once you should set both columns to Unsigned it works.

How to run php artisan migrate on a db with a lot of tables and data without previous migrations in Laravel 4?

I have created a lot of tables and I have a lot of data in my db's tables already.
I haven't used migrations so far. But right now I would like to, in this case where I need to set foreign keys using this code:
public function up()
{
Schema::create('role_user', function(Blueprint $table)
{
$table->increments('id');
$table->integer('role_id')->unsigned()->index();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
But If I run php artisan migrate I get this error:
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `role_user` add constraint role_user_role_id_foreign foreign
key (`role_id`) references `roles` (`id`) on delete cascade)
migrate [--bench[="..."]] [--database[="..."]] [--force] [--path[="..."]] [--pac
kage[="..."]] [--pretend] [--seed]
I have roles and users table already and id is set as the primary key.
Any idea how to make this auto creation of the table from the schema in the migration file in my db happen?

Categories