Laravel migration can't add foreign key - mysql

I'm trying to write a laravel database migration but I'm getting the following error about a foreign key:
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1072 Key column 'category_id' doesn't exist in table (SQL: alter table `subcategories` add constraint subcategories_category_id_foreign foreign key (`category_id`) references `categories` (`id`))
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1072 Key column 'category_id' doesn't exist in table
The categories and subcategories tables do get created but the foreign key doesn't. Here's my migration:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoryTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('categories', function ($table) {
$table->increments('id')->unsigned();
$table->string('name')->unique();
});
Schema::create('subcategories', function ($table) {
$table->increments('id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
$table->string('name')->unique();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('categories');
Schema::drop('subcategories');
}
}
Any ideas? Thanks!

You should create column before creating a foreign key:
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
Documentation: http://laravel.com/docs/5.1/migrations#foreign-key-constraints

Laravel 7, 8
As Limon Monte mentioned firstly create column then add foreign key constraints
$table->foreignId('category_id');
$table->foreign('category_id')->references('id')->on('categories');

Integer didn't work for me. Rather, I used bigInteger to create foreign key:
$table->bigInteger('category_id')->unsigned()->index()->nullable();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');

I forgot to add ->get() to the methods I called.

Related

Unable to rename a foreign column in laravel 5.8 - column not found error

I am trying to rename a foreign column. So I write the following code:
Schema::table('floor_plans', function (Blueprint $table) {
$table->dropForeign(['unit_type_id']);
$table->renameColumn('unit_type_id', 'utd_id');
$table->foreign('utd_id')
->references('id')
->on('unit_type_details')
->onDelete('cascade');
});
But it throws
Doctrine\DBAL\Schema\SchemaException : There is no column with name 'unit_type_id ' on table 'floor_plans'.
at D:\wamp64\www\amenity\vendor\doctrine\dbal\lib\Doctrine\DBAL\Schema\SchemaException.php:85
81| * #return \Doctrine\DBAL\Schema\SchemaException
82| */
83| public static function columnDoesNotExist($columnName, $table)
84| {
> 85| return new self(
86| sprintf("There is no column with name '%s' on table '%s'.", $columnName, $table),
87| self::COLUMN_DOESNT_EXIST
88| );
89| }
Then I tried by turning foreign checks off:
DB::statement('SET FOREIGN_KEY_CHECKS=0');
$table->dropForeign(['unit_type_id']);
$table->renameColumn('unit_type_id ', 'utd_id');
DB::statement('SET FOREIGN_KEY_CHECKS=1');
But same error, the column not found.
Then I tried to drop foreign with exact ForeignKeyConstraint as :
DB::statement('SET FOREIGN_KEY_CHECKS=0');
$table->dropForeign('floor_plans_unit_type_id_foreign');
$table->renameColumn('unit_type_id', 'utd_id');
DB::statement('SET FOREIGN_KEY_CHECKS=1');
$table->foreign('utd_id')
->references('id')
->on('unit_type_details')
->onDelete('cascade');
Still the same error.
I then even tried with Raw SQL as:
DB::statement("ALTER TABLE floor_plans
DROP FOREIGN KEY `floor_plans_unit_type_id_foreign`,
ADD CONSTRAINT `floor_plans_unit_type_detail_id_foreign` FOREIGN KEY (`unit_type_detail_id`) REFERENCES `unit_type_details` (`id`)");
And this gives me the following error:
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'floor_plans_unit_type_id_foreign'; check that column/key exists (SQL: ALTER TABLE floor_plans
DROP FOREIGN KEY `floor_plans_unit_type_id_foreign`,
ADD CONSTRAINT `floor_plans_unit_type_detail_id_foreign` FOREIGN KEY (`unit_type_detail_id`) REFERENCES `unit_type_details` (`id`))
And here is the screenshot of the table.
All I want is to rename unit_type_id to unit_type_detail_id.
#PS: the table is not empty. And, I am happy to run even if you provide me the raw MySQL query.
Their is an additional space on unit_type_id.
Schema::table('floor_plans', function (Blueprint $table) {
$table->dropForeign(['unit_type_id']);//note foreign key already dropped so also you have to make this line also as comment when you test.
//$table->renameColumn('unit_type_id ', 'utd_id');//remove this space and try again
$table->renameColumn('unit_type_id', 'utd_id');//after remove space
$table->foreign('utd_id')
->references('id')
->on('unit_type_details')
->onDelete('cascade');
});

I need to update existing foreign key, but I can't drop it in order to update it

I've got a migration to correct existing foreign key, it looks like this
public function up()
{
Schema::table('content_term', function (Blueprint $table) {
$table->dropForeign('content_term_content_id_foreign');
$table->foreign('content_id')->references('id')->on('content')->onUpdate('cascade')->onDelete('cascade');
});
}
The original table and foregin key looked like this
public function up()
{
Schema::create('content_term', function (Blueprint $table) {
$table->increments('id');
$table->unsignedBigInteger('content_id')->unsigned();
$table->unsignedInteger('term_id');
$table->foreign('content_id')->references('id')->on('content')->onUpdate('cascade');
$table->foreign('term_id')->references('id')->on('terms')->onDelete('cascade')->onUpdate('cascade');
});
}
I forgot to add onDelete('cascade') for content_id foreign key creation and need to correct that in a new migration.
When I run php artisan migrate with thew latest migration I've added I get this
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'content_term_content_id_foreign'; check that column/key exists (SQL: alter table content_term drop foreign key content_term_content_id_foreign)
MYSQL complains that the foreign key does not exist in content_term table. When I check that table using phpmyadmin I can clearly see that key exists. See attached pic for proof of that.
What's the problem with my new migration, why is this line causing a problem:
$table->dropForeign('content_term_content_id_foreign');

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

i have reply_qs table and postqs table.Postqs_id is foreign key in reply_qs table.when i tried to save the reply_qs form data in database,its showed this error.
ERROR:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a
child row: a foreign key constraint fails (fyp2.reply_qs, CONSTRAINT
reply_qs_postqs_id_foreign FOREIGN KEY (postqs_id) REFERENCES postqs
(id) ON DELETE CASCADE ON UPDATE CASCADE) (SQL: insert into reply_qs
(reply, updated_at, created_at) values (saann, 2017-09-22 15:35:03,
2017-09-22 15:35:03))
how i can solve it? and please explain why im getting this error.
reply_qs model :
protected $table = 'reply_qs';
protected $fillable = ['reply'];
public function postqs(){
return $this->hasMany('App\Postqs');
}
postqs model :
public function reply_qs(){
return $this->hasMany('App\Reply_qs');
}
store function:
public function store(Request $request){
$data = $request->all();
$postqs=($request->id);
$reply=Reply_qs::create($data);
$reply->postqs($id);
}
migration:
Schema::create('reply_qs', function (Blueprint $table) {
$table->increments('id')->unique();
$table->text('reply');
$table->timestamps('date');
});
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
Schema::table('reply_qs',function(Blueprint $table)
{
$table->integer('postqs_id')->unsigned();
$table->foreign('postqs_id')->references('id')->on('postqs') -
>onDelete('cascade')->onUpdate('cascade');
});
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
Your relationships are not correct.
Your Reply_qs model should have this relationship with Postqs
public function postqs()
{
return $this->belongsTo(Postqs::class);
}
Your store function does not look correct and should look something like this
public function store( Request $request )
{
$reply = new Reply_qs();
$reply->text = $request->get('text');
$reply->postqs_id = $request->get('postqs_id');
$reply->save();
}
In your store method, it looks like you are trying to associate the parent Postqs object with the Reply_qs.
You would do this like so
$reply->associate($post);
You need to pass the object and not the id
If you are still struggling with this double check your foreign keys are matching correctly, you may need to implement the association like so
public function postqs()
{
return $this->belongsTo(Postqs::class, 'postqs_id', 'id);
}

Laravel 5.1 Migration and Seeding Cannot truncate a table referenced in a foreign key constraint

I'm trying to run the migration (see below) and seed the database, but when I run
php artisan migrate --seed
I get this error:
Migration table created successfully.
Migrated: 2015_06_17_100000_create_users_table
Migrated: 2015_06_17_200000_create_password_resets_table
Migrated: 2015_06_17_300000_create_vehicles_table
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table
referenced in a foreign key constraint (`app`.`vehicles`, CONSTRAINT `vehic
les_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `app`.`users` (`id`
)) (SQL: truncate `users`)
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table
referenced in a foreign key constraint (`app`.`vehicles`, CONSTRAINT `vehic
les_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `app`.`users` (`id`
))
I looked up what this error is supposed to mean, and also found examples of other people running into the same problem, even just related to using MySQL, and their solutions, but applying:
DB::statement('SET FOREIGN_KEY_CHECKS=0;'); and
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
Within down() doesn't seem to work and when I run describe in MySQL the tables look right.
The migrations are named properly to make sure the users table is migrated first, and then vehicles so the foreign key can be applied, and the tables being setup up correctly suggests the migrations were run, but then the error occurs. I dropped and recreated the DB and tried it again and it is the same result. I also don't understand why it is trying to truncate on the first migration and seed of the database, I wouldn't have thought that would occur when you tried to run php artisan migrate:refresh --seed.
// 2015_06_17_100000_create_users_table.php
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('username', 60)->unique();
$table->string('email', 200)->unique();
$table->string('password', 255);
$table->string('role')->default('user');
$table->rememberToken();
$table->timestamps();
});
}
}
public function down()
{
Schema::drop('users');
}
// 2015_06_17_300000_create_vehicles_table.php
class CreateVehiclesTable extends Migration
{
public function up()
{
Schema::create('vehicles', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('make');
$table->string('model');
$table->string('year');
$table->string('color');
$table->string('plate');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
}
public function down()
{
Schema::drop('vehicles');
}
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
App\User::truncate();
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
And it works!
As the error says, you can not truncate tables referenced by foreign keys. Delete should work though...
DB::table('some_table')->delete();
before drop
Schema::disableForeignKeyConstraints();
and before close run method
Schema::enableForeignKeyConstraints();
To clear a table using Eloquent:
Model::query()->delete();
Example using default user model
User::query()->delete();
I faced the same issue with my Role and Permission setup and this is what I did that worked as I wanted. Truncate() will reset the Increment column to 1 but throw a foreign key error while delete on the other hand works fine but doesn't reset the increment column, so I did the following in my Seeder's file (i.e RoleSeeder.php in my case)
1. [ delete() method ]
$roles = [];
... // Some foreach statement to prepare an array of data for DB insert()
// Delete and Reset Table
DB::table('roles')->delete();
DB::statement("ALTER TABLE `roles` AUTO_INCREMENT = 1");
// Insert into table
DB::table('roles')->insert($roles);
This will cascade all other child tables attached to the roles table. in my case users_roles table. This way I avoided disabling and enabling foreign key checks.
2. Something to put in mind / Second Approach [ truncate() method ]
if you don't have the intention of deleting all the data stored in the child's table (in my case users_roles table) ... You can go with truncate() and then in the DatabaseSeeders.php file you disable and enable foreign key check. As I tested this and the users_roles data was intact, the seed on affected roles table.
//RoleSeeders.php File
$roles = [];
... // Some foreach statement to prepare an array of data for DB insert()
// Truncate Table
DB::table('roles')->truncate();
// Insert into table
DB::table('roles')->insert($roles);
Then in the DatabaseSeeder.php file, you do;
public function run()
{
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
$this->call([
RoleSeeder::class,
]);
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
But I prefer the delete() method, since I don't have to disable/enable the foreign key check
you can use
DB::table('your_table_name')->delete();
to empty a table, this won't delete the table structure. But the auto increment id will not start from initial number.
Here is what works for me every time.
When you're adding the foreign key, make sure to add cascade.
the syntax is like this
$table->foreign('column')->references('id')->on('table_name')->onDelete('cascade');
Make sure to replace id with whatever field is applicable for you.
Now before running the seeding add this instead of trucate
DB::statement('DELETE FROM table_name');
It will delete all the data.
Hope this helps.
You could just drop it with.
$table->dropForeign('posts_user_id_foreign');
I'm using Laravel 7.x, this worked for me. Goes without saying that it should only be used in development. To read more, check it out here.
DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
// the Eloquent part and disabling and enabling of foreign keys is only intended for development
Eloquent::unguard();
//disable foreign key check for this connection before running seeders
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
$this->call(RolesTableSeeder::class);
$this->call(UsersTableSeeder::class);
// supposed to only apply to a single connection and reset it's self
// but I like to explicitly undo what I've done for clarity
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}
}

SQLSTATE[23000]: Integrity constraint violation during migration in Laravel 4

I have a problem while migrating
Migration File
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterTableMm extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('downloads', function($table){
$table->engine = 'InnoDB';
$table->increments('id')->unsigned();
$table->string('title',255);
$table->string('count',45)->default(0);
$table->timestamps();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
Schema::table('marketing_materials', function($table)
{
$table->string('download_total', 45 )->default(0);
$table->integer('download_id')->unsigned();
$table->foreign('download_id')->references('id')->on('downloads');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('users', function($table)
{
$table->dropForeign('users_user_id_foreign');
});
Schema::drop('downloads');
Schema::table('marketing_materials', function($table)
{
$table->dropForeign('marketing_materials_download_id_foreign');
});
Schema::table('marketing_materials', function($table)
{
$table->dropColumn('download_total');
$table->dropColumn('download_id');
});
}
}
Error Message
[Illuminate\Database\QueryException]
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`distributor-local`.`#sql-668_3d`, CONSTRAINT `marketing_mater
ials_download_id_foreign` FOREIGN KEY (`download_id`) REFERENCES `downloads` (`id`)) (SQL: alter table `marketing_materials` add constraint marketing_materials_download_id_foreign fo
reign key (`download_id`) references `downloads` (`id`))
[PDOException]
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`distributor-local`.`#sql-668_3d`, CONSTRAINT `marketing_mater
ials_download_id_foreign` FOREIGN KEY (`download_id`) REFERENCES `downloads` (`id`))
I have all the required tables
users
marketing_materials
I just recently migrate my downloads table
Can someone tell me what did I do wrong ?
The part that confuse me the most of that error message is that, all the contents are added the database fine. See the picture below
I also alter my marketing_materials table, and that's also work.
Should I just ignore the error message ???