SQLSTATE[HY000]: General error:Can't create table - php

I am using Laravel 8.21.0 on a CentOS 8 server. I am using mariaDB. I have 3 tables: tests, students and grades.
I am trying to set foreign key of tests and students on the grades table.
However, when I run my migrations, I get errorno 150: Foreign key constraint is incorrectly formed.
Here are my migrations:
Grades table:
class CreateGradesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('grades', function (Blueprint $table) {
$table->id('id')->unique();
$table->unsignedInteger('student_id');
$table->string('test_id');
$table->foreign('test_id')->references('id')->on('tests');
$table->foreign('student_id')->references('id')->on('students');
$table->date('testDate');
$table->integer('testCount');
$table->integer('vocabScore');
$table->integer('readingScore');
$table->integer('listeningScore');
$table->integer('rawTotal');
$table->integer('adjustVocabScore');
$table->integer('adjustReadingScore');
$table->integer('adjustlisteningScore');
$table->integer('adjustTotal');
$table->string('passOrfail');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('grades');
}
}
Student Table migrations:
class CreateStudentsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->integer('id')->unique();
$table->string('name');
$table->date('DOE');
$table->string('belongsTo');
$table->string('country');
$table->string('level');
$table->string('year');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('students');
}
}
Test table:
class CreateTestsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tests', function (Blueprint $table) {
$table->string('id')->unique();
$table->string('testName');
$table->string('level');
$table->integer('vocabFullScore');
$table->integer('readingFullScore');
$table->integer('listeningFullScore');
$table->integer('totalFullScore');
$table->integer('vocabPassScore');
$table->integer('readingPassScore');
$table->integer('listeningPassScore');
$table->integer('totalPassScore');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('tests');
}
}
The bizzare thing is that the migrations table gets created successfully when I run it on localhost WAMP server but it throws me an error on CENTOS server. Does anyone have any idea on how to solve this?
Things that I have tried doing but did not work:
・Changed database to InnoDB by specifying 'engine' => 'InnoDB' on each model.
・Made sure that the order of migration is correct. First migrated student table, then tests and lastly grades.
・Ensure that the data type of the foreign key is correct on grades table.
Any ideas would be greatly appreciated. :'(
Edit: I set the foreign key type of student_id as integer.
In grades table migration:
$table->integer('student_id');
$table->foreign('student_id')->references('id')->on('students');
In students table migration:
$table->integer('id')->unique();
After doing this I am getting a new error:
Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for right syntax to use near ')' at line 1 (SQL: alter table 'grades' add constraint 'grades_test_id_foreign' foreign key ('test_id') references 'tests' ())
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:678
catch(Exception $e){
throw new QueryException(
$query, $this->prepareBindings($bindings),$e
);
}
+9 vendor frames
database/migrations/2021_01_13_064711_create_grades_table.php:54
Illuminate\Support\Facades\Facade::__callStatic()
+32 vendor frames
artisan:37
Illuminate\Foundation\Console\Kernel::handle()

Change
$table->unsignedInteger('student_id');
to
$table->integer('student_id');
in grades table to match the datatypes to form a constraint.

Related

What is the correct foreign key constraint syntax for a database migration in Laravel 8.X Eloquent?

I am a Laravel and Eloquent noob.
I'm trying to do a simple foreign key in a "checklist items" table that takes the primary ID from the "users" table as a foreign key.
Here are my two database migrations:
users:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
items:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
});
Schema::table('items', function($table) {
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}
attempting to run php artisan migrate yields the following error:
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.49 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.59 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.33 seconds)
Migrating: 2021_05_04_085648_create_items_table
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `items` add constraint `items_user_id_foreign` foreign key (`user_id`) references `users` (`id`))
at D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:671
667| // If an exception occurs when attempting to run a query, we'll format the error
668| // message to include the bindings with SQL, which will make this exception a
669| // lot more helpful to the developer instead of just the database's errors.
670| catch (Exception $e) {
> 671| throw new QueryException(
672| $query, $this->prepareBindings($bindings), $e
673| );
674| }
675|
1 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOException::("SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
2 D:\Applications\laragon\www\ToDoApp\vendor\laravel\framework\src\Illuminate\Database\Connection.php:464
PDOStatement::execute()
It should be noted that I can achieve what I need fine in the PHPMyAdmin GUI directly, or using basic PHP PDOs, but I don't understand Eloquent and need to understand what I am doing wrong.
I have a feeling that it's to do with a mismatch in the attribute definitions between the two table migrations, but the few things I tried caused alternate errors.
columns must be of the same type and sign (signed or unsigned)
$table->integer('user_id')->unsigned(); should be $table->bigInteger('user_id')->unsigned();
Just make a new Migration file for only the foreign key (docs). something like
php artisan make:migration add_columns_to_items_table
Why use different file for same table? Because we make the table first before we make the foreignKey right? :)
Then inside your migration file on up() function:
Schema::table('items', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
Yah, its shorter and better for development purpose
This happens when you create the migration for the many before the one part of one-to-many relationship. In your case I guess you created migration for items before users. Simply rename your migration files according to your relationships. Also please note that your relationship columns must be of the same type. In your case, you are referencing an integer of 4-byte to bigInteger of 8-byte. (id columns is an unsigned 8-byte integer).
Replace your items migration with the following code:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('itemName');
$table->string('itemDescription');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('items');
}
}

Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1064

I am trying to migrate tables created in laravel to database and using foreign key. Buut I am getting the following error. Please help me where is the error?
Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access
violation: 1064 You have an error in your SQL syntax; check the manual that cor
responds to your MariaDB server version for the right syntax to use near ')' at
line 1 (SQL: alter table publications add constraint publications_user_id_for
eign foreign key (user_id) references registrations ())
Exception trace:
PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1064 Yo
u have an error in your SQL syntax; check the manual that corresponds to your Ma
riaDB server version for the right syntax to use near ')' at line 1")
C:\xampp\htdocs\plearning\vendor\laravel\framework\src\Illuminate\Database
\Connection.php:452
PDO::prepare("alter table publications add constraint publications_user
_id_foreign foreign key (user_id) references registrations ()")
C:\xampp\htdocs\plearning\vendor\laravel\framework\src\Illuminate\Database
\Connection.php:452
Please use the argument -v to see more details.
The parent table is registration and its code is given below.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRegistrationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('registrations', function (Blueprint $table) {
$table->increments('id'); //primary key
$table->string('tname');
$table->string('fname');
$table->string('domicile');
$table->integer('nic');
$table->integer('phone');
$table->string('email');
$table->string('off_email');
$table->string('password');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('registrations');
}
}
The code of second table where I am using foreign key is educations and its code is given below.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEducationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('educations', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->refrences('id')->on('registrations');
$table->string('degree');
$table->string('univ');
$table->string('country');
$table->integer('year');
$table->text('research_area');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('educations');
}
}
And the third table where I am using also the foreign key, as a primary key of regstration table is publications and its code is given below.
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePublicationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('publications', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->refrences('id')->on('registrations');
$table->string('title');
$table->string('status');
$table->integer('year');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('publications');
}
}
The error is above which I already paste. but the publication table is migrating to database, while other two tables registrations and educations is not migrating.
I see you have misspelled the word references inside your migrations, could you update it to in all your migrations:
...->references('...')...
If this doesn't fix the issue, then your issue is in the order of execution of migrations, meaning that your file order matters when migrations are ran

laravel : seeder with foriegn keys

in my database i have already tables namely: notifications table, statuses table, they have many to many relation, that is why i have a pivot table called notification_status. i created them with migrations and seed them with a seeder, all works fine. now i realize that i need one extra table which has many to one relation with notifications table(natification->hasMany->alertfrequency). when i tried to migrate it, it did allow me to do so.
here is my notification table
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateNotificationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('notifications', function (Blueprint $table) {
$table->increments('id');
$table->string('website_url');
$table->string('email');
$table->string('slack_channel');
$table->string('check_frequency');
$table->string('alert_frequency');
$table->string('speed_frequency');
$table->boolean('active');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('notifications');
}
}
and the alert frequency table, the new table i want to add,
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAlertFrequenciesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('alertFrequencies', function (Blueprint $table) {
$table->increments('id');
$table->integer('notification_id');
$table->foreign('notification_id')
->references('id')->on('notifications')
->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('alertFrequencies');
}
}
when i tried to add i get the following constrain
[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `alertFrequencies` add constraint `alertfrequencies_notification_id_foreign` foreign key (`notification_
id`) references `notifications` (`id`) on delete cascade)
any one with a idea or suggestion. i appreciate all idea and suggestions.
From #AlexeyMezenin's answer, update based on Documentation:
Replace
$table->integer('notification_id')->unsigned();
with
$table->unsignedInteger('notification_id');
First thing you should do is to add unsigned(), because id is unsigned too:
$table->integer('notification_id')->unsigned();
If it'll not help, divide key creation and adding a foreign key constraint:
Schema::create('alertFrequencies', function (Blueprint $table) {
$table->increments('id');
$table->integer('notification_id')->unsigned();
$table->timestamps();
});
Schema::table('alertFrequencies', function (Blueprint $table) {
$table->foreign('notification_id')->references('id')->on('notifications')->onDelete('cascade');
});
You need to migrate notifications table prior to alertFrequencies table as notification_id of alertFrequencies is referencing id of notifications table.
And you need to change $table->integer('notification_id'); to $table->integer('notification_id')->unsigned(); as you cannot accept minus ids as foreign key
And also make sure you have set your table engine set to InnoDB in your `config/database.php'.
$table->engine = 'InnoDB';

Handling foreign checks in Laravel 5 migrations

I have a calls table with user_id column and a foreign key constrain. So, user_id is related to users table.
I made a migration which deletes the column and foreign key constrain. The up method works fine. However, when it comes to down it breaks down because I add a user_id column and then restore the constrain, but the values in the column have nothing to do with real data so I got 150 MySQL error.
I've found a solution which didn't work for me. The solution is to temporarily disable foreign key constrains. Here is my migration file:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RemoveUseridFromCalls extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('calls', function(Blueprint $table)
{
$table->dropForeign('calls_user_id_foreign');
$table->dropColumn('user_id');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
\DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::table('calls', function(Blueprint $table)
{
$table->integer('user_id')->unsigned();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('set null');
});
\DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}
}
But I still get the same error.
So, the questions are:
What would you do if you need to remove user_id from columns table as it's not needed anymore, however you have to write the down method as well as up?
Why disabling foreign key checks doesn't work?
I use InnoDB as table type for all my tables.
You can simply use onDelete('cascade').
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('calls', function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade'); // use 'cascade'
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('calls');
}
}
onDelete('cascade') tells Laravel to delete a calls row when it's corresponsding foreign key user_id is deleted.
I had the same problem and fixed it by separating migration into several files. First one creates the table, the others add columns for the keys and the keys themselves.
After that everything starts working like a charm.
To check foreign key in table while dealing with migration can be as follow:
$keyExists = DB::select(DB::raw('SHOW KEYS FROM TABLE_NAME WHERE Key_name=\'YOUR_FOREIGN_KEY_NAME\''));
if(!$keyExists){
$table->foreign('app_id')
->references('id')
->on('apps')
->onDelete('cascade');
}

laravel and artisan error cannot add foreign key on migrate

I know this has been answered many times as i saw many answers suggestions when i wrote the question, but none of them actually get me the correct answer.
When i try to add new field to the table and use artisan migrate in laravel i get an error
General error: 1215 Cannot add foreign key constraint (SQL: alter table `pages` add constraint pages_page_status_foreign foreign key (`page_status`) references `page_status` (`status_value`))
But i don't understand why do i get an error when before i have done the same thing and with no errors, only answer i could think of is that it's not possible to have two or more foreign keys on same table. Here is my migrate function
class CreateStatusTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('page_status', function($table) {
$table->increments('id');
$table->string('status_name');
$table->integer('status_value')->unsigned();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('page_status');
}
}
This is for status table, and now i have to add new field to pages table using this.
class AddStatusToPagesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('pages', function($table) {
$table->integer('page_status')->unsigned();
$table->foreign('page_status')->references('status_value')->on('page_status');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('pages', function($table) {
$table->dropForeign('pages_page_status_foreign');
});
}
}
And this is where the error appears, for some reason it does not let me set foreign key on page_status field into pages table.
I am using xampp installation on my localhost and in phpmyadmin i can see that table is set to innodb, actually everything is set to innodb by default. and inside my database in pages table looking at page_status field i have first to set it index than i am able to use relations. why it's not set to index i don't know but i already have on that table id as an index and author as foreign key.
Before this i also added few fields when creating pages table and using this
class CreatePagesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('pages', function($table){
$table->increments('id');
$table->integer('author')->unsigned();
$table->foreign('author')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('pages');
}
}
I did not had any problems when using migrate, it worked well and author is set as foreign key.
So why i can't add new foreign key now ?
This is probably due to the fact that a foreign key can't be added if the current records do not meet the condition. If page_status is optional make the field nullable:
$table->integer('page_status')->unsigned()->nullable();
If you don't want to make it nullable and are going to insert valid foreign key values later you can disable foreign key checks temporarily:
DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::table('pages', function($table) {
$table->integer('page_status')->unsigned();
$table->foreign('page_status')->references('status_value')->on('page_status');
});
DB::statement('SET FOREIGN_KEY_CHECKS = 1');
I found where the problem is, after adding a new field to the table you have to set the index on that field, so there is a one step further on migration for setting the field as index.
I still do not understand why in my first migration when i added "author" field it made it automatically as an index but for this one i got it working by setting index additionally like this:
Schema::table('pages', function($table) {
$table->integer('status')->unsigned()->nullable();
$table->index('status');
$table->foreign('status')->references('status_value')->on('page_status');
});

Categories