MySQL problem to add FOREIGN KEY? - mysql

I've got 2 innodb tables, here it is with SHOW CREATE TABLE query:
| top_menu | CREATE TABLE `top_menu` (
`t_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`menu_photo` char(128) NOT NULL,
`title` char(64) NOT NULL,
`atdc_id` int(10) unsigned NOT NULL,
`menu_order` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 |
| attendance | CREATE TABLE `attendance` (
`atdc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` char(128) NOT NULL,
`content` text,
`price` double NOT NULL,
`sale_percent` tinyint(3) unsigned NOT NULL,
`atdc_order` int(10) unsigned NOT NULL,
`s_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`atdc_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
The result of doing, normal adding FOREIGN KEY is an error.
Query: ALTER TABLE top_menu ADD FOREIGN KEY (atdc_id) REFERENCES attendance(atdc_id);
Error: ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (database., CONSTRAINT #sql-a36a_5c109d2_ibfk_1 FOREIGN KEY (atdc_id) REFERENCES attendance (atdc_id))
What should I do with this? It always worked for me well.

It seems that some top_menu rows have the atdc_id which does not exist in attendance table.

in complement to #Alexey Smirnoff answer:
When are you adding the foreign key? If it is from a restore script ensure you have the attendance table content loaded before you perform this query. Or delay foreign key checks to the end of the process.
If you want to find which rows are giving you this problem run this query:
Select a.*
from top_menu a
left join attendance b
on a.atdc_id = b.atdc_id
where b.atdc_id IS NULL;

Related

Foreign Key Constraints In MySQL DB Gives Error

am trying to implement a foreign key constraint but the mysql keeps giving me an error There are two tables "groups" table and "members" table.I have a many to many relationship between these tables and therefore used a third table called "members_groups" table for the many to many relationship. Note: "groups" and "members" tables have been created and contain data but I now want to add the "members_groups" table. Below are the sql codes:
Below is the script for the members table.
CREATE TABLE IF NOT EXISTS `members` (
`member_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`email` varchar(50) NOT NULL,
`password` char(128) NOT NULL,
`salt` char(128) NOT NULL,
`group_id` bigint(64) unsigned NOT NULL,
`perm_override_add` bigint(64) unsigned NOT NULL,
`perm_override_remove` bigint(64) unsigned NOT NULL,
PRIMARY KEY (`member_id`),
KEY `member_id` (`member_id`)
) ENGINE=InnoDB;
script for the groups table
CREATE TABLE IF NOT EXISTS `groups` (
`group_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group_name` varchar(50) NOT NULL,
`permission` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`group_id`)
) ENGINE=InnoDB
script for the members_groups table
CREATE TABLE members_groups
(
member_id INT(11) NOT NULL ,
group_id INT(10) NOT NULL ,
PRIMARY KEY (member_id, group_id),
FOREIGN KEY (member_id) REFERENCES members(member_id) ON UPDATE CASCADE,
FOREIGN KEY (group_id) REFERENCES groups(group_id) ON UPDATE CASCADE
) ENGINE = InnoDB
This is the error I get from the mysql admin console.
Thanks.
You need to make the type same in your table. In your groups table you have defined
`group_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
whereas in your members_groups table it is
group_id INT(10) NOT NULL ,
Try to make the change like
CREATE TABLE members_groups
(
member_id INT(11) NOT NULL ,
group_id INT(10) unsigned NOT NULL , --The datatype should be same as group_id in `groups` table
PRIMARY KEY (member_id, group_id),
FOREIGN KEY (member_id) REFERENCES members(member_id) ON UPDATE CASCADE,
FOREIGN KEY (group_id) REFERENCES `groups`(group_id) ON UPDATE CASCADE
) ENGINE = InnoDB;
SQL FIDDLE DEMO

mysql InnoDB: FOREIGN KEY constraint performance

I have the following InnoDB tables:
CREATE TABLE `vehicle` (
`ID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(50) DEFAULT NULL,
`Model` varchar(100) DEFAULT NULL,
`Engine_Type` varchar(70) DEFAULT NULL,
`Construction_From` date DEFAULT NULL,
`Construction_To` date DEFAULT NULL,
`Engine_Power_KW` mediumint(8) unsigned DEFAULT NULL,
`Engine_Power_HP` mediumint(8) unsigned DEFAULT NULL,
`CC` mediumint(8) unsigned DEFAULT NULL,
`TTC_TYP_ID` int(11) unsigned DEFAULT NULL,
`Vehicle_Type` tinyint(1) DEFAULT NULL,
`ID_Body_Type` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=49407 DEFAULT CHARSET=utf8;
CREATE TABLE `part` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`ID_Brand` smallint(5) unsigned DEFAULT NULL,
`Code_Full` varchar(50) DEFAULT NULL,
`Code_Condensed` varchar(50) DEFAULT NULL,
`Ean` varchar(50) DEFAULT NULL COMMENT 'The part barcode.',
`TTC_ART_ID` int(11) unsigned DEFAULT NULL COMMENT 'TecDoc ID.',
`ID_Product_Status` tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `TTC_ART_ID_UNIQUE` (`TTC_ART_ID`),
UNIQUE KEY `ID_Brand_Code_Full_UNIQUE` (`ID_Brand`,`Code_Full`)
) ENGINE=InnoDB AUTO_INCREMENT=3732260 DEFAULT CHARSET=utf8;
CREATE TABLE `vehicle_part` (
`ID_Vehicle` mediumint(8) unsigned NOT NULL,
`ID_Part` int(11) unsigned NOT NULL,
PRIMARY KEY (`ID_Vehicle`,`ID_Part`),
KEY `fk_vehicle_part_vehicle_id_vehicle_idx` (`ID_Vehicle`),
KEY `fk_vehicle_part_part_id_part_idx` (`ID_Part`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Table vehicle has about 45.000 records, table part has about 3.500.000 records and table vehicle_part has approximately 100.000.000 records.
Creating the secondary indexes for vehicle_part did not take too long, about 30 min for both.
What I cannot do though is create the foreign key constraints: for example
ALTER TABLE `vehicle_part`
ADD CONSTRAINT `fk_vehicle_part_vehicle_id_vehicle`
FOREIGN KEY (`ID_Vehicle`)
REFERENCES `vehicle` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
takes ages to complete. I understand the table is rebuilt since it consumes a lot of disk space. What can I do to improve the performance?
If I create the table with the fk constraints and then add the records the insert process in vehicle_part also takes ages (about 3 days).
I am using a laptop with 4GB RAM.
EDIT 12/01/2016
The answer given by Drew helped a lot in improving the performance dramatically. I changed every script using SELECT ... INTO outfile and then LOAD DATA INFILE from the exported csv file. Also sometimes before LOAD DATA INFILE dropping the indexes and recreating them after the load proccess saves even more time. There is no need to drop the fk constraints just the secondary indexes.
If you know your data is pristine from an FK perspective, then establish your structure without secondary indexes as suggested in comments, but with the FK in the schema yet with FK checks temporarily disabled.
Load your data. If external data, certainly do it with LOAD DATA INFILE.
After your data is loaded, turn on FK checks. And establish secondary indexes with Alter Table.
Again, going with the assumption that your data is clean. There are other ways of proving that after-the-fact for the risk-adverse.
create table student
( id int auto_increment primary key,
sName varchar(100) not null
-- secondary indexes to be added later
);
create table booksAssigned
( id int auto_increment primary key,
studentId int not null,
isbn varchar(20) not null,
constraint foreign key `fk_b_s` (studentId) references student(id)
-- secondary indexes to be added later
);
insert booksAssigned(studentId,isbn) values (1,'asdf'); -- Error 1452 as expected
set FOREIGN_KEY_CHECKS=0; -- turn FK checks of temporarily
insert booksAssigned(studentId,isbn) values (1,'asdf'); -- Error 1452 as expected
set FOREIGN_KEY_CHECKS=1; -- succeeds despite faulty data
insert booksAssigned(studentId,isbn) values (2,'38383-asdf'); -- Error 1452 as expected
As per op comments, how to drop auto-generated index in referencing table after initial schema creation:
mysql> show create table booksAssigned;
| booksAssigned | CREATE TABLE `booksassigned` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`studentId` int(11) NOT NULL,
`isbn` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_b_s` (`studentId`),
CONSTRAINT `booksassigned_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `student` (`id`)
) ENGINE=InnoDB |
mysql> set FOREIGN_KEY_CHECKS=0;
Query OK, 0 rows affected (0.00 sec)
mysql> drop index `fk_b_s` on booksAssigned;
Query OK, 0 rows affected (0.49 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show create table booksAssigned;
| booksAssigned | CREATE TABLE `booksassigned` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`studentId` int(11) NOT NULL,
`isbn` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `booksassigned_ibfk_1` FOREIGN KEY (`studentId`) REFERENCES `student` (`id`)
) ENGINE=InnoDB |
Further links
Temporarily disable foreign keys
A Rolando Answer

What is the cause for MySQL: Errorno 150

Can someone please explain the cause for the following error, 'Can't create table 'Activities' (errno: 150)'
I'm under the understading that the data types and lengths have to be the same, does is have anything to do with the auto increment?
Create Table `LinkMemberActivity` (
`LinkID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`MID` int(11) unsigned NOT NULL,
`AID` int(11) unsigned NOT NULL,
PRIMARY KEY (`LinkID`),
FOREIGN KEY (`MID`) REFERENCES Members(`MID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;
)
CREATE TABLE `Activities` (
`AID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(25) DEFAULT NULL,
`MaxCapacity` int(25) DEFAULT NULL,
`StartTime` time DEFAULT NULL,
`EndTime` time DEFAULT NULL,
PRIMARY KEY (`AID`),
FOREIGN KEY (`AID`) REFERENCES LinkMemberActivity(`AID`))
ENGINE=InnoDB DEFAULT CHARSET=latin1 );
You are trying to make a primary key column a foreign key dependent field. This is not only unusual but makes no sense in a datamodel, unless it is part of a composite key. Common practice has a column foreign key dependent on another tables primary key. Not sure what reasons you have for the way you designed your datamodel this way, but you can fix this problem by creating a not null autoincrement column named ID and make this column the primary key. Next remove autoincrement from aid.

#1215 - Cannot add foreign key constraint

I have this weird issue with creation of foreign key.
Given 2 tables:
CREATE TABLE IF NOT EXISTS `groupdeals` (
`groupdeals_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(10) NOT NULL,
`merchant_id` int(11) NOT NULL,
`minimum_qty` int(11) NOT NULL,
`maximum_qty` int(11) NOT NULL,
`target_met_email` int(11) NOT NULL,
`coupon_barcode` text NOT NULL,
`coupon_merchant_address` int(11) NOT NULL,
`coupon_merchant_contact` int(11) NOT NULL,
`coupon_expiration_date` date DEFAULT NULL,
`coupon_price` int(11) NOT NULL,
`coupon_fine_print` int(11) NOT NULL,
`coupon_highlights` int(11) NOT NULL,
`coupon_merchant_description` int(11) NOT NULL,
`coupon_business_hours` int(11) NOT NULL,
`coupon_merchant_logo` int(11) NOT NULL,
`coupon_additional_info` text NOT NULL,
`position` int(11) NOT NULL,
PRIMARY KEY (`groupdeals_id`),
KEY `groupdeals_id` (`groupdeals_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and
CREATE TABLE IF NOT EXISTS `groupdeals_coupons` (
`coupon_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`groupdeals_id` int(11) NOT NULL,
`order_item_id` int(11) NOT NULL,
`coupon_code` varchar(255) NOT NULL DEFAULT '',
`redeem` varchar(255) NOT NULL DEFAULT '',
`status` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`coupon_id`),
KEY `fk_groupdeals_coupons_groupdeals1_idx` (`groupdeals_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I try to add foreign key by executing following query:
ALTER TABLE `groupdeals_coupons`
ADD CONSTRAINT `fk_groupdeals_coupons_groupdeals1`
FOREIGN KEY (`groupdeals_id`)
REFERENCES `groupdeals` (`groupdeals_id`)
ON DELETE CASCADE
ON UPDATE CASCADE;
All I receive is Error:
#1215 - Cannot add foreign key constraint
Show engine innodb status
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2013-08-17 13:47:49 7ff5dbb2c700 Error in foreign key constraint of table xxxxx/#sql-7b23_282b1a:
FOREIGN KEY (`groupdeals_id`)
REFERENCES `groupdeals` (`groupdeals_id`)
ON DELETE CASCADE
ON UPDATE CASCADE:
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.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
The column groupdeals.groupdeals_id is a primary one, so I really can't understand where is a problem :|
Any hints?
Server type: Percona Server
Server version: 5.6.11-rc60.3-log - Percona Server (GPL), Release 60.3
Your types are inconsistent:
CREATE TABLE IF NOT EXISTS `groupdeals` (
`groupdeals_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
CREATE TABLE IF NOT EXISTS `groupdeals_coupons` (
[...]
`groupdeals_id` int(11) NOT NULL,
As you will see, in one table you have int unsigned. In the other, just int.
BTW, I noticed you have two keys on groupdeals_id. Is that on purpose?
CREATE TABLE IF NOT EXISTS `groupdeals` (
[...]
PRIMARY KEY (`groupdeals_id`),
KEY `groupdeals_id` (`groupdeals_id`)
Try these two steps to add foreign key:-
alter table groupdeals_coupons modify groupdeals_id int unsigned not null default 0;
ALTER TABLE groupdeals_coupons ADD CONSTRAINT fk_groupdeals_coupons_groupdeals1 FOREIGN KEY (groupdeals_id) references groupdeals (roupdeals_id);

on duplicate key update fails with error "Cannot add or update a child row"

I have a table with a compound primary key "name" and "id". The fields are actually "name","id","phone","amount","units","alias". I have the query
insert into MyTable (name,id,phone,amount) select "henry" as name, id,phone,amount from anotherTable
on duplicate key update phone=values(phone),amount=values(amount).
MySQL spits the following error:
Cannot add or update a child row: a foreign key constraint fails.
BTW, "id" is a foreign key.
Any help?
as requested below, the schema for other table is
CREATE TABLE `otherTable` (
`otherId` int(11) NOT NULL AUTO_INCREMENT,
`DOBId` int(11) NOT NULL,
`bankAccount` int(11) DEFAULT NULL,
`partialAmount` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`notes` varchar(299) DEFAULT NULL,
`latitude` decimal(8,5) DEFAULT NULL,
`longitude` decimal(8,5) DEFAULT NULL,
PRIMARY KEY (`otherId `),
KEY `DOBId ` (`DOBId `),
KEY `bankAccount ` (`bankAccount `),
KEY `id ` (`id `)
) ENGINE=InnoDB AUTO_INCREMENT=3305 DEFAULT CHARSET=utf8;
for myTable
CREATE TABLE `myTable` (
`name` int(11) NOT NULL,
`id` int(11) NOT NULL,
`appleNumber` int(11) DEFAULT NULL,
`amount` int(11) DEFAULT NULL,
`windowsNumber` int(11) DEFAULT NULL,
`phone` int(11) DEFAULT NULL,
`pens` int(11) DEFAULT NULL,
`pencils` int(11) DEFAULT NULL,
PRIMARY KEY (`name`,`id`),
KEY `id` (`id`),
CONSTRAINT `myTable_ibfk_1` FOREIGN KEY (`id`) REFERENCES `yet_another` (`id`)
The problem appears to be that the FK constraint you have on myTable is referencing the ids of yet_another, so when you are inserting ids from anotherTable you are breaking this FK constraint. Chances are there are ids in anotherTable that do not exist in yet_another table.
Understand this is a shot in the dark, based on the abstracted schema you posted. If you want a more solid answer, I'd have to see the actual schema.
The on duplicate key applies to the primary key. I take it you're using innodb. This is failing on a foreign key constraint. Which values of you table MyTable are foreign keys? Please post the create statement for the table that shows all keys and constraints for more detailed help.
Just a guess, but for grins I'm betting it's a column that's not in the insert that is a foreign key not allowing a null value.