Foreign key constraint is incorrectly formed (MariaDB) - mysql

I'm just trying to execute a MySQL file within MariaDB, but it gives me the following error: ERROR 1005 (HY000) at line 14: Can't create table roundcube.calendars (errno: 150 "Foreign key constraint is incorrectly formed")
That's the SQL query: https://pastebin.com/4FBA30JM
Unfortunately I can't post it here since it kinda messes up the formatting.

Here's your calendars table definition:
CREATE TABLE IF NOT EXISTS `calendars` (
`calendar_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`color` varchar(8) NOT NULL,
`showalarms` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY(`calendar_id`),
INDEX `user_name_idx` (`user_id`, `name`),
CONSTRAINT `fk_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;
I tested this out in a sandbox and the statement is fine. There's nothing wrong with it.
However, I don't see a users table in your linked code sample. Before you can create a table with a foreign key, the following must be true:
The referenced table (users in your case) must exist.
The referenced table must use the InnoDB storage engine.
The referenced column (user_id) must exist in the table.
The referenced column must have exactly the same data type as the foreign key column that references it. In your case, this is INT UNSIGNED (The integer length argument (10) is optional and may be different in the two tables).
The referenced column must be the leftmost column of a KEY. Ideally it should be the entire PRIMARY KEY or UNIQUE KEY, to be compatible with standard SQL. Technically, InnoDB also allows foreign keys to reference non-unique keys, but this is discouraged.
So you must have a table at least like the following already existing in your database:
CREATE TABLE `users` (
`user_id` int(10) UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_general_ci;
I had to create this table in my sandbox before your calendars table definition would work.

Related

How to set up the tables without errors in phpmyadmin? [duplicate]

When I execute the follow two queries (I have stripped them down to absolutely necessary):
mysql> CREATE TABLE foo(id INT PRIMARY KEY);
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE bar ( id INT, ref INT, FOREIGN KEY (ref) REFERENCES foo(id)) ENGINE InnoDB;
I get the following error:
ERROR 1005 (HY000): Can't create table './test/bar.frm' (errno: 150)
Where the **** is my error? I haven't found him while staring at this for half an hour.
From FOREIGN KEY Constraints
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 right column names and types,
and it must have indexes on the
referenced keys, as stated earlier. If
these are not satisfied, MySQL returns
error number 1005 and refers to error
150 in the error message.
My suspicion is that it's because you didn't create foo as InnoDB, as everything else looks OK.
Edit: from the same page -
Both tables must be InnoDB tables and they must not be TEMPORARY tables.
You can use the command SHOW ENGINE INNODB STATUS to get more specific information about the error.
It will give you a result with a Status column containing a lot of text.
Look for the section called LATEST FOREIGN KEY ERROR which could for example look like this:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
190215 11:51:26 Error in foreign key constraint of table `mydb1`.`contacts`:
Create table `mydb1`.`contacts` with foreign key constraint failed. You have defined a SET NULL condition but column 'domain_id' is defined as NOT NULL in ' FOREIGN KEY (domain_id) REFERENCES domains (id) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT contacts_teams_id_fk FOREIGN KEY (team_id) REFERENCES teams (id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT' near ' ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT contacts_teams_id_fk FOREIGN KEY (team_id) REFERENCES teams (id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT'.
To create a foreign key ,
both the main column and the reference column must have same definition.
both tables engine must be InnoDB.
You can alter the engine of table using this command , please take the backup before executing this command.
alter table [table name] ENGINE=InnoDB;
I had the same problem, for those who are having this also:
check the table name of the referenced table
I had forgotten the 's' at the end of my table name
eg table Client --> Clients
:)
Apart form many other reasons to end up with MySql Error 150 (while using InnoDB), One of the probable reason, is the undefined KEY in the create statement of the table containing the column name referenced as a foreign key in the relative table.
Let's say the create statement of master table is -
CREATE TABLE 'master_table' (
'id' int(10) NOT NULL AUTO_INCREMENT,
'record_id' char(10) NOT NULL,
'name' varchar(50) NOT NULL DEFAULT '',
'address' varchar(200) NOT NULL DEFAULT '',
PRIMARY KEY ('id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and the create syntax for the relative_table table where the foreign key constraint is set from primary table -
CREATE TABLE 'relative_table' (
'id' int(10) NOT NULL AUTO_INCREMENT,
'salary' int(10) NOT NULL DEFAULT '',
'grade' char(2) NOT NULL DEFAULT '',
'record_id' char(10) DEFAULT NULL,
PRIMARY KEY ('id'),
CONSTRAINT 'fk_slave_master' FOREIGN KEY ('record_id') REFERENCES 'master' ('record_id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
This script is definitely going to end with MySql Error 150 if using InnoDB.
To solve this, we need to add a KEY for the The column record_id in the master_table table and then reference in the relative_table table to be used as a foreign_key.
Finally, the create statement for the master_table, will be -
CREATE TABLE 'master_table' (
'id' int(10) NOT NULL AUTO_INCREMENT,
'record_id' char(10) NOT NULL,
'name' varchar(50) NOT NULL DEFAULT '',
'address' varchar(200) NOT NULL DEFAULT '',
PRIMARY KEY ('id'),
KEY 'record_id' ('record_id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I had very same problem and the reason was the "collation" of columns was different. One was latin1 while the other was utf8
This may also happen if you have not given correct column name after "references" keyword.

Mysql error 150 with creating a table that has a foreign key constraint

I am getting error 150 on the following create statement:
CREATE TABLE `lazarus`.`warehouses_devices` (
`parent_unit_id` INT UNSIGNED NULL DEFAULT NULL,
`child_unit_id` INT UNSIGNED NULL DEFAULT NULL,
`message_type` VARCHAR(255) NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`value` LONGTEXT NOT NULL,
INDEX `parent_unit_id` (`parent_unit_id` ASC),
INDEX `child_unit_id` (`child_unit_id` ASC),
INDEX `message_type` (`message_type` ASC),
INDEX `date` (`date` ASC),
CONSTRAINT `fk_parent_unit_id_unit_id`
FOREIGN KEY (`parent_unit_id`)
REFERENCES `lazarus`.`logs` (`unit_id`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci
And I am not sure why, I look up error 150 and it states that its foreign key issues and I am really confused as the reason isn't very clear.
The exact error is ERROR 1005: Can't create table 'lazarus.warehouses_devices' (errno: 150)
Considering that you already have a table created called logs
which has unit_id set as primary key. Most probably the error is causing due to datatype mismatch between referred column and referring column.
Then you probably need to check that the column parent_unit_id in warehouses_devices has the same data type as in logs (unit_id).
Make sure both in lazarus.warehouses_devices the parent_unit_id INT UNSIGNED
In logs table as well the unit_id must be INT UNSIGNED
Also, in your CREATE TABLE lazarus.warehouses_devices ( you are creating a constraint named
fk_parent_unit_id_unit_id. make sure you don't have another constraint with the same name already created in some other table.
According to the documentation:
InnoDB does not currently support foreign keys for tables with
user-defined partitioning. This means that no user-partitioned InnoDB
table may contain foreign key references or columns referenced by
foreign keys.
logs is partitioned, while warehouses_devices is not.

MySQL Errno 150

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.

Adding table with FOREIGN KEY to a MySQL database causes errno 150

I'm attemping to execute the following SQL and am receiving errno: 150 'cannot create table path_relations' in response. According to the MySQL documentation this is caused by my FOREIGN KEY restraints having issues. What am I doing wrong?
DROP TABLE IF EXISTS `paths`;
DROP TABLE IF EXISTS `path_relations`;
CREATE TABLE `paths` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `path_relations` (
`ancestor` int(11) NOT NULL DEFAULT '0',
`descendant` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY(`ancestor`, `descendant`),
FOREIGN KEY(`ancestor`) REFERENCES paths(`id`),
FOREIGN KEY(`descendant`) REFERENCES paths(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Here is a checklist for you, good luck ;)
1) type of foreign key source and reference fields must be identical
2) both source and reference fields must be unsigned
3) source field must be indexed
4) both tables must be InnoDB
Does it work if you make paths.id not unsigned?
UPDATED: In the first table you define your integer value as unsigned whilst in the second you haven't. The fields must be identical in structure to satisfy a foreign key.
Do you have any data in the table already? if so make sure that all records would satisfy the constraint. NULL values in the foreign keyed column will prevent this from working.

Foreign key between MySQL InnoDB tables not working...why?

I have the following tables:
specie (MyIsam)
image (InnoDB)
specie_map (InnoDB)
The specie_map table should map an image to a specie, and therefore has the following columns:
specie_id
image_id
Both are int 11, just like the id columns of the specie and image tables. I know I can't create a foreign key between specie_id and specie=>id, since the specie table is a MyIsam table. However, I would expect it to be possible to create a foreign key between image_id and image=>id.
I can create that foreign key and it will save it, however, the CASCADE action I have associated with it does not work. When I delete an image, it does not delete the specie_map entry that is associated with it. I would expect this to work, as this foreign key is between InnoDB tables. Both columns are indexed and of the same data type.
Is this a limitation of MySQL, or am I doing something else wrong?
Update: as requested hereby the table definitions. I have snipped unimportant columns:
-- ----------------------------
-- Table structure for `image`
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
`id` int(11) NOT NULL auto_increment,
`guid` char(36) default NULL,
`title` varchar(255) NOT NULL,
`description` text,
`user_id` int(11) NOT NULL,
`item_id` int(11) default NULL,
`date_uploaded` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_created` timestamp NOT NULL default '0000-00-00 00:00:00',
`date_modified` timestamp NOT NULL default '0000-00-00 00:00:00',
`status` enum('softdeleted','tobedeleted','active') default 'active',
PRIMARY KEY (`id`),
KEY `image_user` (`user_id`),
KEY `image_item` (`item_id`),
KEY `image_mod_by` (`moderated_by`),
CONSTRAINT `image_mod_by` FOREIGN KEY (`moderated_by`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `image_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='stores image data (not file data)';
-- ----------------------------
-- Table structure for `specie`
-- ----------------------------
DROP TABLE IF EXISTS `specie`;
CREATE TABLE `specie` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(256) NOT NULL,
`commonname` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
-- ----------------------------
-- Table structure for `specie_map`
-- ----------------------------
DROP TABLE IF EXISTS `specie_map`;
CREATE TABLE `specie_map` (
`id` int(11) NOT NULL auto_increment,
`image_id` int(11) NOT NULL,
`specie_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`karma` int(11) NOT NULL,
`date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `image_id` (`image_id`),
KEY `specie_id` (`specie_id`),
CONSTRAINT `specie_map_ibfk_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Foreign keys works only with InnoDb in mysql. MyISAM doesn't support them (the statements are ignored).
And is there any reason why you mix multiple DB engines?
I think you should post the exact DDL statements you used when you attempted to create these tables and the foreign key. Foreign keys between innodb tables work fine, but there are still a few things to look out for:
0) Both tables must be InnoDB. This was already highlighted by the other posters and this is probably the immediate cause of your problem.
1) the data type of the referencing columns (those that make up the foreign key) and their respective referenced columns should be the same. For example, you can't create a foreign key constrain on an INT UNSIGNED column to a plain INT column.
2) if the foreign key is created as part of the table DDL, be sure to put the foreign key definition in the constraints section, that is, below all column definitions. For example:
CREATE TABLE parent (
id int unsigned PRIMARY KEY
);
CREATE TABLE child (
parent_id int unsigned
, foreign key (parent_id)
references parent (id)
);
will work but this:
CREATE TABLE child (
parent_id int unsigned
foreign key references parent (id)
);
won't. It will fail silently because MySQL's parser ignores these types of constraint definitions even before InnoDB gets to create the table (silly, but that's how it is)
3) There must be an index over all the referenced columns. Usually the referenced columns will together make up a primary key or a unique constraint anyway, but it is your job to define this before defining the foreign key.
Final word of advice: if you think your DDL is ok but you still get an error when you execute it, for example like this:
ERROR 1005 (HY000): Can't create table 'test.child' (errno: 150)
Warning (Code 150): Create table 'test/child' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
Error (Code 1005): Can't create table 'test.child' (errno: 150)
Then these errors may still not reveal the true nature of the error (silly again, but that's how it is). To shed more light on it, run this command immediately after your attempt to create the foreign key:
SHOW ENGINE INNODB STATUS;
This will give you a bunch of status info, and one section there looks like this:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
120122 11:38:28 Error in foreign key constraint of table test/child:
foreign key (parent_id) references parent (id) ):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
As you can see, this gives a bit more information and reveals the true problem, namely "column types in the table and the referenced table do not match for constraint"
So please, post your actual DDL, I'm sure there is a problem in there somewhere.