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

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.

Related

MySQL trying to restore two foreign keys returns errors

I have this scenario: I have those two tables:
CREATE TABLE sample_A (
ID bigint(20) UNSIGNED NOT NULL,
product varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE sample_B (
ID bigint(20) UNSIGNED NOT NULL,
ref_id_sample_A_id bigint(20) UNSIGNED NULL,
ref_id_sample_A_ref_id bigint(20) UNSIGNED NULL,
document_name varchar(300) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
and I was trying to restore a foreign key between ref_id_sample_A_id of table sample_B and ID of table sample_A but executing this instruction:
ALTER TABLE sample_B
ADD CONSTRAINT fk_sample_B_ref_sample_A_id
FOREIGN KEY (ref_id_sample_A_id)
REFERENCES sample_A(ID);
I obtain this error:
#1823 - Failed to add the foreign key constraint 'k3/fk_sample_B_ref_sample_A_id' to system tables
but I have no other foreign keys settled, neither informations if I query this:
SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
AND TABLE_NAME = 'sample_B';
I get empty result, and table simple_A is not a system table.... what I should do? Thanks in advance to all!
Cheers
I tested your sample using MySQL 8.0.26, and got this error:
ERROR 1822 (HY000): Failed to add the foreign key constraint. Missing index for constraint 'fk_sample_B_ref_sample_A_id' in the referenced table 'sample_A'
This means the referenced column, sample_A.ID, is not valid as the referenced column of a foreign key, because it is not part of a key in that table.
The referenced column must be part of a key, and ideally should be a PRIMARY KEY or UNIQUE KEY.
You did not define ID or any other column as the PRIMARY KEY for the table sample_A.
Solved right 2 sec ago anyway ... had to export dump data of the table, drop the table and recreate the table with all constraints in CREATE TABLE instruction then re-import all dump data and it worked. Thanks anyway to everyone #nbk and #Bill Karwin! :-)

Foreign key constraint is incorrectly formed (MariaDB)

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.

MySQL Cannot Add Foreign Key Constraint

So I'm trying to add Foreign Key constraints to my database as a project requirement and it worked the first time or two on different tables, but I have two tables on which I get an error when trying to add the Foreign Key Constraints.
The error message that I get is:
ERROR 1215 (HY000): Cannot add foreign key constraint
This is the SQL I'm using to create the tables, the two offending tables are Patient and Appointment.
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE SCHEMA IF NOT EXISTS `doctorsoffice` DEFAULT CHARACTER SET utf8 ;
USE `doctorsoffice` ;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`doctor`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`doctor` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`doctor` (
`DoctorID` INT(11) NOT NULL AUTO_INCREMENT ,
`FName` VARCHAR(20) NULL DEFAULT NULL ,
`LName` VARCHAR(20) NULL DEFAULT NULL ,
`Gender` VARCHAR(1) NULL DEFAULT NULL ,
`Specialty` VARCHAR(40) NOT NULL DEFAULT 'General Practitioner' ,
UNIQUE INDEX `DoctorID` (`DoctorID` ASC) ,
PRIMARY KEY (`DoctorID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`medicalhistory`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`medicalhistory` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`medicalhistory` (
`MedicalHistoryID` INT(11) NOT NULL AUTO_INCREMENT ,
`Allergies` TEXT NULL DEFAULT NULL ,
`Medications` TEXT NULL DEFAULT NULL ,
`ExistingConditions` TEXT NULL DEFAULT NULL ,
`Misc` TEXT NULL DEFAULT NULL ,
UNIQUE INDEX `MedicalHistoryID` (`MedicalHistoryID` ASC) ,
PRIMARY KEY (`MedicalHistoryID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`Patient`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Patient` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`Patient` (
`PatientID` INT unsigned NOT NULL AUTO_INCREMENT ,
`FName` VARCHAR(30) NULL ,
`LName` VARCHAR(45) NULL ,
`Gender` CHAR NULL ,
`DOB` DATE NULL ,
`SSN` DOUBLE NULL ,
`MedicalHistory` smallint(5) unsigned NOT NULL,
`PrimaryPhysician` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`PatientID`) ,
UNIQUE INDEX `PatientID_UNIQUE` (`PatientID` ASC) ,
CONSTRAINT `FK_MedicalHistory`
FOREIGN KEY (`MEdicalHistory` )
REFERENCES `doctorsoffice`.`medicalhistory` (`MedicalHistoryID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_PrimaryPhysician`
FOREIGN KEY (`PrimaryPhysician` )
REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`Appointment`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Appointment` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`Appointment` (
`AppointmentID` smallint(5) unsigned NOT NULL AUTO_INCREMENT ,
`Date` DATE NULL ,
`Time` TIME NULL ,
`Patient` smallint(5) unsigned NOT NULL,
`Doctor` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`AppointmentID`) ,
UNIQUE INDEX `AppointmentID_UNIQUE` (`AppointmentID` ASC) ,
CONSTRAINT `FK_Patient`
FOREIGN KEY (`Patient` )
REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_Doctor`
FOREIGN KEY (`Doctor` )
REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`InsuranceCompany`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`InsuranceCompany` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`InsuranceCompany` (
`InsuranceID` smallint(5) NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(50) NULL ,
`Phone` DOUBLE NULL ,
PRIMARY KEY (`InsuranceID`) ,
UNIQUE INDEX `InsuranceID_UNIQUE` (`InsuranceID` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `doctorsoffice`.`PatientInsurance`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`PatientInsurance` ;
CREATE TABLE IF NOT EXISTS `doctorsoffice`.`PatientInsurance` (
`PolicyHolder` smallint(5) NOT NULL ,
`InsuranceCompany` smallint(5) NOT NULL ,
`CoPay` INT NOT NULL DEFAULT 5 ,
`PolicyNumber` smallint(5) NOT NULL AUTO_INCREMENT ,
PRIMARY KEY (`PolicyNumber`) ,
UNIQUE INDEX `PolicyNumber_UNIQUE` (`PolicyNumber` ASC) ,
CONSTRAINT `FK_PolicyHolder`
FOREIGN KEY (`PolicyHolder` )
REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FK_InsuranceCompany`
FOREIGN KEY (`InsuranceCompany` )
REFERENCES `doctorsoffice`.`InsuranceCompany` (`InsuranceID` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
USE `doctorsoffice` ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
To find the specific error run this:
SHOW ENGINE INNODB STATUS;
And look in the LATEST FOREIGN KEY ERROR section.
The data type for the child column must match the parent column exactly. For example, since medicalhistory.MedicalHistoryID is an INT, Patient.MedicalHistory also needs to be an INT, not a SMALLINT.
Also, you should run the query set foreign_key_checks=0 before running the DDL so you can create the tables in an arbitrary order rather than needing to create all parent tables before the relevant child tables.
I had set one field as "Unsigned" and other one not. Once I set both columns to Unsigned it worked.
Engine should be the same e.g. InnoDB
Datatype should be the same, and with same length. e.g. VARCHAR(20)
Collation Columns charset should be the same. e.g. utf8
Watchout: Even if your tables have same Collation, columns still could have different one.
Unique - Foreign key should refer to field that is unique (usually primary key) in the reference table.
Try to use the same type of your primary keys - int(11) - on the foreign keys - smallint(5) - as well.
Hope it helps!
Confirm that the character encoding and collation for the two tables is the same.
In my own case, one of the tables was using utf8 and the other was using latin1.
I had another case where the encoding was the same but the collation different. One utf8_general_ci the other utf8_unicode_ci
You can run this command to set the encoding and collation for a table.
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
I hope this helps someone.
To set a FOREIGN KEY in Table B you must set a KEY in the table A.
In table A:
INDEX id (id)
And then in the table B,
CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)
I had same problem and the solution was very simple.
Solution : foreign keys declared in table should not set to be not null.
reference : If you specify a SET NULL action, make sure that you have not declared the columns in the child table as NOT NULL. (ref
)
Check following rules :
First checks whether names are given right for table names
Second right data type give to foreign key ?
Please ensure that both the tables are in InnoDB format. Even if one is in MyISAM format, then, foreign key constraint wont work.
Also, another thing is that, both the fields should be of the same type. If one is INT, then the other should also be INT. If one is VARCHAR, the other should also be VARCHAR, etc.
I faced the issue and was able to resolve it by making sure that the data types were exactly matching .
I was using SequelPro for adding the constraint and it was making the primary key as unsigned by default .
Check the signing on both your table columns. If the referring table column is SIGNED, the referenced table column should be SIGNED too.
My problem was that I was trying to create the relation table before other tables!
So you have two ways to fix it:
change the order of MSQL commands
run this before your queries:
SET foreign_key_checks = 0;
NOTE: The following tables were taken from some site when I was doing
some R&D on the database. So the naming convention is not proper.
For me, the problem was, my parent table had the different character set than that of the one which I was creating.
Parent Table (PRODUCTS)
products | CREATE TABLE `products` (
`productCode` varchar(15) NOT NULL,
`productName` varchar(70) NOT NULL,
`productLine` varchar(50) NOT NULL,
`productScale` varchar(10) NOT NULL,
`productVendor` varchar(50) NOT NULL,
`productDescription` text NOT NULL,
`quantityInStock` smallint(6) NOT NULL,
`buyPrice` decimal(10,2) NOT NULL,
`msrp` decimal(10,2) NOT NULL,
PRIMARY KEY (`productCode`),
KEY `productLine` (`productLine`),
CONSTRAINT `products_ibfk_1` FOREIGN KEY (`productLine`) REFERENCES `productlines` (`productLine`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Child Table which had a problem (PRICE_LOGS)
price_logs | CREATE TABLE `price_logs` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`productCode` varchar(15) DEFAULT NULL,
`old_price` decimal(20,2) NOT NULL,
`new_price` decimal(20,2) NOT NULL,
`added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `productCode` (`productCode`),
CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
);
MODIFIED TO
price_logs | CREATE TABLE `price_logs` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`productCode` varchar(15) DEFAULT NULL,
`old_price` decimal(20,2) NOT NULL,
`new_price` decimal(20,2) NOT NULL,
`added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `productCode` (`productCode`),
CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
One additional cause of this error is when your tables or columns contain reserved keywords:
Sometimes one does forget these.
If you are getting this error with PhpMyAdmin, disable foreign key checks before importing the SQL file.
For me the target table was blocking the foreign key.
I had to set Auto-Increment (AI) on the table the Foreign-Key was pointing to.
I had a similar error in creating foreign key in a Many to Many table where the primary key consisted of 2 foreign keys and another normal column. I fixed the issue by correcting the referenced table name i.e. company, as shown in the corrected code below:
create table company_life_cycle__history -- (M-M)
(
company_life_cycle_id tinyint unsigned not null,
Foreign Key (company_life_cycle_id) references company_life_cycle(id) ON DELETE CASCADE ON UPDATE CASCADE,
company_id MEDIUMINT unsigned not null,
Foreign Key (company_id) references company(id) ON DELETE CASCADE ON UPDATE CASCADE,
activity_on date NOT NULL,
PRIMARY KEY pk_company_life_cycle_history (company_life_cycle_id, company_id,activity_on),
created_on datetime DEFAULT NULL,
updated_on datetime DEFAULT NULL,
created_by varchar(50) DEFAULT NULL,
updated_by varchar(50) DEFAULT NULL
);
I had similar error with two foreign keys for different tables but with same key names! I have renamed keys and the error had gone)
Had a similar error, but in my case I was missing to declare the pk as auto_increment.
Just in case it could be helpful to anyone
I got the same error. The cause in my case was:
I created a backup of a database via phpmyadmin by copying the whole database.
I created a new db with the same name the old db had und selected it.
I started an SQL script to create updated tables and data.
I got the error. Also when I disabled foreign_key_checks. Altough the database was completely empty.
The cause was: Since i used phpmyadmin to create some foreign keys in the renamed database - the foreign keys where created with a database name prefix but the database name prefix was not updated. So there were still references in the backup-db pointing to the newly created db.
My solution is maybe a little embarrassing and tells the tale of why you should sometimes look at what you have in front of you instead of these posts :)
I had ran a forward engineer before, which failed, so that meant that my database already had a few tables, then i have been sitting trying to fix foreign key contraints failures trying to make sure that everything was perfect, but it ran up against the tables previously created, so it was to no prevail.
In my case, there was a syntax error which was not explicitly notified by MySQL console upon running the query. However, SHOW ENGINE INNODB STATUS command's LATEST FOREIGN KEY ERROR section reported,
Syntax error close to:
REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8
I had to leave a whitespace between REFERENCES and role to make it work.
For me it was - you can't omit prefixing the current DB table if you create a FK for a non-current DB referencing the current DB:
USE currrent_db;
ALTER TABLE other_db.tasks ADD CONSTRAINT tasks_fk FOREIGN KEY (user_id) REFERENCES currrent_db.users (id);
If I omit "currrent_db." for users table, I get the FK error. Interesting that SHOW ENGINE INNODB STATUS; shows nothing in this case.
My Solution!!
If we want to have column1 of table1 as a foreign key of table2, then column1 should be a key of table1.
For example, consider we have departments table, which has dept_id column.
Now let's say we have another table named employees which has emp_dept_id column.
If we want to use the dept_id column of the department table as a foreign key for the emp_dept_id column of emp, then the dept_id of department table SHOULD ATLEAST BE a key if not a primary key.
So make sure that dept_id of depratment is either a primary key or a unique key before using it as a foreign key for another table.
I had this same issue then i corrected the Engine name as Innodb in both parent and child tables and corrected the reference field name
FOREIGN KEY (c_id) REFERENCES x9o_parent_table(c_id)
then it works fine and the tables are installed correctly. This will be use full for someone.

mysql alter int column to bigint with foreign keys

I want to change the datatype of some primary-key columns in my database from INT to BIGINT. The following definition is a toy-example to illustrate the problem:
CREATE TABLE IF NOT EXISTS `owner` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `thing_id` (`thing_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
DROP TABLE IF EXISTS `thing`;
CREATE TABLE IF NOT EXISTS `thing` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
ALTER TABLE `owner`
ADD CONSTRAINT `owner_ibfk_1` FOREIGN KEY (`thing_id`) REFERENCES `thing` (`id`);
Now when i try to execut one of the following commands:
ALTER TABLE `thing` CHANGE `id` `id` BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE `owner` CHANGE `thing_id` `thing_id` BIGINT NOT NULL;
i'm running into an error
#1025 - Error on rename of './debug/#[temp-name]' to './debug/[tablename]' (errno: 150)
SHOW INODB STATUS outputs:
LATEST FOREIGN KEY ERROR
------------------------
120126 13:34:03 Error in foreign key constraint of table debug/owner:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
CONSTRAINT "owner_ibfk_1" FOREIGN KEY ("thing_id") REFERENCES "thing" ("id")
I'm guessing that the foreign key definition blocks changing the column type on either side. The naive approach to solve this problem would be to delete the foreign key definitions, alter the columns and re-define the foreign keys. is there a better solution?
Even with SET foreign_key_checks = 0, you can't alter the type of the constraint column.
From MySQL doc : http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
However, even if foreign_key_checks = 0, InnoDB does not permit the creation of a foreign key constraint where a column references a nonmatching column type.
So, I agree with the comment of Devart. Just drop it and create it again.
I could suggest you to rename such fields in GUI tool - dbForge Studio for MySQL (free trial edition):
Just select the field you want to rename in the Database Explorer, click on Refactoring->Rename command, enter new name in openned window, and press OK, it will rename the field and recreate all foreign keys automatically.
Even though you changed the column size of id and thing_id, the raw data in the rows is still 4 byte integers instead of 8 byte integers. But you can convert the data.
Try this solution instead. I had to do something similar recently on a large data set, converting INT columns to BIGINT when the data set threatened to grow too large.
ALTER TABLE `owner`
DROP FOREIGN KEY `owner_ibfk_1`;
ALTER TABLE `thing` CHANGE `id` `id` BIGINT NOT NULL AUTO_INCREMENT;
ALTER TABLE `owner` CHANGE `thing_id` `thing_id` BIGINT NOT NULL;
UPDATE `thing` SET `id` = CAST(`id` AS UNSIGNED INTEGER);
UPDATE `owner` SET `thing_id` = CAST(`thing_id` AS UNSIGNED INTEGER);
-- Now the data are BIGINTs; re-create the foreign key constraint
ALTER TABLE `owner`
ADD CONSTRAINT `owner_ibfk_1` FOREIGN KEY (`thing_id`) REFERENCES `thing` (`id`);
I had a similar problem the solution is the change clause:
ALTER TABLE table_name CHANGE id id BIGINT(20) NOT NULL AUTO_INCREMENT;
That worked for me.

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.