MySQL #1215 - Cannot add foreign key constraint [duplicate] - php

I am trying to import a .sql file and its failing on creating tables.
Here's the query that fails:
CREATE TABLE `data` (
`id` int(10) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`value` varchar(15) NOT NULL,
UNIQUE KEY `id` (`id`,`name`),
CONSTRAINT `data_ibfk_1` FOREIGN KEY (`id`) REFERENCES `keywords` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I exported the .sql from the same database, I dropped all the tables and now im trying to import it, why is it failing?
MySQL: Can't create table './dbname/data.frm' (errno: 150)

From the MySQL - FOREIGN KEY Constraints Documentation:
If you re-create a table that was dropped, it must have a definition that conforms to the foreign key constraints referencing it. It must have the correct column names and types, and it must have indexes on the referenced keys, as stated earlier. If these are not satisfied, MySQL returns Error 1005 and refers to Error 150 in the error message, which means that a foreign key constraint was not correctly formed. Similarly, if an ALTER TABLE fails due to Error 150, this means that a foreign key definition would be incorrectly formed for the altered table.

Error 150 means you have a problem with your foreign key. Possibly the key on the foreign table isn't the exact same type?

You can get the actual error message by running SHOW ENGINE INNODB STATUS; and then looking for LATEST FOREIGN KEY ERROR in the output.
Source: answer from another user in a similar question

Data types must match exactly. If you are dealing with varchar types, the tables must use the same collation.

I think all these answers while correct are misleading to the question.
The actual answer is this before you start a restore, if you're restoring a dump file with foreign keys:
SET FOREIGN_KEY_CHECKS=0;
because naturally the restore will be creating some constraints before the foreign table even exists.

In some cases, you may encounter this error message if there are different engines between the relating tables. For example, a table may be using InnoDB while the other uses MyISAM. Both need to be same

Error no. 150 means a foreign key constraint failure. You are probably creating this table before the table the foreign key depends on (table keywords). Create that table first and it should work fine.
If it doesn't, remove the foreign key statement and add it after the table is created - you will get a more meaningful error message about the specific constraint failure.

There are quite a few things that can cause errno 150, so for people searching this topic, here is what I think is a close to exhaustive list (source Causes of Errno 150):
For errno 150 or errno 121, simply typing in SHOW ENGINE INNODB STATUS, there is a section called "LATEST FOREIGN KEY ERROR". Under that it will give you a very helpful error message, which typically will tell you right away what is the matter. You need SUPER privileges to run it, so if you don't have that, you'll just have to test out the following scenarios.
1) Data Types Don't Match: The types of the columns have to be the same
2) Parent Columns Not Indexed (Or Indexed in Wrong Order)
3) Column Collations Don't Match
4) Using SET NULL on a NOT NULL Column
5) Table Collations Don't Match: even if the column collations match, on some MySQL versions this can be a problem.
6) Parent Column Doesn't Actually Exist In Parent Table. Check spelling (and perhaps a space at the beginning or end of column)
7) One of the indexes on one of the columns is incomplete, or the column is too long for a complete index. Note that MySQL (unless you tweak it) has a maximum single column key length of 767 bytes (this corresponds to a varchar(255) UTF column)
In case you get an errno 121, here are a couple of causes:
1) The constraint name you chose is already taken
2) On some systems if there is a case difference in your statement and table names. This can bite you if you go from one server to another that have different case handling rules.

Sometimes MySQL is just super stupid - i can understand the reason cause of foreign-keys.. but in my case, i have just dropped the whole database, and i still get the error... why? i mean, there is no database anymore... and the sql-user i'm using has no access to any other db's on the server... i mean, the server is "empty" for the current user and i still get this error? Sorry but i guess MySQL is lying to me... but i can deal with it :) Just add these two lines of SQL around your fucky statement:
SET FOREIGN_KEY_CHECKS = 0;
# some code that gives you errno: 150
SET FOREIGN_KEY_CHECKS = 1;
Now the sql should be executed... If you really have a foreign-key problem, it would show up to you by the line where you will enable the checks again - this will fail then.. but my server is just quiet :)

usually, the mismatch between foreign key & primary key causes the
error:150.
The foreign key must have the same datatype as the primary key. Also, if the primary key is unsigned then the foreign key must also be unsigned.

I had same issue. It was related to table's column Collation and Character Set.
Make sure Character Set and Collation must be same for both columns on two tables. If you want to set a foreign key on that.
Example- If you put foreign key on userID column of userImage table referencing userID column of users table.Then Collation must be same that is utf8_general_ci and Character set utf8 for both columns of tables. Generally when you create a table mysql takes these two configuration from server settings.

After cruising through the answers above, and experimenting a bit, this is an effective way to solve Foreign Key errors in MySQL (1005 - error 150).
For the foreign key to be properly created, all MySQL asks for is:
All referenced keys MUST have either PRIMARY or UNIQUE index.
Referencing Column again MUST have identical data type to the Referenced column.
Satisfy these requirements and all will be well.

I experienced this error when have ported Windows application to Linux. In Windows, database table names are case-insensitive, and in Linux they are case-sensitive, probably because of file system difference. So, on Windows table Table1 is the same as table1, and in REFERENCES both table1 and Table1 works. On Linux, when application used table1 instead of Table1 when it created database structure I saw error #150; when I made correct character case in Table1 references, it started to work on Linux too. So, if nothing else helps, make you sure that in REFERENCES you use correct character case in table name when you on Linux.

Change the engines of your tables, only innoDB supports foreign keys

If the PK table is created in one CHARSET and then you create FK table in another CHARSET..then also you might get this error...I too got this error but after changing the charset to PK charset then it got executed without errors
create table users
(
------------
-------------
)DEFAULT CHARSET=latin1;
create table Emp
(
---------
---------
---------
FOREIGN KEY (userid) REFERENCES users(id) on update cascade on delete cascade)ENGINE=InnoDB, DEFAULT CHARSET=latin1;

This error can occur if two tables have a reference, for example, one table is Student and another table is Education, and we want the Education table to have a foreign key reference of Student table. In this instance the column data type for both tables should be same, otherwise it will generate an error.

In most of the cases the problem is because of the ENGINE dIfference .If the parent is created by InnoDB then the referenced tables supposed to be created by MyISAM & vice versa

In my case. I had problems with engine and charset because my Hosting server change settings and my new tables was MyISAM but my old tables are InnoDB. Just i changed.

Please make sure both your primary key column and referenced column have the same data types and attributes (unsigned, binary, unsigned zerofill etc).

A real edge case is where you have used an MySQL tool, (Sequel Pro in my case) to rename a database. Then created a database with the same name.
This kept foreign key constraints to the same database name, so the renamed database (e.g. my_db_renamed) had foreign key constraints in the newly created database (my_db)
Not sure if this is a bug in Sequel Pro, or if some use case requires this behaviour, but it cost me best part of a morning :/

The column of PARENT table to which you are referring to from child table has to be unique. If it is not, cause an error no 150.

I had the same error. In my case the reason for the error was that I had a ON DELETE SET NULL statement in the constraint while the field on which I put the constraint in its definition had a NOT NULL statement. Allowing NULL in the field solved the problem.

I faced this kind of issue while creating DB from the textfile.
mysql -uroot -padmin < E:\important\sampdb\createdb.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_absence.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_absence.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_absence.sql
I just wrote the above lines in Create.batand run the bat file.
My mistake is in the sequence order of execution in my sql files. I tried to create table with primary key and also foreign key. While its running it will search for the reference table but tables are not there.
So it will return those kind of error.
If you creating tables with foreign key then check the reference
tables were present or not. And also check the name of the reference
tables and fields.

I had a similar problem but mine was because i was adding a new field to an existing table that had data , and the new field was referencing another field from the parent table and also had the Defination of NOT NULL and without any DEFAULT VALUES. - I found out the reason things were not working was because
My new field needed to autofill the blank fields with a value from the parent table on each record, before the constraint could be applied. Every time the constraint is applied it needs to leave the Integrity of the table data intact. Implementing the Constraint (Foreign Key) yet there were some database records that did not have the values from the parent table would mean the data is corrupt so MySQL would NEVER ENFORCE YOUR CONSTRAINT
It is important to remember that under normal circumstances if you planned your database well ahead of time, and implemented constraints before data insertion this particular scenario would be avoided
The easier Approach to avoid this gotcha is to
Save your database tables data
Truncate the table data (and table artifacts i.e indexes etc)
Apply the Constraints
Import Your Data
I Hope this helps someone

Create the table without foreign key, then set the foreign key separately.

Perhaps this will help? The definition of the primary key column should be exactly the same as the foreign key column.

Make sure that the all tables can support foreign key - InnoDB engine

I had a similar problem when dumping a Django mysql database with a single table. I was able to fix the problem by dumping the database to a text file, moving the table in question to the end of the file using emacs and importing the modified sql dump file into the new instance.
HTH Uwe

I've corrected the problem by making the variable accept null
ALTER TABLE `ajout_norme`
CHANGE `type_norme_code` `type_norme_code` VARCHAR( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL

I got the same problem when executing a series of MySQL commands. Mine occurs during creating a table when referencing a foreign key to other table which was not created yet. It's the sequence of table existence before referencing.
The solution: Create the parent tables first before creating a child table which has a foreign key.

Related

MySQL Error: Table doesn't exist in engine, can't discard tablespace, can't create table with same name for a foreign key constraint

I'm fairly new to mysql and html/php.
This is the long, more in detail version, of my problem, I'll put a summary at the end of the post:
I've been developing a site in local using xampp, so I used phpmyadmin for the DDL part of development.
Problems started when in my php code I passed a variable from one page to another in an incorrect way it seems (this value should have been something like 0000000001 and instead it was 0). In this script, this value was used in an INSERT INTO query. Problem is that the value we're talking about was inserted in a column with a foreign key constraint, but this value didn't point to any primary key in the father table (I'm guessing this was the problem since this is where it all started going downhill). Suddenly the table in phpmyadmin was marked as "in use" and I started getting the error #1932 "table doesn't exist in engine". So I tried to drop it and discard tablespace: the DROP TABLE worked fine (the table disappear from the db view, even though it kept showing errno 1932), but I could not discard tablespace since it kept telling me that the table didn't exist. In mysql files I could see the .frm file gone, but not the .ibd. So I tried to delete it manually in order to be able to create this table once again (because if I tried to recreate it I was told to discard the tablespace first, but it's insane since I cannot discard it because I keep being told that the table does not exist). If I try to create again the table using the phpmyadmin UI I get the error #1005 that reference the error #150. So checking online I get the idea that I have to recreate the table exactly as it was, so from console I write down the CREATE TABLE query, including the foreign key constraint as shown in the "LATEST FOREIGN KEY ERROR" section of the error log, but instead I get the error #121.
SO, SUMMARIZING:
I want to make this table accessible to my code and myself again or create it again.
The table is marked in use and I can't access it.
If I try to drop it and discard tablespace I get error #1932.
If I try to recreate it I get errors because it already exixts, because I have to discard tablespace first or because I have a foreign key constraint incorrectly formed.
If I try to recreate it specifing the constraint I get an error because the constraint already exists.
This is the query I used to create the table specifing the constraint
CREATE TABLE `dbsmartcity`.`copertura` (
`Luogo` INT(10) UNSIGNED ZEROFILL NOT NULL ,
`Rete` INT(10) UNSIGNED ZEROFILL NOT NULL,
CONSTRAINT `copertura_ibfk_1` FOREIGN KEY (`Luogo`) REFERENCES `luoghi` (`IDLuogo`)
ON DELETE CASCADE ON UPDATE CASCADE
)
ENGINE = InnoDB DEFAULT CHARSET=utf8;
Yes, I have restarted MySQL.
Yup, I explicitly dropped the tablespace.
I would like to keep the remove/reinstall option as a last resort.
Sorry if I was not clear somewhere in this post. Please help me, my exam is near. Thanks a lot for your help.

Add a relation between table in PHPMyadmin

I want create a relation between different tables in phymyadmin with mysql.
I want to add cascade option but I don't always see the cascade option every time I add relation.
For example in first image when I relate usergroupid id in usergroup and users table there is not cascade option available. But as in second image when i relate invoice id in invoicedetails and tripmaster table I gets the cascade options availabale.
So I'm no able to understand why cascade option is not available every time.
There are several conditions that your tables and columns need to meet in order to create foreign key constraints.
One that you are missing in your example and that is visible from the screenshot, is the length of the integer value. They both need to have the same length (and sign...) so int(5) and int(11) are not compatible.
You also need indices on the columns, etc. see the manual on foreign key constraints for all requirements.
When you build relationships like this, the key and its matching foreign key must have exactly the same datatype.
So in your first example, the integers are of different sizes (int(5) and int(11) thus MySql cannot create the required constraints and you cannot enable cascade deletes or updates.
In your second example, its not clear from the screenshot but I assume that the datatypes match.
Also ensure that integer datatypes are both signed or unsigned. If one is signed and the other unsigned, you'll run into the same problem.

Doctrine with one field of the composite primary key to be auto generated

I currently have a table that has as primary key a composite value formed by id + foreign key. The id is auto-incremented and the foreign key references another table.
At the moment that I'm saving the data I only know about the foreign key value and I expect that the id returns to me from the database as an auto-increment number.
I understand that doctrine's does not support auto generation of id for a composite primary key so what can be done to allow with Doctrine to save the data and still have the auto-increment on part of the composite key.
Note, before submiting this question I had researched several other questions such as: Defining Composite Key with Auto Increment in MySQL and Doctrine: authorize NULL in a foreign composite key and I have also read Doctrine's documentation several times to see if I was missing something http://doctrine-orm.readthedocs.org/en/latest/tutorials/composite-primary-keys.html#use-case-1-dynamic-attributes
The main issue is that on Doctrine
Every entity with a composite key cannot use an id generator other than
“ASSIGNED”. That means the ID fields have to have their values set before
you call EntityManager#persist($entity).
To help with the issue here is an example of how the table is constructed:
create table composite_example (
id int(11) not null auto_increment,
fk_id int(11) not null,
a_prop varchar(20),
primary key (id, fk_id)
) engine=InnoDB default charset=utf8;
If I had to manually construct a MySQL query to insert into this table knowing the values of fk_id and a_prop I could do:
insert into composite_example (fk_id, a_prop) values (999, 'a_value');
And it would create a row with a proper value for id on the table.
How can I do the same behavior with Doctrine ? Does anyone knows any way or workaround to get the job done ?
There is no easy solution for this matter but here are a few options:
1) You can remove composite key and use UUIDs as keys. This is not an easy solution because it will affect how much of your code needs to be changed, how long it will take to do the migration and how it can affect performance.
2) The other option would be something that was suggested by the Doctrine community that can be used in other ORM's as well: you work with a sequencer. For this solution you will need to create a table where you will store an entity identifier and the next column will be the last value for that identifier.
Example:
Table sequencer
id | entity_name | entity_id
88 | customers | 77
The entity model would need to inform that the id is generated and on the pre-persist it will need to assign that id with a value that would come from the entity_id + 1 out of this table
select max(entity_id)+1 from sequencer where entity_name = 'customers';
This will cause 2 extra queries to be ran, one on the pre-persist and another on the post-persist which will update the sequencer table with the new value.
There are strategies to avoid concurrency on the sequencer table so it would always have the correct value and one of them is by locking the table o.0
3) You can write your own loaders and persister, but at this point you might be facing a change as big as the UUID implementation.
A lot of ORM's doesn't support this and if you are facing the same issue, you might have to consider one of the above.
Now, if you are working specifically with Doctrine I strongly suggest asking for help on the IRC channel. They were very helpful on providing me with some alternatives for this issue.

How to test tables linked with foreign keys?

I am working with mysql and codeigniter using the redbean ORM. After implementing a foreign key for many to many assosciation I got the following error when I run:
drop TABLE IF EXISTS `temp`
Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails thrown
I then entered SHOW ENGINE INNODB STATUS into phpmyadmin. The output includes:
LATEST FOREIGN KEY ERROR------------------------:  Cannot drop table `db1`.`temp`because it is referenced by `db1`.`temp_workers`.
In other words another table references the FK. For testing purposes I think the best thing to do is to drop all the associated tables and recreate them using the controller I'm testing. Is this the best way to go? I've tried:
drop TABLE IF EXISTS `temp` `temp_workers`
, but I'm still getting the above error, and the drop command does not work. Also:
truncate TABLE `temp`, `temp_workers`
gives:
You have an error in your SQL syntax
As mentioned in the comments you have to drop any tables with FK contraints to other tables, first, then you can drop the tables being linked to.
Example:
User
id: 1
name: Mike
Address
id: 1
user_id: 1 (FK constraint to User.id table.column)
address_1: 555 Main Street
This setup is a 1:1 relationship (more on data normalization), where one user row can reference one address row, and because the address row is dependent upon the existence of the user row, if you attempt to remove the user row, you will see the errors you mentioned.
But if you drop the Address table first, everything works as expected because the User table is not FK to any other table.
Ensuring referential integrity within your schema ensures you do not end up with orphaned rows, which will permeate throughout your data driven application.
You could also issue the following commands:
SET foreign_key_checks = 0;
# Do Stuff
SET foreign_key_checks = 1;
But I would strongly advise against this, as you could break the referential integrity of your data, and end up in a real mess. I've seen someone do this in an enterprise environment and it took them weeks to clean it up. However, if you are doing this STRICTLY for testing purposes; like writing unit tests, or just learning, and you didn't want to drop the tables every time, you could do this:
# Because we remove the foreign key check, we can truncate in any order
SET foreign_key_checks = 0;
TRUNCATE TABLE user;
TRUNCATE TABLE address;
SET foreign_key_checks = 1;
Proper schema design using foreign key constraints goes along way to building a good foundation for any data driven application. It will take time to get your head around when to use, and how to construct foreign key constraints, but over time you will begin to understand. A good way to get started is to download an open source project like magento, wordpress, or vbulletin and take a look at their schemas. You can even introspect these schemas using MySQL workbench and view their Entity-Relationship Diagrams (ERDs), which will visually demonstrate links between tables.

MySQL: How to update foreign key field, and create a relationship, after table values have been set with default values?

I have a teamnews Table:
And another table called team:
The values in teamnews table are predetermined before a user signs into the site.
Lets say when a user(teamName) signs in I want to update the teamID row where NewsID = 1
And create a relationship so that if I eventually delete the user(teamName) the teamID value in the teamNews table is reset to zero.
Is this possible?
Please bare in mind I am using phpMyAdmin, so I am not entirely familiar with advanced SQL terms.
When I try to do this I get and error:
Here's the error:
You need to specify a FOREIGN KEY. You can add it in by running this command:
ALTER TABLE teamnews
ADD CONSTRAINT fk_teamID
FOREIGN KEY (TeamID)
REFERENCES team (teamID)
ON DELETE SET NULL;
This sets up a formal relationship between the tables using the foreign key. The ON DELETE SET NULL is the part that is important to you. This says that whenever any item in the referenced table (team in this instance) is deleted, then all rows in this table that had that team id should set that field to null — exactly what you're looking for.
Be aware that this will only work if you are using the InnoDB database engine (not the MyISAM engine). You can probably change that through phpmyadmin somewhere (I'm not familiar with phpmyadmin so I can't help you on the details).
Also be aware that for this to work, MySQL must actually be able to "SET NULL" -- the field containing the foreign key with this constraint can't be set to "NOT NULL" or it will fail with an error saying to "check data type".

Categories