Dropping foreign keys in Laravel causes an error - mysql

After creating and using my database within my laravel application I have realized I initially put foreign keys on the wrong tables. I have a tables called Places, Prices and Websites that I want to change their columns and keys in. At the moment Places is referenced in both Prices and Websites but I want to change it so that Prices and Websites are both referenced in Places.
ERD of what my tables look like currently vs what I want
In order to do this I need to drop both the keys and columns from Prices and Websites and add two new columns to Places. For the life of me I cannot get the migration to drop the columns and foreign keys to successfully migrate.
This is the error that comes up when I try to migrate
SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP FOREIGN KEY `prices_placeid_foreign`; check that it exists (SQL: alter table `prices` drop foreign key `prices_placeid_foreign`)
This is my migration
Schema::table('prices', function (Blueprint $table) {
$table->dropForeign(['placeid']);
$table->dropColumn('placeid');
});
And this is the Prices structure
Schema::create('prices', function (Blueprint $table) {
$table->id()->autoIncrement(); //PK
$table->integer('low');
$table->integer('high');
$table->foreignId('placeid')->constrained('places')->onDelete('cascade');
});
Some of the things I've tried
$table->dropForeign('prices_placeid_foreign');
$table->dropColumn(['placeid']);
According to my table structure the foreign key name is 'prices_placeid_foreign'
Table Structure in PhpMyAdmin
EDIT: The migration where the Places table is created has already run, I am trying to do a new migration that drop the column and the key and that is what is returning the error
Please help!!!

Related

Foreign error in Laravel 8 de migration process [duplicate]

This question already has answers here:
MySQL Creating tables with Foreign Keys giving errno: 150
(20 answers)
Closed 2 years ago.
We want to assign the RequestTypeID in the Request table to the RequestTypeID column in the DefRequestType table as a foreign key, but we get the following error.
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `Request` add constraint `request_requesttypeid_foreign` foreign key (`RequestTypeID`) references `DefRequestType` (`RequestTypeID`))
We fixed the problem by fixing the table engine as MyISAM, but we want to use the table engine as InnoDB. Also, we are trying the migration process in Laravel 8 version. First I create the DefRequestType table, then I create the Request table. The reason I later changed the value of the DefRequestTypeID column to bigIncrements in the DefRequestType table was to assign two primaryKeys in the DefRequestType table. I also wanted to be able to give the DefRequestTypeID column an additional autoIncrement property.
Request table
Schema::create('Request', function (Blueprint $table) {
$table->bigIncrements('RequestID');
$table->unsignedBigInteger('RequestTypeID')->nullable(); <----------------------------
$table->unsignedInteger('CustomerID')->nullable();
$table->unsignedInteger('ApplicationID')->nullable();
$table->foreign('RequestTypeID')
->references('RequestTypeID')
->on('DefRequestType');
$table->foreign('ContentID')
->references('ContentID')
->on('Content');
});
DefRequestType table
Schema::create('DefRequestType', function (Blueprint $table) {
$table->unsignedInteger('DefRequestTypeID');
$table->unsignedBigInteger('RequestTypeID'); <----------------------------
$table->string('RequestDefinition');
$table->integer('Status')->default(1);
$table->integer('OldID');
$table->primary(['DefRequestTypeID','RequestTypeID']);
});
Schema::table('DefRequestType', function (Blueprint $table) {
$table->bigIncrements('DefRequestTypeID')->change();
});
We would appreciate it if you could help.
The problem is on the table DefRequestType the column DefRequestTypeID is an ordinary integer. On the foreign key the RequestTypeID is an big integer.
To solve this either change RequestTypeID to ordinary integer or DefRequestTypeID to a big integer.
EDIT
I would change this to the following.
$table->unsignedBigInteger('DefRequestTypeID');

Laravel 7 error when adding foreign key to Users table

using Laravel 7 and MySQL, I'm trying to add a foreign key to the Users table generated by the Laravel Auth system...
First, i've created my new table user_type and then, on another migration, I'm trying to add the foreign key to the users table, but then I get the error.
Here a gist with the migrations and the error: https://gist.github.com/jdalri/73cee7a00c513c93afd5186ca27d74a4
I've also tried using
$table->unsignedBigInteger('user_type_id');
$table->foreign('user_type_id')->references('id')->on('user_type');
but got the same error.
Thanks
your syntax is right but what is you missing is the foreign key doesnt have a default value(that exists in user_type table) or its not nullable. and its because there no record in user_type table with null value so if you reset the database with php artisan migrate:fresh that will work or make this column nullable.
$table->unsignedBigInteger('user_type_id')->nullable();
$table->foreign('user_type_id')->references('id')->on('user_type');
That works because literally the error is explaining that before you add content to the users table, user_type_id must have content. If you null it, it will work but its not a good idea to do so. I advise you if user_types are not much, create them as enum and choose the default one.
Here is a link to Laravel documentation: https://laravel.com/docs/7.x/migrations#foreign-key-constraints
Schema::table('users', function (Blueprint $table) {
$table->foreignId('user_type_id')->constrained('user_type');
});
There is no primary key for AddUserTypeToUsersTable
Try this
Schema::table('users', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_type_id');
$table->foreign('user_type_id')->references('id')->on('user_type');
});

how to edit original table in laravel migration?

My question is how to edit original table in laravel migration?
That is, suppose to there are two table have as Teacher and Children. As well as Student table has foreign key as TeacherId. (Teacher_id refer to TeacherId in Teacher table)
Some error reason I want to drop Teacher table or edit Teacher table. Then general error occur without original key table cannot had foreign key.
So how can I drop the Teacher table or edit Teacher table without drop Student table?
Have some way to do that?
First you need to drop the foreign key on the your Student table (or maybe the teacher_id column entirely if you no longer have a Teacher table), then you should be able to drop the Teacher table assuming no more foreign keys are referencing the Student table.
You should code your laravel migrations in a way, so you can revert it all back, under down() method.
Sometimes you get stuck, in a way that, migrate or migrate:rollback command produces an error.
Then you should modify your db structure, by hand (using mysql command, workbench, or any other sql tools), to bring your migrations to working again...
And finally targetting your question...
You cannot create table and add foreign constraints in one commit to db, so in order, to do that, you need to add new declaration in your migration up() like Table:... after Schema:create... and add your foreign keys here. Remember to do the opposite in down() method...

Laravel - add foreign key on existing table with data

I have existing table objects with data. Now I need to add new table named holdings and add a relation from objects to holdings table. In the migration file, I print this:
$table->foreign('holding_id')->references('id')->on('holdings')->onDelete("NO ACTION");
and get this error when trying to migrate
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update
a child row: a foreign key constraint fails (`kolomnaoffice`.`#sql-f10_126`
CONSTRAINT `objects_holding_id_foreign` FOREIGN KEY (`holding_id`)
REFERENCES `holdings` (`id`) ON DELETE NO ACTION) (SQL: alter table `objects` add constraint
`objects_holding_id_foreign` foreign key (`holding_id`) references `holdings`
(`id`) on delete NO ACTION)
I have correct database structure (both InnoDB), the fields exist and have correct type (int). The only thing different is that the table objects is filled with data, and table holdings is new and empty.
The holding_id column should be unsigned
Create a new migration file and migrate it, migration code should be like this :
Schema::table('objects', function (Blueprint $table) {
$table->integer('holding_id')->unsigned()->change();
$table->foreign('holding_id')->references('id')->on('holdings');
});
The change() method is called to change the structure of existing column.
It's not necessary to call onDelete("NO ACTION") method.
Thanks Mohammad but this solution didn't work for me as I am Laravel 5.4 and have different case here that my other table is already exists, Here what I found may it help some one.
Schema::table('objects', function (Blueprint $table) {
$table->integer('holding_id')->unsigned()->index()->nullable();
$table->foreign('holding_id')->references('id')->on('holdings');
});
with index() and nullable() it made the trick.
Edit
No need for index() it just need to be nullable()
To adding a foreign key, first make sure your column is marked as unsigned.
Just add a line before your line:
$table->integer('holding_id')->unsigned();
$table->foreign('holding_id')->references('id')->on('holdings')->onDelete("NO ACTION");
If you have a large table, say 1Million+ records, they I guess the best plan of operation is to:
Create a field with unsigned int datatype
Make sure new insertions to the table will follow to add value to the column. So change your insert queries accordingly
Create a queue to update older records and run it
After the the queue finishes, convert the field into foreign key

"General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys

Essentially, I am having the same issue as this guy, minus the table prefix. Because I have no table prefix, his fix does not work. http://forums.laravel.com/viewtopic.php?id=972
I am trying to build a table using Laravel's Schema Builder like this:
Schema::create('lessons', function($table)
{
$table->increments('id');
$table->string('title')->nullable();
$table->string('summary')->nullable();
$table->timestamps();
});
Schema::create('tutorials', function($table)
{
$table->increments('id');
$table->integer('author');
$table->integer('lesson');
$table->string('title')->nullable();
$table->string('summary')->nullable();
$table->string('tagline')->nullable();
$table->text('content')->nullable();
$table->text('attachments')->nullable();
$table->timestamps();
});
Schema::table('tutorials', function($table)
{
$table->foreign('author')->references('id')->on('users');
$table->foreign('lesson')->references('id')->on('lessons');
});
The issue is, when I run this code (in a /setup route), I get the following error:
SQLSTATE[HY000]: General error: 1005 Can't create table 'tutorials.#sql-2cff_da' (errno: 150)
SQL: ALTER TABLE `tutorials` ADD CONSTRAINT tutorials_author_foreign FOREIGN KEY (`author`) REFERENCES `users` (`id`)
Bindings: array (
)
Based on posts around the web and the limited documentation available on how to setup Laravel's Eloquent relationships, I'm not sure what I'm doing wrong...
users already exists and it does have an id field that is auto_increment. I am also setting up my models with the proper relationships (belongs_to and has_many), but as far as I can tell this is not the issue-- it's the database setup. The DB is InnoDB.
What exactly am I doing wrong with the foreign key?
I've been having the same problem. I just noticed the following note at the very bottom of the Laravel Schema docs:
Note: The field referenced in the foreign key is very likely an auto increment and therefore automatically an unsigned integer. Please make sure to create the foreign key field with unsigned() as both fields have to be the exact same type, the engine on both tables has to be set to InnoDB, and the referenced table must be created before the table with the foreign key.
For me, as soon as I set my foreign key fields as such:
$table->integer('author')->unsigned();
I had no problem.
EDIT: Also, make sure that the fields in the foreign table are already created, otherwise this may fail with the same error.
I'm not 100% sure if these are the reasons this is failing but a couple of pointers. If you're using an older version of mySQL as the database, the default table implementation is myISAM that does not support foreign key restraints. As your scripts are failing on the foreign key assignment, you are better off explicitly stating that you want INNODB as the engine using this syntax in Schema's create method.
Schema::create('lessons', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('title')->nullable();
$table->string('summary')->nullable();
$table->timestamps();
});
This should hopefully alleviate the problems you are having.
Also, whilst you can declare foreign keys as an afterthought, I create the foreign keys within the initial schema as I can do an easy check to make sure I've got the right DB engine set.
Schema::create('tutorials', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('author');
$table->integer('lesson');
$table->string('title')->nullable();
$table->string('summary')->nullable();
$table->string('tagline')->nullable();
$table->text('content')->nullable();
$table->text('attachments')->nullable();
$table->timestamps();
$table->foreign('author')->references('id')->on('users');
$table->foreign('lesson')->references('id')->on('lessons');
});
Hope this helps / solves your problem.
A Summary of the answers already listed, plus mine:
Foreign Keys generally require InnoDb, so set your default engine, or explicitly specify
$table->engine = 'InnoDB';
Foreign keys require the referenced table to exist. Make sure the referenced table is created in an earlier migration, prior to creating the key. Consider creating the keys in a separate migration to be sure.
Foreign Keys require the data type to be congruent. Check whether the referenced field is the same type, whether its signed or unsigned, whether it's length is the same (or less).
If you are switching between hand-coding migrations, and using generators, make sure you check the id type you are using. Artisan uses increments() by default but Jeffrey Way appears to prefer integer('id', true).
I ran into this issue too.
The solution I found is that the tables that contain the id that is being used a foreign id needs to be created before another table can reference it. Basically, you are creating a table and telling MySQL to reference another table's primary key but that table doesn't exist yet.
In your example, the author and lesson tables need to be created first.
The order in which the tables are created is dependent on artisan and the order you created your migration files.
My opinion would be to empty out your database of all the tables and change the timestamps in the migration file names (or delete them and recreate them in the correct order) so that your author and lesson tables are created before your tutorials table.
I received the same error because I forgot to set the table type to InnoDB on the referenced table:
$table->engine = 'InnoDB';
Laravel5, MySQL55, CentOS65
in my case the errors were same as this.
Error: [Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table
'nabsh.#sql-5b0_e' (errno: 121) (SQL: alter table usermeta add
constraint usermeta_uid_foreign foreign key (uid) ref erences
users (id) on delete cascade).
I found a good tip in this problem's approved answer:
ERROR: Error 1005: Can't create table (errno: 121)
Tip: You will get this message if you're trying to add a constraint with a name that's already used somewhere else.
in my case this error means the constraint which has been tried to add is already exists somewhere (but i couldn't see them anywhere).
I copied the output error query and execute it within sequel pro, then hopefully I saw the same error again. as the tip says I changed the constraint name to something else then it affected with no error so there's a problem with constraint name builder in laravel5 + MySQL55 + CentOS65.
Solution: try to rename constraints by sending the second parameter at foreign method in table schema.
Schema::table('tutorials', function($table)
{
$table->foreign('author')->references('id')->on('users');
$table->foreign('lesson')->references('id')->on('lessons');
});
to ->
Schema::table('tutorials', function($table)
{
$table->foreign('author', 'fk_tutorials_author')->references('id')->on('users');
$table->foreign('lesson', 'fk_tutorials_lesson')->references('id')->on('lessons');
});
i hope it helps. it works in my case
Easiest way is to disable foreign key checks:
DB::statement('set foreign_key_checks=0');
Schema::table( ... );
DB::statement('set foreign_key_checks=1');
This happened to me in Yii Framework 1.x migrations too. Turned out that
similarily to the Laravel solutions above it may be caused by a
wrong spelled (or not yet existing) table name
wrong spelled (or not yet existing) column name
duplicate foreign key name in the same database being used in different tables
when using foreign key-s make sure that your foreign key is unsigned. this worked for me
Here's what I do in Laravel 5:
// CREATING TABLE
Schema::create('your_table_name', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id'); // index field example sample
$table->string('field2'); // some varchar/string field sample
$table->integer('field3'); // some integer field sample
$table->integer('field_some_table_id')->unsigned; //for field that contains foreign key constraint
});
// FOREIGN KEY CONSTRAINT
Schema::table('stock', function ($table) {
$table->foreign('field_some_table_id')->references('id')->on('some_table')->onDelete('cascade')->onUpdate('cascade');
});
That's all for the conclusion, and it works for me.
You have to give the integer an unsigned flag in Laravel 5.4, like this:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('post_id');
$table->text('title');
$table->text('text');
$table->integer('employee_post_id_number')->unsigned();
$table->foreign('employee_post_id_number')->references
('employee_id_number')->on('employees');
$table->timestamps();
});
}
Basically, you get this error because the migration command creates tables in an order which does not match the FK reference you are providing for tables.
Like if you want to create an FK which should refer to the id in users table then users table must exist.
In your example, the author and lesson tables need to be created first.
So, I solved this by creating the tables (one by one) in such order, where I can successfully refer the FK to an existing table. So that Php Artisan Migration cannot decide the order.
Another solution is, you can simply rename the tables or the timestamps provided by migration command .
By using:
$table->unsignedInteger('author');
instead of:
$table->integer('author');
the problem will be solved.
The problem is that integer generates an int(11) variable while you need an int(10) variable. unsignedInteger will make it for you.
One of the reasons for this error can be the time and date creation of the migration files. For example , if we have tasks which belongs to some tasks groups, and there is references like:
"create_tasks_table
$table->id();
$table->string('task_name');
$table->integer('task_group')->unsigned();
$table->foreign('task_group')
->references('id')->on('tasks_groups')->onDelete('cascade');
$table->longText('task_desc');...."
it is important to create migration file for tasks_groups first (in the name of file we can see the time and date of creation) and than we should create tasks which belongs to some tasks_groups
also it is better to form the migration files with relations like this:
enter codeOne of the reasons for this error can be the time and date creation of the migration files. For example , if we have tasks which belongs to some tasks groups, and there is references like:
"create_tasks_table
$table->id();
$table->string('task_name');
$table->integer('task_group')->unsigned();
$table->foreign('task_group')
->references('id')->on('tasks_groups')->onDelete('cascade');
$table->longText('task_desc');...."
it is important to create migration file for tasks_groups first (in the name of file we can see the time and date of creation) and than we should create tasks which belongs to some tasks_groups
also
migration table should look like this
`use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTasksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tasks_groups', function (Blueprint $table) {
$table->increments('id');
$table->string('group_name');
$table->string('slug');
$table->timestamps();
});
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('task_name');
$table->integer('task_group')->unsigned();
$table->foreign('task_group')
->references('id')->on('tasks_groups')->onDelete('cascade');
$table->longText('task_desc');
$table->string('izvrsioc');
$table->string('ulogovani_rukovodioc');
$table->date('time_finishingtask');
$table->string('prioritet_izrade')->default('');
$table->string('file_1')->nullable();
$table->string('file_path1')->nullable();
$table->string('file_2')->nullable();
$table->string('file_path2')->nullable();
$table->string('file_3')->nullable();
$table->string('file_path3')->nullable();
$table->longText('dodatni_komentar');
$table->boolean('zavrsen_task')->default(false);
$table->boolean('otkazan_task')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('tasks');
Schema::dropIfExists('tasks_groups');
}
}`
it is better if there is relation
I was facing this problem, I just solved it this way
Add ->unsigned() with any column you add to represent a relationship
example:
errorr
$table->integer('lesson');
right is
$table->integer('lesson')->unsigned();