Foreign key constraint fails during `drop table` - mysql

I have a strange problem in which I'm not able to delete a table as a foreign key constraint fails. The scenario is as follows.
I'm trying to drop the table departments from my DB, the structure for which is as follows:
show create table `departments`
CREATE TABLE `departments` (
`dept_id` int(11) NOT NULL AUTO_INCREMENT,
`dept_name` varchar(50) NOT NULL,
PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Now, the only other table in the database that has department_id is the employee table:
show create table employee
CREATE TABLE `employee` (
`emp_id` varchar(20) NOT NULL,
`role` varchar(10) DEFAULT NULL,
`password` varchar(500) DEFAULT NULL,
`division_id` int(20) DEFAULT NULL,
`email_bb` varchar(100) DEFAULT NULL,
`is_active` tinyint(1) NOT NULL,
`date_joining` date DEFAULT NULL,
`date_confirmation` date DEFAULT NULL,
`date_appraisal` date DEFAULT NULL,
`date_leaving` date DEFAULT NULL,
`first_name` varchar(100) DEFAULT NULL,
`middle_name` varchar(100) DEFAULT NULL,
`last_name` varchar(100) DEFAULT NULL,
`sex` varchar(1) DEFAULT NULL,
`dob` date DEFAULT NULL,
`email_other` varchar(100) DEFAULT NULL,
`contact` varchar(100) DEFAULT NULL,
`present_addr` varchar(1000) DEFAULT NULL,
`perma_addr` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
As you can see, none of these tables are related via foreign keys. So why do I get this error when trying to drop the department table:
#1217 - Cannot delete or update a parent row: a foreign key constraint fails
Is there a better way (and hopefully, simpler) way to see the foreign keys defined? What might be going wrong?

show create table doesn't show incoming FK restraints (e.g. FK is specified in child table, not parent)
So there is a possibility that you have another table with a FK constraint to that table. I usually dump the schema of the database, which shows all FK constraints.

Related

How to use "ON UPDATE CASCADE" Correctly in MariaDB 10.1.37 / Ver 15.1?

I am experiencing trouble getting ON UPDATE CASCADE to work with a CONSTRAINT. If I use UPDATE to change the value of customerName in the customer table, it will not change the customerName value in the city table. No error message shows up.
The version of the MariaDB:
Ver 15.1 Distrib 10.1.37-MariaDB
My city table when using SHOW CREATE TABLE city:
city | CREATE TABLE `city` (
`cityId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`city` varchar(50) DEFAULT NULL,
`countryId` int(10) unsigned DEFAULT NULL,
`customerName` varchar(50) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`postalCode` varchar(50) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
`createDate` varchar(50) DEFAULT NULL,
`createdBy` varchar(50) DEFAULT NULL,
`lastUpdateBy` varchar(50) DEFAULT NULL,
PRIMARY KEY (`cityId`),
KEY `customerNameChange01` (`customerName`),
CONSTRAINT `customerNameChange01` FOREIGN KEY (`customerName`)
REFERENCES `customer` (`customerName`)
ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
My customer table SHOW CREATE TABLE customer:
customer | CREATE TABLE `customer` (
`customerId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`customerName` varchar(50) DEFAULT NULL,
`addressId` int(10) unsigned DEFAULT NULL,
`active` int(10) unsigned DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`postalCode` varchar(50) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
`createDate` varchar(50) DEFAULT NULL,
`createdBy` varchar(50) DEFAULT NULL,
`lastUpdateBy` varchar(50) DEFAULT NULL,
PRIMARY KEY (`customerId`),
KEY `CustomerName` (`customerName`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
These are the commands I used to create the index and CONSTRAINT:
CREATE INDEX CustomerName ON customer (customerName);
ALTER TABLE city
ADD CONSTRAINT customerNameChange01
FOREIGN KEY (customerName)
REFERENCES customer (customerName)
ON UPDATE CASCADE
ON DELETE SET NULL;
In the customer table, the CustomerName key references an index. Otherwise, I would not have been able to put in the CONSTRAINT in the city table.
Update: The code works fine in DB Fiddle for MariaDB 10.2 and personal testing confirms that the example code from there works in my own database as well.
Thank you for spending your time.

MySQL: Optimizing JOINs to find non-matching records

We have a host management system (let's call it CMDB), and a DNS system, each using different tables. The former syncs to the latter, but manual changes cause them to get out of sync. I would like to craft a query to find aliases in CMDB that do NOT have a matching entry in DNS (either no entry, or the name/IP is different)
Because of the large size of the tables, and the need for this query to run frequently, optimizing the query is very important.
Here's what the tables look like:
cmdb_record: id, ipaddr
cmdb_alias: record_id, host_alias
dns_entry: name, ipaddr
cmdb_alias.record_id is a foreign key from cmdb_record.id, so that one IP address can have multiple aliases.
So far, here's what I've come up with:
SELECT cmdb_alias.host_alias, cmdb_record.ipaddr
FROM cmdb_record
INNER JOIN cmdb_alias ON cmdb_alias.record_id = cmdb_record.id
LEFT JOIN dns_entry
ON dns_entry.ipaddr = cmdb_record.ipaddr
AND dns_entry.name = cmdb_alias.host_alias
WHERE dns_entry.ipaddr IS NULL OR dns_entry.name IS NULL
This seems to work, but takes a very long time to run. Is there a better way to do this? Thanks!
EDIT: As requested, here are the SHOW CREATE TABLEs. There are lots of extra fields that aren't particularly relevant, but included for completeness.
Create Table: CREATE TABLE `cmdb_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ip_version` int(11) DEFAULT NULL,
`ipaddr` varchar(40) DEFAULT NULL,
`ipaddr_numeric` decimal(40,0) DEFAULT NULL,
`block_id` int(11) NOT NULL,
`record_commented` tinyint(1) NOT NULL,
`mod_time` datetime NOT NULL,
`deleted` tinyint(1) NOT NULL,
`deleted_date` datetime DEFAULT NULL,
`record_owner` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ipaddr` (`ipaddr`),
KEY `cmdb_record_fe30f0f7` (`ipaddr`),
KEY `cmdb_record_2b8b575` (`ipaddr_numeric`),
KEY `cmdb_record_45897ef2` (`block_id`),
CONSTRAINT `block_id_refs_id_ed6ed320` FOREIGN KEY (`block_id`) REFERENCES `cmdb_block` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=104427 DEFAULT CHARSET=latin1
Create Table: CREATE TABLE `cmdb_alias` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`host_alias` varchar(255) COLLATE latin1_general_cs NOT NULL,
`record_id` int(11) NOT NULL,
`record_order` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `cmdb_alias_fcffc3bb` (`record_id`),
KEY `alias_lookup` (`host_alias`),
CONSTRAINT `record_id_refs_id_8169fc71` FOREIGN KEY (`record_id`) REFERENCES `cmdb_record` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=155433 DEFAULT CHARSET=latin1 COLLATE=latin1_general_cs
Create Table: CREATE TABLE `dns_entry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rec_grp_id` varchar(40) NOT NULL,
`parent_id` int(11) NOT NULL,
`domain_id` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`type` varchar(6) DEFAULT NULL,
`ipaddr` varchar(255) DEFAULT NULL,
`ttl` int(11) DEFAULT NULL,
`prio` int(11) DEFAULT NULL,
`status` varchar(20) NOT NULL,
`op` varchar(20) NOT NULL,
`mod_time` datetime NOT NULL,
`whodunit` varchar(50) NOT NULL,
`comments` longtext NOT NULL,
PRIMARY KEY (`id`),
KEY `dns_entry_a2431ea` (`domain_id`),
KEY `dns_entry_52094d6e` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=49437 DEFAULT CHARSET=utf8
If you don't have one already, create an index on dns_entry(ipaddr, name). This might be all you need to speed the query.

MySQL Error Number 150 when creating Table with Foreign Key

I am having an issue creating a new table in my database. I've seen that the error code it is returning is to do with Foreign Key constraints.
I checked to ensure that the data type of the foreign key in the new table matched the data type of the primary key in the other table. They are both int(11).
However I am still getting an error. Am I missing something? This is my SQL script for creating the new table:
CREATE TABLE `regular_features` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200) DEFAULT NULL,
`day` VARCHAR(200) DEFAULT NULL,
`description` TEXT DEFAULT NULL,
`programme_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`programme_id`) REFERENCES directoryprogramme(id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
This is the original table containing the primary key:
CREATE TABLE `directoryprogramme` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(250) NOT NULL,
`broadcast_time` VARCHAR(100) NOT NULL,
`description` TEXT NOT NULL,
`days` VARCHAR(150) NOT NULL,
`contributors` VARCHAR(250) NOT NULL,
`directorycompany_id` INT(11) NOT NULL,
`directorycontact_id` VARCHAR(250) NOT NULL,
`facebook_link` VARCHAR(250) DEFAULT NULL,
`twitter_link` VARCHAR(250) DEFAULT NULL,
`wikipedia_link` VARCHAR(250) DEFAULT NULL,
`web` VARCHAR(250) DEFAULT NULL,
`imageextension` VARCHAR(10) DEFAULT NULL,
`type` VARCHAR(20) NOT NULL DEFAULT 'other',
PRIMARY KEY (`id`)
) ENGINE=MYISAM AUTO_INCREMENT=1161 DEFAULT CHARSET=utf8;
The Foreign Key will be the id of directoryprogramme
The problem is the last line of your create statement:
ENGINE=INNODB DEFAULT CHARSET=utf8;
You mix MYISAM in ald table with INNODB in your new table.
That doesn't work.
Chnage the engine in your new table to MYISAM and it works.

cannot add second FK : got error can't create table'.jobstatus\#sql-32c_12f2f.frm' (errno:150)

CREATE TABLE `job` (
`jobId` int(11) NOT NULL auto_increment,
`jobcode` varchar(25) default NULL,
`jobname` varchar(255) default NULL,
`location` varchar(255) default NULL,
`budget` int(10) unsigned default NULL,
`year_type` varchar(100) default NULL,
`worklineId` int(11) default NULL,
PRIMARY KEY (`jobId`),
KEY `NewIndex` (`worklineId`),
FOREIGN KEY (`worklineId`) REFERENCES `workline` (`worklineId`)
) TYPE=InnoDB;
CREATE TABLE `subjob` (
`subjobId` int(11) NOT NULL auto_increment,
`subjobcode` varchar(25) default NULL,
`subjobname` varchar(255) default NULL,
`subjobbudget` int(11) unsigned default NULL,
`jobgoal_date` date default '0000-00-00',
`jobId` int(11) default NULL,
PRIMARY KEY (`subjobId`),
KEY `NewIndex` (`jobId`),
FOREIGN KEY (`jobId`) REFERENCES `job` (`jobId`)
) TYPE=InnoDB;
CREATE TABLE `contract` (
`contractId` int(11) NOT NULL auto_increment,
`contractcode` varchar(25) default NULL,
`price` int(11) unsigned default NULL,
`contractprice` int(11) unsigned default NULL,
`company` varchar(50) default NULL,
`signdate` date default '0000-00-00',
`begindate` date default '0000-00-00',
`enddateplan` date default '0000-00-00',
`note` text,
PRIMARY KEY (`contractId`)
) TYPE=InnoDB;
CREATE TABLE `subjob_contract` (
`subjobcontractId` int(11) NOT NULL auto_increment,
`status` varchar(11) default NULL,
`contractId` int(11) default NULL,
`subjobId` int(11) default NULL,
PRIMARY KEY (`subjobcontractId`),
KEY `NewIndex` (`contractId`),
KEY `NewIndex2` (`subjobId`),
FOREIGN KEY (`contractId`) REFERENCES `contract` (`contractId`)
) TYPE=InnoDB
I m using mysql front 3.2 to manage database,I can add first fk but when i add second fk i got an error following this :
sql execution error #1005. response from the database: can't create table'.jobstatus#sql-32c_12f2f.frm' (errno:150). i already define the new index for fk subjobId reference to subjob table what could be the possibility of this error? thank you
Check the datatype and size of the subjobId column on primary table and referenced table. both must be same than it will allow you to create foreign key.
Answer is: You can not refer that column/table which is not created yet. Try to execute tables having foreign keys after the referenced tables.
Obviously you should have consistency in datatypes of foreign key and referenced column as well
Correct Execution Demo. Also You should use Engine=InnoDB instead of Type=InnoDB

Delete Cascade Multiple Tables

I wonder whether someone can help me please.
I have the following three tables:
Parent Table
CREATE TABLE `userdetails` (
`userid` int(6) NOT NULL auto_increment,
`forename` varchar(20) NOT NULL,
`surname` varchar(30) NOT NULL,
`emailaddress` varchar(150) NOT NULL,
`password` varchar(200) NOT NULL,
`passwordhint` varchar(20) NOT NULL,
`subscriptionexpiration` date NOT NULL,
`salt` varchar(200) NOT NULL,
PRIMARY KEY (`userid`),
UNIQUE KEY `emailaddress` (`emailaddress`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Child Table
CREATE TABLE `detectinglocations` (
`userid` int(6) NOT NULL,
`locationid` int(6) NOT NULL auto_increment,
`locationname` varchar(80) NOT NULL,
`address` varchar(110) NOT NULL,
`osgb36lat` float(10,6) NOT NULL,
`osgb36lon` float(10,6) NOT NULL,
`osgridref` varchar(20) NOT NULL,
`wgs84latd` int(2) NOT NULL,
`wgs84latm` int(2) NOT NULL,
`wgs84lats` decimal(6,2) NOT NULL,
`wgs84latb` varchar(1) NOT NULL,
`wgs84lond` int(2) NOT NULL,
`wgs84lonm` int(2) NOT NULL,
`wgs84lons` decimal(6,2) NOT NULL,
`wgs84lonb` varchar(1) NOT NULL,
`nameoflocationcontact` varchar(30) NOT NULL,
`locationcontactsaddressline1` varchar(50) NOT NULL,
`locationcontactsaddressline2` varchar(50) default NULL,
`locationcontactsaddressline3` varchar(50) default NULL,
`locationcontactsaddressline4` varchar(50) default NULL,
`locationcontactstelephonenumber` varchar(15) default NULL,
PRIMARY KEY (`locationid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Child Table
CREATE TABLE `detectors` (
`userid` int(6) NOT NULL,
`detectorid` int(6) NOT NULL auto_increment,
`detectorname` varchar(30) NOT NULL,
PRIMARY KEY (`detectorid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=0 AUTO_INCREMENT=1 ;
Using the this code below, I'm trying to implement the 'Delete Cascade' functionality, whereby if the user is deleted from the parent table, the associated rows within the child tables are alse deleted.
ALTER TABLE 'tablename'
add CONSTRAINT fk_userdetails
FOREIGN KEY (userid)
REFERENCES userdetails(userid)
ON DELETE CASCADE
I can successfully implement this for the first child table, but when I try to do the same with the second child table I receive the following error:
#1005 - Can't create table './db369054642/#sql-30d_bd1a57.frm' (errno: 121)
I've done quite a bit of research to find out what the problem may be, but I must admit I'm none the wiser.
Could someone perhaps have a look at this please and let me know what I'm doing wrong?
Many thanks
The solution is on http://dev.mysql.com/doc/refman/5.0/en/innodb-error-codes.html in the post by Mark Robbins on September 29 2007 10:19pm and the next one:
Constraint names must be unique
fk_userdetails is not unique
So you might try
ALTER TABLE 'tablename'
add CONSTRAINT fk_userdetails_detectors
FOREIGN KEY (userid)
REFERENCES userdetails(userid)
ON DELETE CASCADE
on the second table