I have created two migrations with the Jeffrey Way generators for Laravel 5. Namely: php artisan make:migrate:schema create_roles_table --schema='name:string, description:text' and php artisan make:migrate:pivot user role.
Now, my MySQL database is defaulted to InnoDB, which I've read should be. I also moved the foreign key setup to Schema::table() instead of Schema::create('role_user'). There shouldn't be anything wrong with my migrations, yet they error out with: General error: 1215 Cannot add foreign key constraint (SQL: alter table role_user add constraint role_user_user_id_foreign foreign key (user_id) references user (id) on delete cascade).
Schema::create('role_user', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('role_id')->unsigned()->index();
$table->integer('user_id')->unsigned()->index();
$table->primary(['role_id', 'user_id']);
});
Schema::table('role_user', function(Blueprint $table){
$table->foreign('user_id')->references('id')->on('user')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('role')->onDelete('cascade');
});
I have called $table->engine = 'InnoDB'; in every migration. Also have I set all id columns to unsigned, even though they were like that already. I am clueless, who helps me out..
Check to see if you have already migrated the tables users and roles. Otherwise you will not be able to create a foreign key. Check your migration order as well. If you are migrating this one before the users and roles it will fail.
Well, apparently this was a huge typo. user instead of users, for example. I had hoped Laravel would get that right, but unfortunately Laravel and I as well didn't.
This might be related to your SQL engine, check your engine (mariadb, mysql, ...)
And then read the documentation from your engine regarding foreign keys.
Quick solution
Remove the onDelete('cascade') and run the migration.
You can add it manually from phpMyAdmin later on
Related
I am building an eCommerce site and I am running into an issue when migrating my orders table. I am getting the following error:
SQLSTATE[HY000]: General error: 3780 Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'orders_user_id_foreign' are incompatible. (SQL: alter table `orders` add constraint `orders_user_id_foreign` foreign key (`user_id`) references `users` (`id`) on delete set null on update cascade)
The schema that sets up the foreign key for this migration looks like:
// set up foreign key on users
$table->integer('user_id')->unsigned()->nullable(); // will be null if guest
$table->foreign('user_id')
->references('id')->on('users')
->onUpdate('cascade')
->onDelete('set null');
I figured out that the users table schema sets up the id like so:
$table->id();
And the orders table schema sets up the id like this:
$table->increments('id');
So I changed the users migration so that it is the same as the orders migration i.e both are like:
$table->increments('id');
But when I run php artisan migrate, I get this back:
➜ MobileMastery_V2 git:(master) ✗ php artisan migrate --path=/database/migrations/2014_10_12_000000_create_users_table.php
Nothing to migrate.
As you can see above I tried declaring the path to the migration I wanted to see if that would work but it didn't. How can I get this single file to migrate? Thanks
Laravel migrations are intended to keep track of the changes you make on your database over time. Laravel creates a table called migrations that keeps track of the migrations if it already ran or not. So in this case you can create a new migration that only makes that change, or if your database has no data on it yet you can drop the database schema, make your modifications on the migrations and run it again.
And about the primary key and foreign keys, I recommend you to read this part of Laravel documentation.
You should create migration for this change and run php artisan migrate.
I am working in a project where a table has a foreign key called tax_id, the problem is that in some point another migration was created to change the tax_id to nullable.
Schema::table('products', function (Blueprint $table) {
$table->unsignedInteger('tax_id')->nullable()->change();
});
I realize this after I wrote other migrations and tried to run them, it throws Column 'tax_id' cannot be NOT NULL, it seems that in the "project" that migration was run, so I can't just delete the file, how can I run my migrations without the error? I have tried to remove the foreign key, but nothing worked.
I'll assume you're working with MySQL InnoDB because you did not specify the database type/engine.
You could try different approaches:
1) If yuo're in hurry, disable foreign keys, do the update, enable the foreign key. You should then correct the problem of course.
2) Add set tax_id to '' where tax_id is null and then do the migration
3) Document yourself about the database engine and implement a correct solution
Giacomo
Schema::create('a', function(Blueprint $table) {
$table->bigInteger('id');
$table->primary('id');
});
Schema::create('b', function(Blueprint $table) {
$table->bigInteger('id');
$table->bigInteger('a_id');
$table->foreign('a_id')->references('id')->on('a');
});
Schema::create('c', function(Blueprint $table) {
$table->bigInteger('id');
$table->bigInteger('a_id');
$table->foreign('a_id')->references('id')->on('a');
});
Running this with php artisan migrate on this gives me a
ORA-02264: name already used by an existing constraint.
It seems that migrate creates a constraint on b called A_ID_PK, then it tries to create a constrain on c called A_ID_PK and errors since there are 2 A_ID_PK constraints on the A.id. Am I correct, and if so is there a solution?
From the error utility, ORA-02264 error means ORA-02264: Name already used by an existing constraint.
And the definition is that specified constraint name has to be unique. So the solution is specify a unique constraint name for the constraint.
Problem and workaround
Not sure but the problem is that while the table may have not been created, the constraint_name might be exists in the dba_constraints view. You can check this like:
select
table_name
from
dba_constraints
where constraint_name = upper ('A_ID_PK');
If you do not have already used this constraint_name for other table.
Your solution is either of the below:
Use another constraint name, that unique to the table.
Make sure that this constraint name exists for a table.
I try to add a foreign key constraint in migrations. For some reason it does work when I set it to nullable, but it doesn't work when I make it not nullable. Why does this happen and how can I solve this?
This does work:
Schema::create('role_user', function (Blueprint $table){
$table->increments('id');
$table->integer('role_id')->unsigned()->index()->nullable();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('set null');
$table->integer('user_id')->unsigned()->index()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
$table->timestamps();
});
This throws the exception:
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('set null');
$table->integer('user_id')->unsigned()->index()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
$table->timestamps();
});
Both the role and user tables already excist before making these constraints. I want them to be not nullable (so they must be filled). The error:
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 set null)
The migrations happen in the order that you specify in the filename. Maybe your roles table hasn't been created by the time this migration is run and your DB complains about trying to reference a field in a (yet) non-existent table?
For example: 2016_03_27_0000_first will be executed before 2016_03_28_0000_second
UPDATE: Added solution.
I noticed that you have "onDelete('set null')" for the field that you are trying to set as non-nullable. That would also cause a problem if the role was deleted, since it would then try to set the value to null.
You should set both foreign keys to:
->onDelete('cascade')
This way if the user or the role get deleted, any associations related to them would also get deleted automatically and not simply set to null or left hanging around.
Cheers
I am building something that allows users to upload their graphical work and other users can comments on the projects and like other projects.
Now when a user wants to delete their own project it works but as soon as the project has comments or likes I get this error:
Integrity constraint violation: 1451
Cannot delete or update a parent row: a foreign key constraint fails
(`scotchbox`.`comments`, CONSTRAINT `comments_on_projects_foreign` FOREIGN KEY (`on_projects`)
REFERENCES `projects` (`id`)) (SQL: delete from `projects`
where `id` = 31 and `user_id` = 32)
I assume this can be resolved by deleting the comments from the comments table and the likes from the likes table aswell? but I honestly have no idea how to fix this issue with the foreign keys.
I think I need a way to delete the comments and likes of the project before deleting the project itself. Is this possible from the destroy function of my ProjectsController?
This is my destroy function for deleting the projects:
public function destroy($id)
{
$input = Request::all();
Project::whereId($id)->whereUserId(Auth::user()->id)->delete();
return redirect('projects/');
}
When you have a foreign key, you can choose the behavior of deletion.
You have: Users, Projects
User has many Projects
so that means in the Projects schema you will have something similar to this
Schema::create('projects', function(Blueprint $table){
// table fields
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
In this case, you have established a relation without saying "how to behave" if a deletion occurs on the parent (User), that means if you attempt to delete the user, the query exception will be thrown to protect you.
So, if this is the case, you will have to find all the children (Projects) of that parent (User), and delete them before you are able to delete the Parent.
the 2nd solution would be adding onDelete() behavior:
Schema::create('projects', function(Blueprint $table){
// table fields
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
This means, if you delete the Parent (User) it will automatically find all of the children (Projects) and delete them one by one for you.
Finally, please note that i am using Parent Children analogy in order to clarify the situation, where this analogy only fits in the One to Many relations.
Please avoid using the analogy when you are surrounded by Databasists to protect yourself from further consequences.
The user you try to delete commented on a project. Delete his comments before deleting the user. Or there is a comment on the project you try to delete.
Fixed it by adding onDelete('cascade') to my migrations like this:
Comments migration:
$table->foreign('on_projects')->references('id')->on('projects')->onDelete('cascade');
Likes migration:
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');