I'm hitting a bug where I can't run some laravel migrations as I'm getting the error (errno: 150 "Foreign key constraint is incorrectly formed")
I have read around the subject and can't seem to work out what my problem is. The foreign key I wish to set is an unsigned integer. The data-types are the same across both tables, etc.
Here is my migration:
Schema::create('sample_migration', function (Blueprint $table) {
$table->increments('id');
$table->integer('subject_id')->unsigned();
$table->string('1');
$table->string('2');
$table->integer('3');
$table->string('4');
$table->integer('5');
$table->integer('type')->unsigned();
$table->timestamps();
$table->foreign('type')->references('subject_type')->on('some_table');
});
On some_table I have subject_type as an unsigned integer. Both use the same collation and encoding.
If I add a unique() flag on the relevant fields then the migration runs smoothly, but I don't want this as there will be duplicate data.
Is there something that I am missing?
I assume you are trying to add a foreign key to a non-unique column.
There are 2 ways you can solve this depending on your business logic.
Firstly you can opt to create a unique key on multiple columns and reference the same on sample_migration table.
Secondly you can make subject_type column as an index key like this
$table->integer('subject_type')->unsigned()->index();
This method still have foreign key to non unique column which I personally don't recommend as it may have bad consequences as stated here: https://stackoverflow.com/a/2179372/3929188
Related
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');
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
1215 - Cannot add foreign key constraint
PhpMyAdmin is giving me this error whenever I try to execute the following script:
It's self referencing, so it shouldn't have anything to do with its type and the syntax seems to be right, given the other examples on stackoverflow and MySQL's documentation.
Not sure if it'll help, but the code is a migration script generated by MySQL Workbench: Moving from Microsoft SQL to MySQL.
Does anyone have any clue as to what might be causing this error?
CREATE TABLE IF NOT EXISTS `clinicalTrialEmployee` (
clinicalTrialId INT NOT NULL,
employeeId INT NOT NULL,
clinicalTrialEmployeeTypeId INT NULL,
roleName VARCHAR(50) CHARACTER SET 'utf8' NULL,
PRIMARY KEY (clinicalTrialId, employeeId),
CONSTRAINT FK_clinicalTrialEmployee_clinicalTrialEmployee
FOREIGN KEY (clinicalTrialId , employeeId)
REFERENCES clinicalTrialEmployee (clinicalTrialId , employeeId)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
What in the world does it even mean for a field to reference itself? That's a new one on me. I've had one column on a table be a foreign key for another column on the same table, but I've never heard of a column referencing itself. Do you understand what such a foreign key constraint is supposed to accomplish? I mean that quite literally: what is the actual point of this? Most likely the answer is that MySQL doesn't support this. There are many variations between different "dialects" of SQL, and just because an export from a Microsft SQL server created this SQL doesn't mean that MySQL supports either the syntax or the principle in general.
Someone else might come along with more information, but in the meantime I wouldn't try to just reproduce this exactly as is. I would figure out what it was actually supposed to accomplish, figure out if that even still matters, and then find a way to do the equivalent in MySQL (if it is even possible).
Usually there is another field in the table to reference a related record. For instance, you may have a supervisor_id pointing to a supervisor employee that is also in the clinicalTrialEmployee table.
The way the foreign key is written now, it is just referencing itself, which becomes an infinite loop.
I created the database structure using MySQL workbench. When I do the forward engineer or synchronize model it displays some errors.
When I remove the foreign key or if I connect "INT" as a foreign key to the second table then it's working fine. But I want to use "Varchar(255)". Can't we use "Varchar(255)" as a foreign key? If so please help me to fix this error. I can't do forward engineer to this table.
Yes you can use varchar as foreign key.It is appropriate to add a unique index or a unique constraint to your table. However, your primary key should generally be some "meaningless" value, such as an auto-incremented number or a GUID.
I've a table CustomizationSet with the columns:
customization_set_guid (which is a non-nullable guid and also the primary key)
creator_account_guid
and a few others
And a table with existing data Registration with the columns:
registration_id (an int and the primary key)
customization_set_guid (also a guid (so a char(36)) which is nullable, and all entries are currently null)
and a few other columns
When I try and run
ALTER TABLE Registration ADD FOREIGN KEY
(
customization_set_guid
) REFERENCES CustomizationSet (
customization_set_guid
);
in MySQL Workbench, it gives the error 1050Table '.\dbname\registration' already exists.
If I try to use the UI to add the foreign keys with the Foreign Keys tab of the Alter Table Dialog, and choose CustomizationSet as the referenced table, it doesn't let me choose customization_set_guid in the list of columns.
I'm really not sure why it won't let me add this foreign key. I've just successfully created foreign keys between tables I just added. The Registration table has existed for awhile...
I got the same error, and it was due to the fact that the foreign key already existed. What you want is just to add the constraint:
ALTER TABLE Registration
ADD CONSTRAINT idx_Registration_CustomizationSet
FOREIGN KEY (customization_set_guid)
REFERENCES CustomizationSet(customization_set_guid);
It looks like there is a bug report for this at MySQL located here:
MySQL Bug 55296
In the end, I guess they upgraded their server and it fixed the issue. From reading it, I'm not sure though. They did have some workarounds like putting in constraint names/changing them. If you think this is the same, I would request that the bug is reopened.
At one point, they mention the types didn't match and workbench was responding with the wrong error (it should have been an errno 150, or errno 121). You can see the causes for those errors here:
MySQL Foreign Key Errors and Errno 150
So a team member figured this out. The one table was set with the type utf8_general, and another was set to the type default. I didn't think this was an issue, since the default is utf8_general, but apparently mysql just looks at the type names and not the underlying type.
I got the same error, and since my case wasnt mentioned yet, i ll post this answer and hopefully it may save somebody's time!
My two tables engines, where different.
The one was InnoDB, and the other MyIsam.
To change the engine of a table:
choose table, hit alter table, and then to hit that double arrow at
the right-most of the Workbench(so it will point upwards).
Now change the engine!
Check the Storage Engine type for CustomizationSet table.
I had a same issue but i could solve it by changing engine type to
InnoDB , because few types don't support foreign key constraints.
Not sure about the table already existing, but the reason it's not letting you choose the column you want is most likely due to the columns not being the same type. Check to ensure they are both the same type, same length, and have all the same options.
I'm not sure if it's a typo but shouldn't be
ALTER TABLE Registration ADD FOREIGN KEY
(
customization_set_guid
) REFERENCES CustomizationSet (
customization_set_guid
);
be something like
ALTER TABLE Registration ADD FOREIGN KEY
customization_set_guid_fk (customization_set_guid)
REFERENCES CustomizationSet (customization_set_guid);
I had a similar problem and in the end it was a problem of Integrity Constraint.
The Foreign Key column was referencing a foreign column that didnt
exist.
Try run the following to test whether this is the case:
select r.customization_set_guid, c.customization_set_guid
from Registration r
right join CustomizationSet c
on
r.customization_set_guid = c.customization_set_guid
where isnull(c.customization_set_guid);
When using MysqlWorkbench the error is misleading. My issue was that I was trying to add a foreign key constraint on table that already had rows and one of the rows was empty (did not meet the FK constraint. Instead of complaining that constraint will fail if applied, MysqlWorkbench reported that table exists.
Removing the offending row fixed (or adding and constraint acceptable value to the field) solved the problem.