MySQL Create table with reference to non existant table - mysql

Using MySQL workbench, I copied the create statement from a few related tables to put into a clean schema. They all reference each other in some way so there is no inherent order I can create them in. How can I just force MySQL to create the tables while ignoring any warning that may occur, just until the rest of the tables are created?
Would I have to group it inside a transaction of some sort?
A very simple example would be:
CREATE TABLE `vehicle` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`gallery_id` int(11) DEFAULT NULL,
`make_id` int(11) NOT NULL,
`model_id` int(11) DEFAULT NULL,
`make` varchar(100) DEFAULT '',
`model` varchar(100) DEFAULT '',
`colour_id` int(11) DEFAULT NULL,
`currency_id` int(11) NOT NULL DEFAULT '1',
`fuel_id` int(11) DEFAULT NULL,
`status_id` int(11) DEFAULT NULL,
`stock_code` varchar(100) DEFAULT NULL,
`registration` varchar(20) DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
`description` text,
`month` tinyint(4) DEFAULT NULL,
`public` tinyint(4) NOT NULL DEFAULT '0',
`sold` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `vehicle_fk_idx` (`status_id`),
CONSTRAINT `vehicle_fk` FOREIGN KEY (`status_id`) REFERENCES `vehicle_status` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `vehicle_status` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`slug` varchar(100) DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug_UNIQUE` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
vehicle references vehicle_status which would mean that vehicle_status would have to be created first. How would I create vehicle first and then vehicle_status without adding the reference afterwards?

You do not define foreign keys when creating tables, you would have them in a separate query like this:
ALTER TABLE `vehicle`
ADD CONSTRAINT `vehicle_ibfk_1` FOREIGN KEY (`status_id`)
REFERENCES `vehicle_status` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
So you would first create tables and then create foreign keys.
The way I personally do is I have all CREATE TABLE queries in one file that I know I can simply just import without any errors. I have all CONSTRAINT queries in a separate file that I import after all the tables have been created and I have all INSERT INTO queries in a separate file that adds data after all constraints and tables have been set.

It looks like vehicle_status is a lookup table, while vehicle is a primary transaction table.
In general, lookup tables do not reference other tables, although there can be designs where one lookup table references another lookup table. In your case, it's simple: just create vehicle_status first. If your schema has a hundred tables in it, it's going to involve a little work to order the create commands in the right sequence.
There are designs where the reference chain forms a circle. In such a case, you'll have to do what GGio suggests: add the constraints later. There are other problems with designs involving circular references, and those problems may or may not be present in your schema.
When you go to populate the tables, you'll have to worry about order as well. In general, you'll have to populate the lookup tables first, before you begin to populate the transaction tables. Otherwise you'll get reference violations at load time.

Related

How to debug mysql foreign key constraint, ON DELETE CASCADE not deleting rows from Child table on production environment

I have defined 2 tables and a foriegn key constraint between them as follows:
| users | CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account_master_id` int(11) NOT NULL,
`user_type_id` int(11) NOT NULL,
`user_group_id` int(11) NOT NULL,
`user_type_code` char(1) NOT NULL,
`membership_number` varchar(40) NOT NULL,
`password` varchar(60) NOT NULL,
`email` varchar(200) NOT NULL,
`isd` varchar(10) NOT NULL,
`mobile` varchar(20) NOT NULL,
`passenger_id` int(11) NOT NULL,
`added_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`added_by` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
KEY `account_master_id` (`account_master_id`),
CONSTRAINT `acMaster_to_user` FOREIGN KEY (`account_master_id`) REFERENCES `account_master` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=189 DEFAULT CHARSET=utf8 |
user_oauth | CREATE TABLE `user_oauth` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`service` varchar(30) NOT NULL,
`auth_id` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`auto_share` tinyint(4) NOT NULL,
`photo` varchar(255) NOT NULL,
`auth_token_short` varchar(255) DEFAULT NULL,
`auth_details` text NOT NULL,
`device_type` varchar(60) NOT NULL,
`login_date` datetime NOT NULL,
`login_ip` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `user` (`user_id`),
CONSTRAINT `user_to_oauth` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=latin1 |
on deleting a row from users table, deletes corresponding entries from user_oauth table in LOCAL and Staging environment. but however same thing is not working in PRODUCTION environment. I want to know how can i debug this.
update:
both tables are innodb
running mysql in strict mode
The reasons why foreign keys might not work are:
they are not supported (e.g. on MyISAM-tables)
they are disabled
MySQL allows you to disable foreign key contraints by setting the system variable foreign_key_checks to 0. This will allow you to violate all foreign key constraints (e.g. delete a parent or add parentless childs). But it will in turn also disable related features like cascades, which are there to automatically prevent specific constraint violations (by e.g. deleting the children) - which of course won't occur anymore if the option is disabled.
The idea is to help you with some administration tasks, e.g. importing data when the referenced data is not yet there, but should usually not be used during normal operation. If the setting reappears, you might want to check your apps if one is setting this option by accident, as it is enabled after every server start by default and has to be disabled explicitely.
You can check the current setting by e.g. using
select ##foreign_key_checks;
You can use
SET foreign_key_checks = 1;
to enable it again, but be aware that it will not check your current data:
Setting foreign_key_checks to 1 does not trigger a scan of the existing table data. Therefore, rows added to the table while foreign_key_checks=0 will not be verified for consistency.
So you will have to check and fix it yourself. You can do it either before or after you enabled the setting again, although it might be easier to do it before. To trigger a recheck, you can and should drop and recreate the foreign key, just to make sure everything is consistent now.

Mysql Workbench Can't Select Foreign Key

First of all I've examined a lot of questions and googled it a lot, none of them solved my problem..
I'm creating my tables by using Mysql Workbench 6.3. I've created them by using only gui not a single query. After that I've tried to create some foreign keys for int(11) columns but GUI is not allowing me to do so.
Here's my Show Create Table 'tableName'
CREATE TABLE `item` (
`id` int(11) NOT NULL,
`description` varchar(300) NOT NULL,
`maker` varchar(200) NOT NULL,
`model` varchar(200) NOT NULL,
`condition` varchar(200) NOT NULL,
`locationId` int(11) NOT NULL,
`categoryId` int(11) NOT NULL,
`userId` int(11) NOT NULL,
`lendTermsId` int(11) NOT NULL,
`itemOptionsId` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
And the other one ;
CREATE TABLE `location` (
`id` int(11) NOT NULL,
`type` varchar(200) NOT NULL,
`coordinateLat` varchar(200) NOT NULL,
`coordinateLong` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I'm trying to create a foreign key between location.id and item.locationId.
Workbench GUI is not allowing me to select checkboxes...
As you can see from this image I can't select checkbox or select combobox value..
EDIT: I can manage this with query, but there are a lot of tables in some projects, dont want to do it all with queries... Is there something that I'm missing in workbench ?
Thanks in advance.
As user4115463 said, this is caused by a difference in DataType. Make sure that both keys have the exact same data type:
the Datatype field should contain the exact same string (INT and INT(10) are not the same)
the B (Is binary) checkbox should match
the UN (Unsigned) checkbox should match
When selecting a checkbox, MySQL Workbench attempts to populate the dropdown next to the checkbox with matching columns, and if it can't find any matching columns, it decides to silently ignore the click on the checkbox instead.
It might be a little late to answer this question but,
Recently, I experience this issue in Workbench GUI and it was caused by difference in DataType.
Making sure that both fields have the same DataType seems to resolve the issue.
Hope this helps.
Try the following Alt statement
ALTER TABLE `emp`.`item`
ADD INDEX `location_idx` (`categoryId` ASC);
ALTER TABLE `emp`.`item`
ADD CONSTRAINT `location`
FOREIGN KEY (`categoryId`)
REFERENCES `emp`.`location` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
I have tested through GUI check this screenshot

Creating composite primarykey using a foreignkey and a non key attribute

This is my auto generated code after creating the batch table. while inserting data to this table
BatchID=1,Course_CourseID=1
BatchID=1,Course_CourseID=2
it is creating an error saying "Duplicate entry '1' for key 'BatchID_UNIQUE'".
I'm using C# 2010 express windows application as well as MySQl 5.1
My table schema is here
CREATE TABLE `batch` (
`BatchID` int(11) NOT NULL,
`Course_CourseID` int(11) NOT NULL,
`NoOfStudents` int(11) DEFAULT NULL,
`ClassRoom` varchar(45) DEFAULT NULL,
`StartDate` varchar(45) DEFAULT NULL,
`Day` varchar(45) DEFAULT NULL,
`Time` varchar(45) DEFAULT NULL,
PRIMARY KEY (`BatchID`,`Course_CourseID`),
UNIQUE KEY `BatchID_UNIQUE` (`BatchID`),
KEY `fk_Batch_Course1` (`Course_CourseID`),
CONSTRAINT `fk_Batch_Course1` FOREIGN KEY (`Course_CourseID`)
REFERENCES `course` (`CourseID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Well, the error message quite clearly refers to this string:
UNIQUE KEY `BatchID_UNIQUE` (`BatchID`)
So what you have to do is either drop this index (with...
ALTER TABLE `batch` DROP INDEX `BatchID_UNIQUE`
... command, or just exclude this line from the table's definition (in CREATE TABLE).
All that said assuming that you really don't need your batch ids to be unique (in other words, there's no logical error in your INSERT statement. That seems to be the case, though: pair BatchID-Course_CourseID is already defined as unique (via PRIMARY KEY).
Try it this way. Drop your batch table and then run this sql. Rightly answered that you can not have two same vaues for a unique key. So I removed the unique key line as well.
CREATE TABLE IF NOT EXISTS `batch` (
`BatchID` int(11) NOT NULL,
`Course_CourseID` int(11) NOT NULL,
`NoOfStudents` int(11) DEFAULT NULL,
`ClassRoom` varchar(45) DEFAULT NULL,
`StartDate` varchar(45) DEFAULT NULL,
`Day` varchar(45) DEFAULT NULL,
`Time` varchar(45) DEFAULT NULL,
PRIMARY KEY (`BatchID`,`Course_CourseID`),
KEY `Course_CourseID` (`Course_CourseID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `batch` ADD CONSTRAINT `batch_ibfk_2` FOREIGN KEY (`Course_CourseID`)
REFERENCES `course` (`CourseId`) ON DELETE NO ACTION ON UPDATE NO ACTION;

mysql won't allow foreign key

Many people had this problem already, but there was no fitting solution in other posts.
I have two tables, one named "sales", the other named "host_flags". I would like to have a foreign key for host_flags.sales_id to sales.id, but mysql won't let me! I have primary indexes defined in each table, so I wonder why...
The host_flags table already has a foreign key on the column host_id, but even when I tried and created the foreign key for the sales id first, it wouldn't let me.
The tables look like:
CREATE TABLE `sales` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
CREATE TABLE `host_flags` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`host_id` int(11) DEFAULT NULL,
`sales_id` int(11) DEFAULT NULL,
`creation` datetime DEFAULT NULL,
`lastupdate` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `host_id6` (`host_id`),
CONSTRAINT `host_id6` FOREIGN KEY (`host_id`) REFERENCES `hosts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `hosts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`creation` datetime NOT NULL,
`lastupdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32225 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
I get this error message:
MySQL said: Can't create table 'primarydata.#sql-191_1' (errno: 150)
Thanks!
Charles
SOLUTION FOUND
All ints of the primary indexes have to be either signed or unsigned - not mixed.
Typically:
I like to declare the FK constraints outside of the table definition after all tables have been constructed.
ALTER TABLE `tbl`
ADD CONSTRAINT `constr`
FOREIGN KEY `fk_id` REFERENCES `ftbl`(`id`)
ON UPDATE CASCADE
ON DELETE CASCADE;
This way I can make sure the problem isn't something like the datatype of tbl.fk_id not being the same as the one of ftbl.id (including UNSIGNED as #Devart said). Or not having declared ftbl.id as unique. Regardless of the order of declaration of the tables.
After i do this i can integrate the constraint back into the table definition and take into account the order in which the tables need to be created to allow the constraint to be added.
You problem:
-- creating the sales table
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-- creating the host_flags table
`sales_id` int(11) DEFAULT NULL,
-- the sales.id is declared as unsigned
-- the host_flags.sales_id is declared signed
Additonally to Recursed's answer:
There is a requirement that foreign keys contstraints' names must be unique in database scope. Maybe changing the name will work?
There is also a huge thread on MySQL community forums about the problem containing several solutions for some specific situations.
Possible two errors:
Reference and referenced columns must have the same type - int(11) unsigned
Unknown referenced table hosts.

Help with my table structure

I'm trying to make an address book. And have made my tables like this:
CREATE TABLE `list_`.`contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` tinyint(11) NOT NULL,
`group` varchar(128) NOT NULL,
`first_name` varchar(128) NOT NULL,
`last_name` varchar(128) NOT NULL,
`address` varchar(128) NOT NULL,
`city` varchar(128) NOT NULL,
`state` varchar(2) NOT NULL,
`zip` int(5) NOT NULL,
`phone_number` varchar(16) NOT NULL,
`cell_number` varchar(16) NOT NULL,
`work_number` varchar(16) NOT NULL,
`fax_number` varchar(16) NOT NULL,
`email` varchar(128) NOT NULL,
`company` varchar(55) NOT NULL,
`title` varchar(56) NOT NULL,
`notes` text NOT NULL,
`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`user_id`),
KEY `user_id` (`user_id`),
KEY `group` (`group`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
CREATE TABLE `list_`.`groups` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` tinyint(11) NOT NULL,
`position` int(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL,
`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`user_id`),
KEY `user_id` (`user_id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 AUTO_INCREMENT=32 ;
My logic here is that I have all the contacts in the contacts table, from there I have a column called group that I use to filter the contacts into groups.
Then I have a table called groups that I'll use to keep track of what groups where created by a specific user and fill a with these groups so they can move the contacts around.
When a group is deleted I will throw back an error no letting it be deleted if the group contains contacts. I can probably query the contacts to see what group they belong to and if they belong to the group being deleted then I'll move them into a group called Uncategorized or something.
But if they choose to accept and delete ALL contacts within a group then go ahead and delete the group and all child rows that belong to that group.
I am having trouble creating my Foreing Keys in the contacts table. No matter what combination of index and keys I try I still can't make it work.
--
-- Constraints for table `contacts`
--
ALTER TABLE `list_`.`contacts`
ADD CONSTRAINT `contacts_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
ADD CONSTRAINT `contacts_ibfk_2` FOREIGN KEY (`group`) REFERENCES `groups` (`name`) ON UPDATE CASCADE;
--
-- Constraints for table `groups`
--
ALTER TABLE `list_`.`groups`
ADD CONSTRAINT `group_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
Also, can someone help me with the ON DELETE and ON UPDATE. To help me figure out how I can delete all child rows that reference the name column in groups
I do not think you should have MySQL do so much heavy lifting, specifically deleting a group if it is empty. Is there any specific reason to do this, i.e. can the group no longer be used if it is empty? You could probably achieve this with mysql triggers if you really wanted to.
As for preventing the deletion of a group that is simply done by the foriegn key on contacts that you already have on groups. However I highly recommend that you use ids rather than names for keys.
What you are saying seems to conflict, however: you want to prevent deletion of a group that has contacts, but you want all contacts in a group to be deleted when the group is deleted?