Foreign key constraint fails even when data types are the same - mysql

I'm building a table with a two part foreign key that references a two part key in another table. It isn't working, and I can't see why because the data types line up.
Can't create table 'tsugi.video_comments' (errno: 150)
Here's the code I'm trying to run:
CREATE TABLE `video_comments` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`video_id` varchar(11) NOT NULL DEFAULT '',
`link_id` int(11) NOT NULL,
`videoTime` int(11) NOT NULL,
`comment` text NOT NULL,
`parent` int(11) unsigned DEFAULT NULL,
`private` tinyint(1) DEFAULT NULL,
`replies` int(11) unsigned DEFAULT '0',
`reports` int(11) DEFAULT '0',
`user_id` int(11) NOT NULL,
`displayname` varchar(2048) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `video_ibfk_1` (`link_id`),
KEY `video_ibfk_2` (`user_id`),
CONSTRAINT `video_comments_ibfk_1` FOREIGN KEY (`parent`) REFERENCES `video_comments` (`id`) ON DELETE CASCADE,
CONSTRAINT `video_ibfk_1` FOREIGN KEY (`link_id`) REFERENCES `lti_link` (`link_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `video_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `lti_user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `video_key` FOREIGN KEY (`link_id`, `video_id`) REFERENCES `video_ids` (`link_id`, `video_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=285 DEFAULT CHARSET=utf8;
The command runs successfully if I delete the last constraint, so that's where the problem is, not in the other constraints.
Here's the table it's referencing:
CREATE TABLE `video_ids` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`video_id` varchar(11) NOT NULL DEFAULT '',
`link_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `video_key` (`video_id`,`id`),
KEY `link_id` (`link_id`),
KEY `id` (`id`,`video_id`),
CONSTRAINT `video_ids_ibfk_1` FOREIGN KEY (`link_id`) REFERENCES `t_lti_link` (`link_id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
To make sure that the video_id and link_id fields are exactly the same, I copied them directly from the existing table's code to the code for creating the new table. I expected that to solve it, but it did not. Here's the error log:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
141114 22:04:09 Error in foreign key constraint of table tsugi/video_comments:
FOREIGN KEY (`link_id`, `video_id`) REFERENCES `video_ids` (`link_id`, `video_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=285 DEFAULT CHARSET=utf8:
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.

Foreign key references need to be to unique or primary keys. So, you can fix this just by having a unique declaration in video_ids:
CREATE TABLE `video_ids` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`video_id` varchar(11) NOT NULL DEFAULT '',
`link_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `video_key` (`video_id`,`id`),
KEY `link_id` (`link_id`),
KEY `id` (`id`,`video_id`),
UNIQUE (link_id, video_id),
CONSTRAINT `video_ids_ibfk_1` FOREIGN KEY (`link_id`) REFERENCES `t_lti_link` (`link_id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
Here is a SQL Fiddle with an example.

Related

How to create composite foreign key in Mysql

I need to add composite foreign key to table which structure looks like
CREATE TABLE IF NOT EXISTS `discount_month_devices` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`discount_month_id` int(11) UNSIGNED NOT NULL,
`global_device_id` int(11) DEFAULT NULL,
`location_id` int(11) UNSIGNED DEFAULT NULL,
`server_id` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `discount_month_id` (`discount_month_id`),
KEY `global_device_id` (`global_device_id`),
KEY `location_id` (`location_id`,`server_id`),
KEY `server_id` (`server_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Devices table DDL looks like
CREATE TABLE IF NOT EXISTS `devices` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`server_id` varchar(20) CHARACTER SET utf8mb4 NOT NULL,
`device_id` int(11) DEFAULT NULL,
`location_id` int(11) UNSIGNED DEFAULT NULL,
`device_lat` float DEFAULT NULL,
`device_long` float DEFAULT NULL,
....
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `devices_idx1` (`server_id`,`device_id`) USING BTREE,
KEY `devices_idx5` (`server_id`) USING BTREE,
KEY `devices_idx6` (`device_id`) USING BTREE,
KEY `devices_idx8` (`server_id`,`owner_id`) USING BTREE,
KEY `server_id` (`server_id`,`location_id`),
KEY `devices_idx14` (`location_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1583586 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;
ALTER TABLE `devices`
ADD CONSTRAINT `devices_fk1` FOREIGN KEY (`server_id`,`location_id`) REFERENCES `locations` (`server_id`, `location_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `devices_fk2` FOREIGN KEY (`discount_month_id`) REFERENCES `discount_month` (`id`);
There are location_id composite index. I can create FK for location_id and server_id separately so columns types and ranges should be right.
I would like to run alter table which should add the foreign which looks like
ALTER TABLE `discount_month_devices` ADD CONSTRAINT `discount_month_devices_fk3`
FOREIGN KEY (`location_id`, `server_id`) REFERENCES `devices`(`location_id`, `server_id`)
ON DELETE CASCADE ON UPDATE CASCADE;
This throws me an error: General error: 1215 Cannot add foreign key constraint
Does anybody know what could be the problem.
You must list the columns in the foreign key constraint in the same order that they appear in a key in the referenced table. Your key in devices is on (server_id, location_id) but you tried to reference them in your foreign key constraint as (location_id, server_id).
Try this:
ALTER TABLE `discount_month_devices`
ADD CONSTRAINT `discount_month_devices_fk3`
FOREIGN KEY (`server_id`, `location_id`)
REFERENCES `devices`(`server_id`, `location_id`)
ON DELETE CASCADE ON UPDATE CASCADE;
The order of columns in keys and constraints is not required to match the order of columns in the table definition.

mysql sometimes removes and old index when adding a new index?

TL;DR
We've seen on a virtual machine, that adding a UNIQUE index causes an older non-UNIQUE index to be removed automatically.
I cannot reproduce this on any other machines (yet?), and if I do:
mysql -e 'create db2'
mysqldump db1 | mysql db2
before adding the new index to db1, and then try adding the index on db2 instead, the old index is not removed from db2. Funky!
We have a snapshot of the machine with db1, and can reproduce it there in the existing db1 database...
Anybody have any idea what is going on? We have scripts to automate adding/removing indexes, and that started failing because on that one machine, the old index didn't exist any longer.
When a dump/restore cycle causes the problem to go away, that makes it hard understand, reproduce and reduce the problem to a simple example.
Details
The table in question looked like this before adding the new index (from SHOW CREATE TABLE). Note the monitoredTableRowID KEY:
CREATE TABLE `cfgAttributeInstances` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`attributeID` int(10) unsigned DEFAULT NULL,
`nodeID` int(10) unsigned DEFAULT NULL,
`groupID` int(10) unsigned DEFAULT NULL,
`statisticID` int(10) unsigned DEFAULT NULL,
`nodeStatisticID` int(10) unsigned DEFAULT NULL,
`serviceID` int(10) unsigned DEFAULT NULL,
`nodeServiceID` int(10) unsigned DEFAULT NULL,
`nodeComponentID` int(10) unsigned DEFAULT NULL,
`syslogFilterID` int(10) unsigned DEFAULT NULL,
`value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE KEY `nodeID` (`nodeID`,`attributeID`),
UNIQUE KEY `groupID` (`groupID`,`attributeID`),
UNIQUE KEY `statisticID` (`statisticID`,`attributeID`),
UNIQUE KEY `nodeStatisticID` (`nodeStatisticID`,`attributeID`),
UNIQUE KEY `serviceID` (`serviceID`,`attributeID`),
UNIQUE KEY `nodeServiceID` (`nodeServiceID`,`attributeID`),
KEY `attributeID` (`attributeID`),
KEY `monitoredTableRowID` (`nodeComponentID`),
KEY `syslogFilterID` (`syslogFilterID`),
CONSTRAINT `cfgAttributeInstances_ibfk_1` FOREIGN KEY (`attributeID`) REFERENCES `cfgAttributes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_2` FOREIGN KEY (`nodeID`) REFERENCES `cfgNodes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_3` FOREIGN KEY (`groupID`) REFERENCES `cfgGroups` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_4` FOREIGN KEY (`statisticID`) REFERENCES `cfgStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_5` FOREIGN KEY (`nodeStatisticID`) REFERENCES `cfgNodeStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_6` FOREIGN KEY (`serviceID`) REFERENCES `cfgServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_7` FOREIGN KEY (`nodeServiceID`) REFERENCES `cfgNodeServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_8` FOREIGN KEY (`nodeComponentID`) REFERENCES `cfgNodeComponents` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_9` FOREIGN KEY (`syslogFilterID`) REFERENCES `cfgSyslogFilters` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='CapMon Attribute instances';
I added this index:
ALTER TABLE cfgAttributeInstances ADD
UNIQUE new_nodeComponentID (nodeComponentID, attributeID)
It looked like this after adding that index:
CREATE TABLE `cfgAttributeInstances` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`attributeID` int(10) unsigned DEFAULT NULL,
`nodeID` int(10) unsigned DEFAULT NULL,
`groupID` int(10) unsigned DEFAULT NULL,
`statisticID` int(10) unsigned DEFAULT NULL,
`nodeStatisticID` int(10) unsigned DEFAULT NULL,
`serviceID` int(10) unsigned DEFAULT NULL,
`nodeServiceID` int(10) unsigned DEFAULT NULL,
`nodeComponentID` int(10) unsigned DEFAULT NULL,
`syslogFilterID` int(10) unsigned DEFAULT NULL,
`value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE KEY `nodeID` (`nodeID`,`attributeID`),
UNIQUE KEY `groupID` (`groupID`,`attributeID`),
UNIQUE KEY `statisticID` (`statisticID`,`attributeID`),
UNIQUE KEY `nodeStatisticID` (`nodeStatisticID`,`attributeID`),
UNIQUE KEY `serviceID` (`serviceID`,`attributeID`),
UNIQUE KEY `nodeServiceID` (`nodeServiceID`,`attributeID`),
UNIQUE KEY `new_nodeComponentID` (`nodeComponentID`,`attributeID`),
KEY `attributeID` (`attributeID`),
KEY `syslogFilterID` (`syslogFilterID`),
CONSTRAINT `cfgAttributeInstances_ibfk_1` FOREIGN KEY (`attributeID`) REFERENCES `cfgAttributes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_2` FOREIGN KEY (`nodeID`) REFERENCES `cfgNodes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_3` FOREIGN KEY (`groupID`) REFERENCES `cfgGroups` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_4` FOREIGN KEY (`statisticID`) REFERENCES `cfgStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_5` FOREIGN KEY (`nodeStatisticID`) REFERENCES `cfgNodeStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_6` FOREIGN KEY (`serviceID`) REFERENCES `cfgServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_7` FOREIGN KEY (`nodeServiceID`) REFERENCES `cfgNodeServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_8` FOREIGN KEY (`nodeComponentID`) REFERENCES `cfgNodeComponents` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_9` FOREIGN KEY (`syslogFilterID`) REFERENCES `cfgSyslogFilters` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='CapMon Attribute instances';
But hey! Where did the monitoredTableRowID index go?
Again, I cannot reproduce this. If I do a mysqldump > dump.db/mysql < dump.db cycle, the monitoredTableRowID doesn't disappear...
Any ideas on what is going on?
The composite key with nodeComponentID causes the non-composite key with nodeComponentID to be redundant within the context of the foreign key reference it is used. MySQL automatically drops the redundant implicit index. The behavior is dependant on column index ordering, as the dropped index will always be the first column within the defined composite key. [sic]
The issue(s) are specifically caused by the automatic implicit index created when adding a foreign key CONSTRAINT, and the index(es) being explicitly defined in SHOW CREATE TABLE which is also used by mysqldump.
The index_name value is ignored if there is already an explicitly
defined index on the child table that can support the foreign key.
Otherwise, MySQL implicitly creates a foreign key index... [sic]
MySQL requires indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. In the
referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist. This index might be silently dropped later, if you create
another index that can be used to enforce the foreign key constraint.
index_name, if given, is used as described previously. [sic]
To reproduce the issue
Implicit Key Example db-fiddle
Note - INDEX FK_BAR_FOO (foo_id) is not explicitly defined.
DROP TABLE IF EXISTS `BAR`;
DROP TABLE IF EXISTS `FOO`;
CREATE TABLE `FOO` (
`id` INT(11) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
SHOW CREATE TABLE `BAR`;
Result
INDEX FK_BAR_FOO (foo_id) is explicitly defined in SHOW CREATE TABLE, but is implicitly created by MySQL.
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
Composite Key Example: db-fiddle
ALTER TABLE `BAR`
ADD UNIQUE INDEX `foo_id_b` (`foo_id`, `b`);
SHOW CREATE TABLE `BAR`;
Result
foo_id index is removed due to being redundant.
Since foo_id is the first column within the composite key, the implicit foo_id index FK_BAR_FOO is removed.
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `foo_id_b` (`foo_id`, `b`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
Explicit Key Example: db-fiddle
MySQL ignores the redundant indexes, if the table was created with an explicit index that satisfies the foreign key CONSTRAINT.
DROP TABLE IF EXISTS `BAR`;
DROP TABLE IF EXISTS `FOO`;
CREATE TABLE `FOO` (
`id` INT(11) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
ALTER TABLE `BAR`
ADD UNIQUE INDEX `foo_id_b` (`foo_id`, `b`);
SHOW CREATE TABLE `BAR`;
Result
Composite-key index for foo_id, b and index on foo_id are created.
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `foo_id_b` (`foo_id`, `b`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
Solution
In your scripts, verify the index (does not) exist before attempting to drop/add the index.
IF NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'new_nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
ADD UNIQUE INDEX `new_nodeComponentID` (`nodeComponentID`,`attributeID`);
END IF;
IF EXISTS (
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
DROP INDEX `nodeComponentID`;
END IF;

MySQL Nullable FK and the 150 error

I have a problem with create table statement in MySQL.
The scenario is, I want to have a table P_CDP wchich stores some informations, and the table P_CDPFiles which stores the data of the uploaded files.
The column SelectedCDPFileID by default should be NULL unless the user selects some file. Then that column is filled by the file ID. But, I'm still getting the errno 150, why ? I think the FK names are set properly
CREATE TABLE `P_CDP` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`P_OrderID` int(11) NOT NULL DEFAULT '0',
`SelectedCDPFileID` int(11) NULL,
PRIMARY KEY (`ID`),
KEY `FK_P_CDP_P_Orders` (`P_OrderID`),
KEY `FK_P_CDP_P_CDPFiles` (`SelectedCDPFileID`),
CONSTRAINT `FK_P_CDP_P_Orders` FOREIGN KEY (`P_OrderID`) REFERENCES `P_Orders` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_P_CDP_P_CDPFiles` FOREIGN KEY (`SelectedCDPFileID`) REFERENCES `P_CDPFiles` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `P_CDPFiles` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`FileID` int(11) NOT NULL DEFAULT '0',
`P_CDPID` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `FK_P_CDPFiles_File` (`FileID`),
KEY `FK_P_CDPFiles_P_CDP` (`P_CDPID`),
CONSTRAINT `FK_P_CDPFiles_File` FOREIGN KEY (`FileID`) REFERENCES `File` (`FileID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_P_CDPFiles_P_CDP` FOREIGN KEY (`P_CDPID`) REFERENCES `P_CDP` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
You're attempting to reference a table that does not yet exist.
If you must have references in both directions between these two tables (which generally indicates quite poor design), you will have to:
Create the first table without any reference to the as-yet-undefined table:
CREATE TABLE `P_CDP` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`P_OrderID` int(11) NOT NULL DEFAULT '0',
`SelectedCDPFileID` int(11) NULL,
PRIMARY KEY (`ID`),
KEY `FK_P_CDP_P_Orders` (`P_OrderID`),
KEY `FK_P_CDP_P_CDPFiles` (`SelectedCDPFileID`),
CONSTRAINT `FK_P_CDP_P_Orders` FOREIGN KEY (`P_OrderID`)
REFERENCES `P_Orders` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Create the second table, including its reference to the first table:
CREATE TABLE `P_CDPFiles` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`FileID` int(11) NOT NULL DEFAULT '0',
`P_CDPID` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `FK_P_CDPFiles_File` (`FileID`),
KEY `FK_P_CDPFiles_P_CDP` (`P_CDPID`),
CONSTRAINT `FK_P_CDPFiles_File` FOREIGN KEY (`FileID`)
REFERENCES `File` (`FileID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_P_CDPFiles_P_CDP` FOREIGN KEY (`P_CDPID`)
REFERENCES `P_CDP` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Alter the first table to add the intended constraint:
ALTER TABLE `P_CDP`
ADD CONSTRAINT `FK_P_CDP_P_CDPFiles` FOREIGN KEY (`SelectedCDPFileID`)
REFERENCES `P_CDPFiles` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION;

InnoDB unique keys and indexes

I used the following create statement:
CREATE TABLE `subscr` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`media_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY (`media_id`, `user_id`),
CONSTRAINT FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE CASCADE,
CONSTRAINT FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB
Why does InnoDB only put an index on user_id? I thought it needed indexes on all foreign key references.
CREATE TABLE `subscr` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`media_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `media_id` (`media_id`,`user_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `subscriptions_media_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE CASCADE,
CONSTRAINT `subscriptions_media_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB
media_id has an index, too, and it's unique. It's sufficient the way it is for MySQL. There's just a separate index created for user_id, since user_id in the unique index is second, and therefore it's useless for the foreign key.

MySQL error when trying to truncate table

I'm having problems to truncate a table on the MySQL Server 5.5.
The table I'm trying to truncate has a column that serves as a foreign key in another table.
The CREATE TABLE of both tables involved is as it follows:
CREATE TABLE `tbluser` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`creationDate` datetime NOT NULL,
`creationUserId` int(11) NOT NULL,
`updateDate` datetime NOT NULL,
`updateUserId` int(11) NOT NULL,
`lastAccess` datetime NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
UNIQUE KEY `email_UNIQUE` (`email`),
KEY `FK_tbluser_creationUserId` (`creationUserId`),
KEY `FK_tbluser_updateUserId` (`updateUserId`),
CONSTRAINT `FK_tbluser_updateUserId` FOREIGN KEY (`updateUserId`) REFERENCES `tbluser` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `FK_tbluser_creationUserId` FOREIGN KEY (`creationUserId`) REFERENCES `tbluser` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
CREATE TABLE `tblpost` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` mediumtext NOT NULL,
`creationDate` datetime NOT NULL DEFAULT '1901-01-01 00:00:00',
`creationUserId` int(11) NOT NULL,
`updateDate` datetime NOT NULL DEFAULT '1901-01-01 00:00:00',
`updateUserId` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_tblpost_creationUserId` (`creationUserId`),
KEY `FK_tblpost_updateUserId` (`updateUserId`),
CONSTRAINT `FK_tblpost_updateUserId` FOREIGN KEY (`updateUserId`) REFERENCES `tbluser` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `FK_tblpost_creationUserId` FOREIGN KEY (`creationUserId`) REFERENCES `tbluser` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Please note that all the constraints are both set to DELETE and UPDATE ON CASCADE.
When I try to TRUNCATE the table:
TRUNCATE TABLE `<databasename>`.`tbluser`;
I receive the following error message:
Cannot truncate a table referenced in a foreign key constraint
(`<databasename>`.`tblpost`,
CONSTRAINT `FK_tblpost_updateUserId`
FOREIGN KEY (`updateUserId`)
REFERENCES `<databasename>`.`tbluser` (`id`))
In addition to this information, there is the fact that when the action above is attempted on a MySQL Server 5.1, it works!
Does anyone have an idea of why this is happening?
Check here . That makes sense that TRUNCATE TABLE raises an error in such cases; the bad thing that it's not documented.