I'm creating a new table who will have relationships with an existing table. The new table has a column user_id which references a userid column on another table (the ID of a user in the users table).
I have the following table:
CREATE TABLE `ads` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-- Other columns...
)
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci
ENGINE = InnoDB;
Adding a referencing column
ALTER TABLE `ads` ADD `user_id` INT(11) NOT NULL
Which references the following column
CREATE TABLE users
(
userid INT(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
-- Other irrelevant fields...
);
And finally my key definition:
ALTER TABLE `ads` ADD CONSTRAINT ads_user_id_foreign FOREIGN KEY (`user_id`) REFERENCES `users` (`userid`)
But for some reason I still get an error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL: alter table `ads` add constraint ads_user_id_foreign foreign key (`user_id`) references `users` (`userid`))
Note: I don't believe it's of much relevance, but I'm using Laravel's query builder to create the new table. I'm getting these queries from PHPStorm's Copy DDL feature to show you the equivalent "vanilla MySQL query".
Okay, so I figured it out. In my case, I also needed to change the engine, charset, and collation of the users table. IT was set to MyISAM, latin1, and latin1_swedish_ci, respectively.
I did say I was using Laravel, so here are the statements I used to fix that:
DB::statement('ALTER TABLE users CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci');
DB::statement('ALTER TABLE users ENGINE=InnoDB;');
I'll try to leave a generic answer here for those who find this post in the future.
Things to check when foreign keys aren't working:
1. Make sure that the columns are setup identically
I use an IDE (PHPStorm) that allows me to get some DDL from existing tables. I paste that somewhere and find the columns in question to see if they're defined correctly.
2. Check table status for inconsistencies
You can check all tables' statuses with SHOW TABLE STATUS. You'll get a result that looks like this (obviously this depends on your IDE):
Make sure that engine and collation match in both tables
• If you notice that your engine is wrong (it should be InnoDB), you can fix it with
ALTER TABLE <table_name> ENGINE=InnoDB;
• If you notice that your collation is wrong, you can fix it with
alter table <table_name> convert to character set <CHARSET> collate <COLLATION>;
(where a charset might be utf8 and a collation might be utf8_unicode_ci)
Related
I am making two tables and I want the personOne column from table b to reference the person column on table a, but for some reason it doesn't work.
I have the below code as an example:
create table a(
person varchar(20),
cost varchar(10) not Null
)character set latin1
collate latin1_general_ci;
create table b(
personOne varchar(20),
personTwo varChar(2) not null,
key person_index (personOne),
CONSTRAINT C FOREIGN KEY (personOne) references a(person)
) engine=InnoDB default charset=latin1;
It is telling me an error:
Error Code: 3780. Referencing column 'personOne' and referenced column 'person' in foreign key constraint 'C' are incompatible.
I tried to to set table a engine to InnoDB, but that didn't work. I researched the problem more but couldn't figure out how to fix it.
The two columns must have the same collation. I'm guessing your table b is using the default collation for old versions of MySQL, which is latin1_swedish_ci.
You might like to review this checklist for foreign keys: https://stackoverflow.com/a/4673775/20860
I suggest the best choice is to declare both a and b tables with character set utf8mb4 and collation utf8mb4_unicode_520_ci if your version of MySQL is new enough to support it.
Here I had to first define a primary key in a:
ALTER TABLE a ADD PRIMARY KEY (person);
And pass the COLLATE value of a:
CREATE TABLE b (
...
)ENGINE=InnoDB
DEFAULT CHARSET=latin1
COLLATE latin1_general_ci;
I got the same error code.
Although it may not help your situation, my problem was;
The ID column in all my tables is set as INT UNSIGNED but I was using a foreign key of type INT signed.
I have this Query:
CREATE TABLE `team` (
`id` int(11) NOT NULL
);
/* SQL Error (1215): Cannot add foreign key constraint */
which clearly does not contain a foreign key declaration. So all answers I am finding online are not for me. The reason this error occurs must have been related to a MySQL caching issue. Because the table existed previously and I deleted it. Thus, renaming the table name in the create table command to teams creates the table just fine.
My question is, where does mysql store this cache and how can I delete it. In information_schema I cannot find it. in information_schema.INNODB_TABLES the table is no longer listed.
Update 1
Before deleting the table team it was created with foreign keys, with:
CREATE TABLE `team` (
`id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`is_verified` tinyint(1) NOT NULL,
`uuid` char(36) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '(DC2Type:guid)',
`foreign_uuid` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `team`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `UNIQ_C4E0A61FD17F50A6` (`uuid`);
But now the error occurs with just the first (very simple) query.
Update 2
I tried
mysql> FLUSH LOGS;
mysql> RESET MASTER;
to no avail.
Update 3
After restarting the mysql service the error changed more concrete to:
CREATE TABLE `team` (
`id` int(11) NOT NULL
);
/* SQL Error (1822): Failed to add the foreign key constraint. Missing index for constraint 'FK_6C66F57B296CD8AE' in the referenced table 'team' */
When you are disabling foreign_key_checks, it allows you to all kind of things, especially
Setting foreign_key_checks to 0 also affects data definition statements: [...] DROP TABLE drops tables that have foreign keys that are referred to by other tables.
That's what you (or someone you can blame) did.
When you recreate the table, you need to make sure that the referenced constraints are technically valid (even if you keep foreign_key_checks disabled):
When re-creating a table that was dropped, an error is returned if the table definition does not conform to the foreign key constraints referencing the table.
The exact error you get depends a bit on what version you are using, for MySQL 5.5 it would be Error Code: 1005. Can't create table 'tablename' (errno: 150), since MySQL 5.6, the error message is
SQL Error (1215): Cannot add foreign key constraint
So the problem here is that another table is referencing your table with a foreign key constraint, but the new table definition doesn't fit.
A fairly easy way to find the culprit is to use show engine innodb status, it will contain, amongst other things, useful details in the LATEST FOREIGN KEY ERROR section, including the foreign key definition and the name of table. Alternatively, and especially if you suspect to have more than one foreign key problem, have a look at How do I see all foreign keys to a table or column? (which is where MySQL stores that information, although it's not a cache that you can clear).
While you can include the referenced column into your new table, it doesn't look as if you intend to honor that constraint anymore, so you probably need to drop the referencing foreign key (or table).
I have two tables:
CREATE TABLE first_table(
my_id TEXT(6) NOT NULL,
content VARCHAR(30) NOT NULL,
PRIMARY KEY(my_id(6))
) Engine=InnoDB charset utf8mb4 collate utf8mb4_general_ci;
CREATE TABLE second_table(
another_id TEXT(6) NOT NULL,
my_id TEXT(6) NOT NULL,
another_content VARCHAR(30) NOT NULL,
PRIMARY KEY(another_id(6))
) Engine=InnoDB charset utf8mb4 collate utf8mb4_general_ci;
But in the second table I can't create a foreign key that references the first table, first I've tried this:
ALTER TABLE second_table
ADD FOREIGN KEY (my_id)
REFERENCES first_table(my_id)
ON DELETE CASCADE ON UPDATE CASCADE;
And got this error:
ERROR 1170 (42000): BLOB/TEXT column 'my_id' used in key specification without a key length
MariaDB [base_ventas]>
So, I tried to specify the key length like this:
ALTER TABLE second_table
ADD FOREIGN KEY (my_id(6))
REFERENCES first_table(my_id)
ON DELETE CASCADE ON UPDATE CASCADE;
And I got this error:
ERROR 1005 (HY000): Can't create table `base_ventas`.`#sql-1a08_23c`
(errno: 150 "Foreign key constraint is incorrectly formed")
This doesn't happen with numeric ids but I need to have string type ids, it can be done, or I am missing something?
I am sorry to inform that it's not possible.
According to MySql Documentation:
Index prefixes on foreign key columns are not supported. One
consequence of this is that BLOB and TEXT columns cannot be included
in a foreign key because indexes on those columns must always include
a prefix length.
And MariaDB Documentation:
The columns in the child table must be an index, or the leftmost part
of an index. Index prefixes are not supported (thus, TEXT and BLOB
columns cannot be used as foreign keys)
If you really need alphanumeric keys, consider using something like char or varchar instead. The easiest, most generic, and most common approach is to use numeric keys, such as INT.
This question already has answers here:
MySQL Creating tables with Foreign Keys giving errno: 150
(20 answers)
Closed 9 years ago.
I am using MySQL 5 to try and create two tables. Here are the two tables:
DROP TABLE IF EXISTS `users` ;
CREATE TABLE IF NOT EXISTS `users` (
`username` VARCHAR(50) not null ,
`password` VARCHAR(50) not null,
`enabled` boolean not null,
`accountNonExpired` boolean not null,
`accountNonLocked` boolean not null,
`credentialsNonExpired` boolean not null,
PRIMARY KEY (`username`)
) ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
DROP TABLE IF EXISTS `authorities` ;
create table IF NOT EXISTS `authorities` (
`username` VARCHAR(50) not null ,
`authority` varchar(50) not null,
foreign key (`username`) references `users` (`username`),
unique index authorities_idx_1 (username, authority)
) engine = InnoDb;
When I try to execute this statement, the users table is created but then I get the error:
Error Code: 1005
Can't create table 'dental.authorities' (errno: 150)
I am not seeing why this foreign key fails when the two referenced columns are identical. Is there
Foreign keys require both keys to have the same character set.
Add
DEFAULT CHARACTER SET = utf8;
to your second table CREATE instruction.
Edit: Oh boy looks like I'm late to the party.
Depending on your server version and settings, you might need to add
DEFAULT CHARACTER SET = utf8
to the CREATE TABLE statement for "authorities". That will match the character set of the referenced table.
check out following points:
i think DEFAULT CHARACTER SET = utf8; not provided to second table
1. The two tables must be ENGINE=InnoDB. (can be others: ENGINE=MyISAM
works too)
2. The two tables must have the same charset.
3. The PK column(s) in the parent table and the FK column(s) must be
the same data type.
4. The PK column(s) in the parent table and the FK column(s), if they
have a define collation type, must have the same collation type;
5. If there is data already in the foreign key table, the FK column
value(s) must match values in the parent table PK columns.
6. And the child table cannot be a temporary table.
Hope this helps.
I'm creating a few simple tables and I can't get passed this foreign key error and I'm not sure why. Here's the script below.
create TABLE Instructors (
ID varchar(10),
First_Name varchar(50) NOT NULL,
Last_Name varchar(50) NOT NULL,
PRIMARY KEY (ID)
);
create table Courses (
Course_Code varchar(10),
Title varchar(50) NOT NULL,
PRIMARY KEY (Course_Code)
);
create table Sections (
Index_No int,
Course_Code varchar(10),
Instructor_ID varchar(10),
PRIMARY KEY (Index_No),
FOREIGN KEY (Course_Code) REFERENCES Courses(Course_Code)
ON DELETE cascade
ON UPDATE cascade,
FOREIGN KEY (Instructor_ID) REFERENCES Instructors(ID)
ON DELETE set default
);
Error Code: 1005. Can't create table '336_project.sections' (errno: 150)
My data types seem identical and the syntax seems correct. Can anyone point out what I'm not seeing here?
I'm using MySQL Workbench 5.2
This error also occurs if you are relating columns of different types, eg. int in the source table and BigInt in the destination table.
If you're using the InnoDB engine, the ON DELETE SET DEFAULT is your problem. Here's an excerpt from the manual:
While SET DEFAULT is allowed by the MySQL Server, it is rejected as invalid by InnoDB. CREATE TABLE and ALTER TABLE statements using this clause are not allowed for InnoDB tables.
You can use ON DELETE CASCADE or ON DELETE SET NULL, but not ON DELETE SET DEFAULT. There's more information here.
You can run
SHOW ENGINE INNODB STATUS
to read the reason of the failure in a human readable format
e.g.
------------------------
LATEST FOREIGN KEY ERROR
------------------------
150331 15:51:01 Error in foreign key constraint of table foobar/#sql-413_81:
FOREIGN KEY (`user_id`) REFERENCES `foobar`.`users`(`id`) ON DELETE SET NULL ON UPDATE CASCADE:
You have defined a SET NULL condition though some of the columns are defined as NOT NULL.
In order to create a FOREIGN KEY with reference to another table, the keys from both tables should be PRIMARY KEY and with the same datatype.
In your table sections, PRIMARY KEY is of different datatype i.e INT but in another table, it's of type i.e VARCHAR.
It may also be the case if you are not specifying the ON DELETE at all but are trying to reference a MYISAM table from InnoDB table:
CREATE TABLE `table1`(
`id` INT UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MYISAM CHARACTER SET UTF8;
CREATE TABLE `table2`(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`table1_id` INT UNSIGNED NOT NULL,
`some_value` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_table1_id`(`table1_id`),
CONSTRAINT FOREIGN KEY (`table1_id`) REFERENCES `table1`(`id`)
) ENGINE=INNODB CHARACTER SET UTF8;
The above will throw errno 150. One need to change the first table to InnoDB too for this to work.
It is failing on the
ON DELETE set default
I have not come across that before and I am not seeing it in the manuals either ( but then it is late )
Update
just seen this in the manual
While SET DEFAULT is allowed by the MySQL Server, it is rejected as
invalid by InnoDB. CREATE TABLE and ALTER TABLE statements using this
clause are not allowed for InnoDB tables.
I guess you may be using InnoDB tables ?
For completeness sake - you will also get this error if you make a foreign reference to a table that isn't defined at the time;
Here Problem is in database engine ( table1 MYISAM and table2 ENGINE).
To set FOREIGN KEYs,
Both table must be in same ENGINE and same charset.
PK column in parent and FK column must be in same data type and same collation type.
Hope you got an idea.
Make sure that table type is InnoDB, MyISAM does not support foreign key, afaik.